From 3f23278d7911847d825b61e0cd2ad87425d91deb Mon Sep 17 00:00:00 2001
From: pans <pans@454eff88-639b-444f-9e54-f578c98de674>
Date: 星期五, 30 十二月 2016 13:43:16 +0800
Subject: [PATCH]
---
RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp | 114 +++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 95 insertions(+), 19 deletions(-)
diff --git a/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp b/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp
index 0b38140..9ea1bba 100644
--- a/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp
+++ b/RtspFace/FFmpegRTSPServer/FFmpegH264Encoder.cpp
@@ -16,6 +16,13 @@
pthread_mutex_init(&outqueue_mutex,NULL);
}
+
+ FFmpegH264Encoder::~FFmpegH264Encoder()
+ {
+ pthread_mutex_init(&inqueue_mutex,NULL);
+ pthread_mutex_init(&outqueue_mutex,NULL);
+
+ }
void FFmpegH264Encoder::setCallbackFunctionFrameIsReady(std::function<void()> func)
{
@@ -45,13 +52,13 @@
pthread_mutex_unlock(&inqueue_mutex);
if(frame != NULL)
{
- WriteFrame(frame);
+ WriteFrameRGB(frame);
}
}
}
}
- void FFmpegH264Encoder::SetupCodec(const char *filename, int codec_id)
+ bool FFmpegH264Encoder::SetupCodec(const char *filename, int codec_id)
{
int ret;
m_sws_flags = SWS_BICUBIC;
@@ -60,14 +67,17 @@
avcodec_register_all();
av_register_all();
- avformat_alloc_output_context2(&m_oc, NULL, NULL, filename);
+ if (strlen(filename) == 0)
+ avformat_alloc_output_context2(&m_oc, NULL, "h264", filename);
+ else
+ avformat_alloc_output_context2(&m_oc, NULL, NULL, filename);
if (!m_oc) {
avformat_alloc_output_context2(&m_oc, NULL, "avi", filename);
}
if (!m_oc) {
- return;
+ return false;
}
m_fmt = m_oc->oformat;
@@ -79,13 +89,13 @@
m_video_codec = avcodec_find_encoder(m_fmt->video_codec);
if (!(m_video_codec)) {
- return;
+ return false;
}
st = avformat_new_stream(m_oc, m_video_codec);
if (!st) {
- return;
+ return false;
}
st->id = m_oc->nb_streams-1;
@@ -112,7 +122,7 @@
ret = avcodec_open2(c, m_video_codec, NULL);
if (ret < 0) {
- return;
+ return false;
}
//ret = avpicture_alloc(&m_dst_picture, c->pix_fmt, c->width, c->height);
@@ -126,7 +136,7 @@
ret = av_image_alloc(m_dst_picture->data, m_dst_picture->linesize, c->width, c->height, (AVPixelFormat)m_dst_picture->format, 32);
if (ret < 0) {
- return;
+ return false;
}
//ret = avpicture_alloc(&m_src_picture, AV_PIX_FMT_BGR24, c->width, c->height);
@@ -135,7 +145,7 @@
ret = av_image_alloc(m_src_picture->data, m_src_picture->linesize, c->width, c->height, AV_PIX_FMT_BGR24, 24);
if (ret < 0) {
- return;
+ return false;
}
bufferSize = ret;
@@ -145,27 +155,28 @@
if (!(m_fmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&m_oc->pb, filename, AVIO_FLAG_WRITE);
if (ret < 0) {
- return;
+ return false;
}
}
ret = avformat_write_header(m_oc, NULL);
if (ret < 0) {
- return;
+ return false;
}
sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR24,
c->width, c->height, AV_PIX_FMT_YUV420P,
SWS_BICUBIC, NULL, NULL, NULL);
if (!sws_ctx) {
- return;
+ return false;
}
+
+ return true;
}
- void FFmpegH264Encoder::WriteFrame(uint8_t * RGBFrame )
- {
-
+ bool FFmpegH264Encoder::WriteFrameRGB(uint8_t * RGBFrame )
+ {
memcpy(m_src_picture->data[0], RGBFrame, bufferSize);
sws_scale(sws_ctx,
@@ -182,7 +193,7 @@
ret = avcodec_encode_video2(m_c, &pkt, m_dst_picture, &got_packet);
if (ret < 0) {
- return;
+ return false;
}
if (!ret && got_packet && pkt.size)
@@ -215,10 +226,75 @@
m_frame_count++;
m_dst_picture->pts += av_rescale_q(1, m_video_st->codec->time_base, m_video_st->time_base);
- onFrame();
+ if (onFrame != nullptr)
+ onFrame();
+
+ return true;
+ }
+
+ void copyAVFrame(AVFrame* dest, AVFrame* src)
+ {
+ int height = dest->height;
+ int width = dest->width;
+
+ memcpy(dest->data[0], src->data[0], height * width); // Y
+ memcpy(dest->data[1], src->data[1], height * width / 4); // U
+ memcpy(dest->data[2], src->data[2], height * width / 4); // V
+ }
+
+ bool FFmpegH264Encoder::WriteFrameYUV420(AVFrame * YUVFrame)
+ {
+ copyAVFrame(m_dst_picture, YUVFrame);
+
+ AVPacket pkt = { 0 };
+ int got_packet;
+ av_init_packet(&pkt);
+
+ int ret = 0;
+
+ ret = avcodec_encode_video2(m_c, &pkt, m_dst_picture, &got_packet);
+
+ if (ret < 0) {
+ return false;
+ }
+
+ if (!ret && got_packet && pkt.size)
+ {
+ pkt.stream_index = m_video_st->index;
+ FrameStructure * frame = new FrameStructure();
+ frame->dataPointer = new uint8_t[pkt.size];
+ frame->dataSize = pkt.size-4;
+ frame->frameID = m_frame_count;
+
+ memcpy(frame->dataPointer,pkt.data+4,pkt.size-4);
+
+ pthread_mutex_lock(&outqueue_mutex);
+
+ if(outqueue.size()<30)
+ {
+ outqueue.push(frame);
+ }
+ else
+ {
+ delete frame;
+ }
+
+ pthread_mutex_unlock(&outqueue_mutex);
+
+ }
+
+ av_free_packet(&pkt);
+
+ m_frame_count++;
+ m_dst_picture->pts += av_rescale_q(1, m_video_st->codec->time_base, m_video_st->time_base);
+
+ if (onFrame != nullptr)
+ onFrame();
+
+ return true;
}
- void FFmpegH264Encoder::SetupVideo(std::string filename, int Width, int Height, int FPS, int GOB, int BitPerSecond)
+ bool FFmpegH264Encoder::SetupVideo(std::string filename, int Width, int Height, int FPS, int GOB, int BitPerSecond)
{
m_filename = filename;
m_AVIMOV_WIDTH=Width; //Movie width
@@ -227,7 +303,7 @@
m_AVIMOV_GOB=GOB; //I frames per no of P frames, see note below!
m_AVIMOV_BPS=BitPerSecond; //Bits per second, if this is too low then movie will become garbled
- SetupCodec(m_filename.c_str(),AV_CODEC_ID_H264);
+ return SetupCodec(m_filename.c_str(),AV_CODEC_ID_H264);
}
void FFmpegH264Encoder::CloseCodec()
--
Gitblit v1.8.0