Advertisement
Guest User

ffmpeg

a guest
May 7th, 2016
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.71 KB | None | 0 0
  1. void Controler::exportVideo( QList<QPair<quint64, quint64> >clips, QString fileName )
  2. {
  3.     OutputStream video_st = { 0 }, audio_st = { 0 };
  4.     AVOutputFormat *fmt;
  5.     AVFormatContext *oc;
  6.     AVFrame* frame;
  7.     AVCodec *audio_codec, *video_codec;
  8.     int ret;
  9.     int have_video = 0, have_audio = 0;
  10.     int encode_video = 0, encode_audio = 0;
  11.     AVDictionary *opt = NULL;
  12.  
  13.     /* Initialize libavcodec, and register all codecs and formats. */
  14.     av_register_all();
  15.     avcodec_register_all();
  16.  
  17.     /* allocate the output media context */
  18.     avformat_alloc_output_context2(&oc, NULL, NULL, fileName.toLatin1() );
  19.     if ( !oc )
  20.     {
  21.         qDebug() << "Could not deduce output format from file extension: using MPEG.";
  22.         avformat_alloc_output_context2( &oc, NULL, "mpeg", fileName.toLatin1() );
  23.         return;
  24.     }
  25.    
  26.     fmt = oc->oformat;
  27.    
  28.     /* Add the audio and video streams using the default format codecs
  29.      * and initialize the codecs. */
  30.     if ( fmt->video_codec != AV_CODEC_ID_NONE )
  31.     {
  32.         VE::add_stream( &video_st, oc, &video_codec, fmt->video_codec );
  33.         have_video = 1;
  34.         encode_video = 1;
  35.     }
  36.     if ( fmt->audio_codec != AV_CODEC_ID_NONE )
  37.     {
  38.         VE::add_stream( &audio_st, oc, &audio_codec, fmt->audio_codec );
  39.         have_audio = 1;
  40.         encode_audio = 1;
  41.     }
  42.  
  43.     video_st.st->codec->width = 1920;
  44.     video_st.st->codec->height = 1080;
  45.  
  46.     /* Now that all the parameters are set, we can open the audio and
  47.      * video codecs and allocate the necessary encode buffers. */
  48.     if ( have_video )
  49.         VE::open_video( oc, video_codec, &video_st, opt );
  50.  
  51.     if ( have_audio )
  52.         VE::open_audio( oc, audio_codec, &audio_st, opt );
  53.  
  54.  
  55.     av_dump_format( oc, 0, fileName.toLatin1(), 1 );
  56.  
  57.     /* open the output file, if needed */
  58.     if ( !( fmt->flags & AVFMT_NOFILE ) )
  59.     {
  60.         ret = avio_open( &oc->pb, fileName.toLatin1(), AVIO_FLAG_WRITE );
  61.         if (ret < 0)
  62.         {
  63.             qDebug() << "Could not open " << fileName.toLatin1(); //, av_err2str(ret));
  64.             return;
  65.         }
  66.     }
  67.  
  68.     frame = av_frame_alloc();
  69.     if ( !frame )
  70.     {
  71.         qDebug() <<  "Could not allocate video frame";
  72.         return;
  73.     }
  74.     frame->format = AV_PIX_FMT_YUV420P;
  75.     frame->width  = 1920;
  76.     frame->height = 1080;
  77.  
  78.     /* the image can be allocated by any means and av_image_alloc() is
  79.      * just the most convenient way if av_malloc() is to be used */
  80.     //ret = av_image_alloc( frame->data, frame->linesize, 1920, 1080, AV_PIX_FMT_YUV420P, 32 );
  81.     ret = av_image_alloc( video_st.frame->data, frame->linesize, 1920, 1080, AV_PIX_FMT_YUV420P, 32 );
  82.  
  83.     if ( ret < 0 )
  84.     {
  85.         qDebug() <<  "Could not allocate raw picture buffer";
  86.         return;
  87.     }
  88.  
  89.     /* Write the stream header, if any. */
  90.     ret = avformat_write_header( oc, &opt );
  91.     if (ret < 0)
  92.     {
  93.         qDebug() << "Error occurred when opening output file: "; //, av_err2str(ret));
  94.         return ;
  95.     }
  96.     quint64 totalSize = 0;
  97.     for (int clip = 0; clip < clips.size(); ++clip)
  98.     {
  99.         quint64 in = clips[clip].first;
  100.         quint64 out = clips[clip].second;
  101.         totalSize += ( out - in );
  102.     }
  103.  
  104.     QProgressDialog progress("Encoding video file", "Cancel", 0, totalSize, 0);
  105.     progress.setWindowModality(Qt::WindowModal);
  106.     progress.show();
  107.     quint64 progressValue = 0;
  108.     for ( int clip = 0; clip < clips.size(); ++clip )
  109.     {
  110.         quint64 in  = clips[clip].first;
  111.         quint64 out = clips[clip].second;
  112.         qDebug() << "-----";
  113.         qDebug() << clips[clip].first << " " << clips[clip].second;
  114.        
  115.         for ( quint64 frameId = in; frameId <= out; ++frameId )
  116.         {
  117.             progress.setValue( progressValue++ );
  118.             encode_video = !write_video_frame( oc, &video_st, frameId );
  119.             //encode_video = !write_video_frame( oc, &video_st, frame );
  120.             /*
  121.             if ( encode_video && ( !encode_audio || av_compare_ts( video_st.next_pts, video_st.st->codec->time_base, audio_st.next_pts, audio_st.st->codec->time_base ) <= 0) )
  122.             {
  123.                 encode_video = !write_video_frame(oc, &video_st, frameId );
  124.             }
  125.             else
  126.             {
  127.                 encode_audio = !write_audio_frame(oc, &audio_st, frameId );
  128.             }
  129.             */
  130.         }
  131.     }
  132.    
  133.    
  134.     av_write_trailer(oc);
  135.  
  136.     /* Close each codec. */
  137.     if (have_video)
  138.         VE::close_stream(oc, &video_st);
  139.     if (have_audio)
  140.         VE::close_stream(oc, &audio_st);
  141.  
  142.     if (!(fmt->flags & AVFMT_NOFILE))
  143.         /* Close the output file. */
  144.         avio_closep(&oc->pb);
  145.  
  146.     /* free the stream */
  147.     avformat_free_context(oc);
  148.  
  149.     return ;
  150. }
  151.  
  152. /*
  153.  * encode one video frame and send it to the muxer
  154.  * return 1 when encoding is finished, 0 otherwise
  155.  */
  156. int Controler::write_video_frame( AVFormatContext *oc, OutputStream *ost, quint64 frameId )
  157. {
  158.     int ret;
  159.     AVCodecContext *c;
  160.     int got_packet = 0;
  161.     AVPacket pkt = { 0 };
  162.  
  163.     c = ost->st->codec;
  164.    
  165.     AVFrame* frame = getVideoFrame( frameId, ost );
  166.  
  167.     av_init_packet( &pkt );
  168.  
  169.     /* encode the image */
  170.     ret = avcodec_encode_video2( c, &pkt, frame, &got_packet );
  171.     if ( ret < 0 )
  172.     {
  173.         qDebug() << "Error encoding video frame: "; //, av_err2str(ret));
  174.         exit(1);
  175.     }
  176.  
  177.     if (got_packet)
  178.     {
  179.         ret = VE::write_frame( oc, &c->time_base, ost->st, &pkt );
  180.     }
  181.     else
  182.     {
  183.         ret = 0;
  184.     }
  185.  
  186.     if ( ret < 0 )
  187.     {
  188.         qDebug() << "Error while writing video frame: "; //, av_err2str(ret));
  189.         exit(1);
  190.     }
  191.  
  192.     return (frame || got_packet) ? 0 : 1;
  193. }
  194.  
  195. int Controler::write_audio_frame(AVFormatContext *oc, OutputStream *ost, quint64 frameId )
  196. {
  197.     AVCodecContext *c;
  198.     AVPacket pkt = { 0 }; // data and size must be 0;
  199.     AVFrame *frame;
  200.     int ret;
  201.     int got_packet;
  202.     int dst_nb_samples;
  203.  
  204.     av_init_packet(&pkt);
  205.     c = ost->st->codec;
  206.  
  207.     frame = getAudioFrame( frameId, ost );
  208.  
  209.     if (frame)
  210.     {
  211.         /* convert samples from native format to destination codec format, using the resampler */
  212.             /* compute destination number of samples */
  213.             dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
  214.                                             c->sample_rate, c->sample_rate, AV_ROUND_UP);
  215.             av_assert0(dst_nb_samples == frame->nb_samples);
  216.  
  217.         /* when we pass a frame to the encoder, it may keep a reference to it
  218.          * internally;
  219.          * make sure we do not overwrite it here
  220.          */
  221.         ret = av_frame_make_writable(ost->frame);
  222.         if (ret < 0)
  223.             exit(1);
  224.  
  225.             /* convert to destination format */
  226.             ret = swr_convert(ost->swr_ctx,
  227.                               ost->frame->data, dst_nb_samples,
  228.                               (const uint8_t **)frame->data, frame->nb_samples);
  229.             if (ret < 0) {
  230.                 fprintf(stderr, "Error while converting\n");
  231.                 exit(1);
  232.             }
  233.             frame = ost->frame;
  234.         AVRational ar;
  235.         ar.num = 1;
  236.         ar.den = c->sample_rate;
  237.         frame->pts = av_rescale_q(ost->samples_count, ar, c->time_base);
  238.         ost->samples_count += dst_nb_samples;
  239.     }
  240.  
  241.     ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
  242.     if (ret < 0) {
  243.         qDebug() << "Error encoding audio frame: "; //, av_err2str(ret));
  244.         exit(1);
  245.     }
  246.  
  247.     if (got_packet) {
  248.         ret = VE::write_frame(oc, &c->time_base, ost->st, &pkt);
  249.         if (ret < 0) {
  250.             qDebug() << "Error while writing audio frame:"; //, av_err2str(ret));
  251.             exit(1);
  252.         }
  253.     }
  254.  
  255.     return ( frame || got_packet ) ? 0 : 1;
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement