Advertisement
Guest User

Untitled

a guest
Dec 17th, 2014
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.68 KB | None | 0 0
  1. #include "base/sys_string_conversions.h"
  2. #include "database/PA_SqliteHelper.h"
  3. #include "utils/PA_ProcessLock.h"
  4. #include "utils/PA_Helpers.h"
  5. #include "utils/PA_StringUtils.h"
  6. #include "MPEG2TSRecorderSink.h"
  7.  
  8.  
  9. MPEG2TSRecorderSink::MPEG2TSRecorderSink( void )
  10. {
  11.     Init();
  12. }
  13.  
  14. MPEG2TSRecorderSink::~MPEG2TSRecorderSink( void )
  15. {
  16.     if(IsOpened())
  17.         Close();
  18. }
  19.  
  20.  
  21. int MPEG2TSRecorderSink::Open( const EncoderConfig& encoder_config, const std::string& file_path )
  22. {
  23.     encoder_config_ = encoder_config;
  24.     file_path_ = file_path;
  25.     if(CreateContext() != PA_OK)
  26.     {
  27.         PA_WarnLog("CreateMp4Context failed!");
  28.         return PA_ERROR;
  29.     }
  30.  
  31.     return PA_OK;
  32. }
  33.  
  34.  
  35.  
  36. int MPEG2TSRecorderSink::CreateContext()
  37. {
  38.     avformat_alloc_output_context2(&output_ctx_, NULL, NULL, file_path_.c_str());
  39.     if (!output_ctx_)
  40.     {
  41.         PA_WarnLog("Could not deduce output format from file extension: using MPEG.\n");
  42.         avformat_alloc_output_context2(&output_ctx_, NULL, "mpegts", file_path_.c_str());
  43.     }
  44.  
  45.     if (!output_ctx_)
  46.     {
  47.         return PA_ERROR;
  48.     }
  49.  
  50.     output_ctx_->oformat->video_codec = AV_CODEC_ID_MPEG4;
  51.     output_ctx_->oformat->audio_codec = CODEC_ID_AAC;
  52.  
  53.     output_format_ = output_ctx_->oformat;
  54.  
  55.     if (avio_open(&output_ctx_->pb, file_path_.c_str(), AVIO_FLAG_READ_WRITE) < 0)
  56.     {
  57.         PA_WarnLog("avio_open failed \n");
  58.         goto label_error;
  59.     }
  60.  
  61.     if (output_format_->video_codec != CODEC_ID_NONE)
  62.     {
  63.         video_steam_ = AddVideoStream(output_ctx_,
  64.                                           output_format_->video_codec,
  65.                                           encoder_config_.video_bitrate_,
  66.                                           encoder_config_.width_,
  67.                                           encoder_config_.height_,
  68.                                           encoder_config_.frame_rate_);
  69.     }
  70.  
  71.     if (output_format_->audio_codec != CODEC_ID_NONE)
  72.     {
  73.         audio_stream_ = AddAudioStream(output_ctx_,
  74.                                        output_format_->audio_codec,
  75.                                        encoder_config_.audio_bitrate_,
  76.                                        encoder_config_.sample_rate_,
  77.                                        encoder_config_.channels_);
  78.     }
  79.  
  80.     if (NULL == video_steam_ || NULL == audio_stream_)
  81.     {
  82.         PA_WarnLog("NULL == video_steam_ || NULL == audio_stream_");
  83.         goto label_error;
  84.     }
  85.  
  86.     av_dump_format(output_ctx_, 0, file_path_.c_str(), 1);
  87.  
  88.     if (OpenVideo(output_ctx_, video_steam_) == -1)
  89.     {
  90.         PA_WarnLog("NULL == video_steam_ || NULL == audio_stream_");
  91.         goto label_error;
  92.     }
  93.  
  94.     if (OpenAudio(output_ctx_, audio_stream_))
  95.     {
  96.         PA_WarnLog("NULL == video_steam_ || NULL == audio_stream_");
  97.         goto label_error;
  98.     }
  99.  
  100.     if (avformat_write_header(output_ctx_, NULL))
  101.     {
  102.         PA_WarnLog("Call avformat_write_header function failed! \n");
  103.         goto label_error;
  104.     }
  105.  
  106.     return PA_OK;
  107.  
  108. label_error:
  109.  
  110.     if (NULL != video_steam_)
  111.     {
  112.         if(video_steam_->codec != NULL)
  113.         {
  114.             avcodec_close(video_steam_->codec);
  115.         }
  116.  
  117.         video_steam_ = NULL;
  118.     }
  119.  
  120.     if (NULL != audio_stream_)
  121.     {
  122.         if(audio_stream_->codec != NULL)
  123.         {
  124.             avcodec_close(audio_stream_->codec);
  125.         }
  126.         audio_stream_ = NULL;
  127.     }
  128.  
  129.     for(unsigned i = 0; i < output_ctx_->nb_streams; i++)
  130.     {  
  131.         av_freep(&output_ctx_->streams[i]->codec);  
  132.         av_freep(&output_ctx_->streams[i]);  
  133.     }  
  134.  
  135.     if(output_ctx_ != NULL)
  136.     {
  137.         if (output_ctx_->pb != NULL)
  138.         {
  139.             avio_close(output_ctx_->pb);
  140.         }
  141.         av_free(output_ctx_);
  142.         output_ctx_ = NULL;
  143.     }
  144.  
  145.     output_format_ = NULL;
  146.  
  147.     return PA_ERROR;
  148. }
  149.  
  150. AVStream* MPEG2TSRecorderSink::AddVideoStream(AVFormatContext *oc, enum AVCodecID codec_id , int bit_rate , int width , int height , int frame_rate)
  151. {
  152.     AVCodecContext *c;
  153.     AVStream *new_stream;
  154.     AVCodec *codec;
  155.    
  156.     new_stream = avformat_new_stream(oc, NULL);
  157.     if (!new_stream)
  158.     {
  159.         PA_WarnLog("Could not alloc stream\n");
  160.         return NULL;
  161.     }
  162.     new_stream->id = 0;
  163.    
  164.     c = new_stream->codec;
  165.    
  166.     /* find the video encoder */
  167.     codec = avcodec_find_encoder(codec_id);
  168.     if (!codec)
  169.     {
  170.         PA_WarnLog("add_video_stream_v codec not found\n");
  171.         av_freep(new_stream);
  172.         return NULL;
  173.     }
  174.     avcodec_get_context_defaults3(c, codec);
  175.    
  176.     c->codec_id = codec_id;
  177.     c->codec_type = AVMEDIA_TYPE_VIDEO;
  178.    
  179.     /* put sample parameters */
  180.     c->bit_rate = /*400000*/bit_rate;
  181.     /* resolution must be a multiple of two */
  182.     c->width = width;
  183.     c->height = height;
  184.    
  185.     /* time base: this is the fundamental unit of time (in seconds) in terms
  186.      of which frame timestamps are represented. for fixed-fps content,
  187.      timebase should be 1/framerate and timestamp increments should be
  188.      identically 1. */
  189.     c->time_base.den = frame_rate;
  190.     c->time_base.num = 1;
  191.     c->gop_size = 12; /* emit one intra frame every twelve frames at most */
  192.     c->pix_fmt = PIX_FMT_YUV420P;
  193.     if (c->codec_id == CODEC_ID_MPEG2VIDEO)
  194.     {
  195.         /* just for testing, we also add B frames */
  196.         c->max_b_frames = 2;
  197.     }
  198.     if (c->codec_id == CODEC_ID_MPEG1VIDEO){
  199.         /* Needed to avoid using macroblocks in which some coeffs overflow.
  200.          This does not happen with normal video, it just happens here as
  201.          the motion of the chroma plane does not match the luma plane. */
  202.         c->mb_decision=2;
  203.     }
  204.     // some formats want stream headers to be separate
  205.     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  206.         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  207.    
  208.     return new_stream;
  209. }
  210.  
  211. AVStream* MPEG2TSRecorderSink::AddAudioStream(AVFormatContext *oc, enum AVCodecID codec_id,
  212.                          int bit_rate, int sample_rate, int channels)
  213. {
  214.     AVCodecContext *c;
  215.     AVStream *new_stream;
  216.     //AVCodec *codec;
  217.    
  218.     new_stream = avformat_new_stream(oc, NULL);
  219.     if (!new_stream)
  220.     {
  221.         PA_WarnLog("Could not alloc stream\n");
  222.         return NULL;
  223.     }
  224.     new_stream->id = 1;
  225.    
  226.     c = new_stream->codec;
  227.    
  228.     /* find the video encoder */
  229.     /*  codec = avcodec_find_encoder(codec_id);
  230.      if (!codec)
  231.      {
  232.          fprintf(stderr, "add_video_stream_v codec not found\n");
  233.          exit(1);
  234.      }
  235.      avcodec_get_context_defaults3(c, codec);*/
  236.    
  237.     c->codec_id = codec_id;
  238.     c->codec_type = AVMEDIA_TYPE_AUDIO;
  239.    
  240.     /* put sample parameters */
  241.     c->sample_fmt = AV_SAMPLE_FMT_S16;
  242.     c->bit_rate = bit_rate;
  243.     c->sample_rate = sample_rate;
  244.     c->channels = channels;
  245.     c->profile = FF_PROFILE_AAC_LOW;
  246.     c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
  247.    
  248.     // some formats want stream headers to be separate
  249.     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  250.         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  251.    
  252.     return new_stream;
  253. }
  254.  
  255. int MPEG2TSRecorderSink::OpenAudio(AVFormatContext *oc, AVStream *st)
  256. {
  257.     AVCodecContext *audio_codec_context;
  258.     AVCodec *codec;
  259.  
  260.     audio_codec_context = st->codec;
  261.  
  262.     /* find the audio encoder */
  263.     codec = avcodec_find_encoder(audio_codec_context->codec_id);
  264.     if (!codec)
  265.     {
  266.         PA_WarnLog("codec not found\n");
  267.         return -1;
  268.     }
  269.  
  270.     /* open it */
  271.     if (avcodec_open2(audio_codec_context, codec, NULL) < 0)
  272.     {
  273.         PA_WarnLog("could not open codec\n");
  274.         return -1;
  275.     }
  276.  
  277.     return 0;
  278. }
  279.  
  280.  
  281. int MPEG2TSRecorderSink::OpenVideo(AVFormatContext *oc, AVStream *st)
  282. {
  283.     AVCodec *codec;
  284.     AVCodecContext *c;
  285.  
  286.     c = st->codec;
  287.  
  288.     /* find the video encoder */
  289.     codec = avcodec_find_encoder(c->codec_id);
  290.     if (!codec)
  291.     {
  292.         PA_WarnLog("codec not found\n");
  293.         return -1;
  294.     }
  295.  
  296.     /* open the codec */
  297.     if (avcodec_open2(c, codec, NULL) < 0)
  298.     {
  299.         PA_WarnLog("could not open codec\n");
  300.         return -1;
  301.     }
  302.     return 0;
  303. }
  304.  
  305. int MPEG2TSRecorderSink::WriteAudioFrame(char* data , int len , unsigned int timestemp)
  306. {
  307.     if(output_ctx_ == NULL)
  308.         return PA_ERROR;
  309.  
  310.     AVPacket pkt;
  311.     av_init_packet(&pkt);
  312.  
  313.     pkt.stream_index= 1;
  314.     pkt.data= (uint8_t *)data;
  315.     pkt.size = len;
  316.  
  317.     if (last_audio_timestamp_ == 0)
  318.     {
  319.         last_audio_timestamp_  = timestemp;
  320.         pkt.pts = 0;
  321.     }
  322.     else
  323.     {
  324.         pkt.pts = (timestemp - last_audio_timestamp_) / (av_q2d(audio_stream_->time_base)*1000);
  325.     }
  326.  
  327.     /* write the compressed frame in the media file */
  328.     if (av_write_frame(output_ctx_, &pkt) != 0)
  329.     {
  330.         PA_WarnLog("Error while writing audio frame\n");
  331.         return PA_ERROR;
  332.     }
  333.  
  334.     return PA_OK;
  335. }
  336.  
  337. int MPEG2TSRecorderSink::WriteVideoFrame(char* data , int len , bool keyframe , unsigned int timestemp)
  338. {
  339.     if(output_ctx_ == NULL)
  340.         return PA_ERROR;
  341.  
  342.     AVPacket pkt;
  343.     av_init_packet(&pkt);
  344.     pkt.stream_index = 0;
  345.  
  346.     if (keyframe)
  347.     {
  348.         pkt.flags |= AV_PKT_FLAG_KEY;
  349.     }
  350.  
  351.     pkt.data= (uint8_t *)data;
  352.     pkt.size = len;
  353.  
  354.     if (last_video_timestamp_  == 0)
  355.     {
  356.         last_video_timestamp_ = timestemp;
  357.         pkt.pts = 0;
  358.         video_timestamp_ = 0;
  359.     }
  360.     else
  361.     {
  362.         pkt.pts = (timestemp - last_video_timestamp_) / (av_q2d(video_steam_->time_base)*1000);
  363.         if (video_timestamp_ == pkt.pts)
  364.         {
  365.             pkt.pts += 1;
  366.         }
  367.         video_timestamp_ = pkt.pts;
  368.     }
  369.  
  370.     /* write the compressed frame in the media file */
  371.     if (av_write_frame(output_ctx_, &pkt) != 0)
  372.     {
  373.         PA_WarnLog("Error while writing audio frame\n");
  374.         return PA_ERROR;
  375.     }
  376.  
  377.     return PA_OK;
  378. }
  379.  
  380. void MPEG2TSRecorderSink::Init()
  381. {
  382.     output_format_ = NULL;
  383.     output_ctx_ = NULL;
  384.  
  385.     last_audio_timestamp_ = 0;
  386.     last_video_timestamp_ = 0;
  387.  
  388.      video_timestamp_ = 0;;
  389.  
  390.     audio_stream_ = NULL;
  391.     video_steam_ = NULL;
  392. }
  393.  
  394. void MPEG2TSRecorderSink::Finalize()
  395. {
  396.     if(output_ctx_ != NULL)
  397.     {
  398.         av_write_trailer(output_ctx_);
  399.     }
  400. }
  401.  
  402. void MPEG2TSRecorderSink::Close()
  403. {
  404.     if (NULL != video_steam_)
  405.     {
  406.         if(video_steam_->codec != NULL)
  407.         {
  408.             avcodec_close(video_steam_->codec);
  409.         }
  410.  
  411.         video_steam_ = NULL;
  412.     }
  413.  
  414.     if (NULL != audio_stream_)
  415.     {
  416.         if(audio_stream_->codec != NULL)
  417.         {
  418.             avcodec_close(audio_stream_->codec);
  419.         }
  420.         audio_stream_ = NULL;
  421.     }
  422.  
  423.  
  424.     if(output_ctx_ != NULL)
  425.     {
  426.         for(unsigned i = 0; i < output_ctx_->nb_streams; i++)
  427.         {  
  428.             av_freep(&output_ctx_->streams[i]->codec);  
  429.             av_freep(&output_ctx_->streams[i]);  
  430.         }  
  431.  
  432.         if (output_ctx_->pb != NULL)
  433.         {
  434.             avio_close(output_ctx_->pb);
  435.         }
  436.         av_free(output_ctx_);
  437.         output_ctx_ = NULL;
  438.     }
  439.  
  440.     output_format_ = NULL;
  441. }
  442.  
  443. bool MPEG2TSRecorderSink::IsOpened()
  444. {
  445.     return output_format_ != NULL;
  446. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement