xuxiuxi
2017-05-11 109ffe9a777658936a38d0c146579a67c60a0d17
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()