From 4ef430e946e717d72e923c4708a9120f94d55dbd Mon Sep 17 00:00:00 2001 From: houxiao <houxiao@454eff88-639b-444f-9e54-f578c98de674> Date: 星期三, 28 十二月 2016 09:35:14 +0800 Subject: [PATCH] test h264 encoder --- 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