add missing ffmpeg encoder flush, bdwrite leaks + fixes
authorGood Guy <good1.2guy@gmail.com>
Mon, 17 Aug 2015 17:08:50 +0000 (11:08 -0600)
committerGood Guy <good1.2guy@gmail.com>
Mon, 17 Aug 2015 17:08:50 +0000 (11:08 -0600)
cinelerra-5.0/cinelerra/bdcreate.C
cinelerra-5.0/cinelerra/bdwrite.C
cinelerra-5.0/cinelerra/ffmpeg.C
cinelerra-5.0/cinelerra/ffmpeg.h

index 50748492d76cb2aeb7adfefb0a2524e854567bf7..86a2a690dabd4919cd2e03582054b17c17556724 100644 (file)
@@ -139,13 +139,13 @@ int CreateBD_Thread::create_bd_jobs(ArrayList<BatchRenderJob*> *jobs,
        fprintf(fp,"#!/bin/bash -ex\n");
        fprintf(fp,"mkdir -p $1/udfs\n");
        fprintf(fp,"sz=`du -sb $1/bd.m2ts | sed -e 's/[ \t].*//'`\n");
-       fprintf(fp,"blks=$((sz/2048 + 512))\n");
+       fprintf(fp,"blks=$((sz/2048 + 4096))\n");
        fprintf(fp,"mkudffs $1/bd.udfs $blks\n");
        fprintf(fp,"mount -o loop $1/bd.udfs $1/udfs\n");
        fprintf(fp,"%s/bdwrite $1/udfs $1/bd.m2ts\n",exe_path);
        fprintf(fp,"umount $1/udfs\n");
        fprintf(fp,"echo To burn bluray, load blank media and run:\n");
-       fprintf(fp,"echo dd if=$1/bd.udfs 0f=/dev/bd bs=2048000\n");
+       fprintf(fp,"echo dd if=$1/bd.udfs of=/dev/bd bs=2048000\n");
        fprintf(fp,"\n");
        fclose(fp);
 
index 3ac4b0ff503700947c29f116a4c2391e747a9536..ad3311692ca7767ed80eb4ba6350b6660cfa60d7 100644 (file)
@@ -719,7 +719,9 @@ public:
   int write();
 
   mpls_pi() {}
-  ~mpls_pi() {}
+  ~mpls_pi() {
+    clip.remove_all_objects();
+  }
 };
 
 class _mpls_plm {
@@ -1168,7 +1170,10 @@ public:
     strcpy(filename, fn);
     brk = 0;  pidx = 0;  pgm_pid = -1;  still = 0;
   }
-  ~media_info() { streams.remove_all_objects(); }
+  ~media_info() {
+    streams.remove_all_objects();
+    programs.remove_all_objects();
+  }
 
   int scan();
   int scan(AVFormatContext *fmt_ctx);
@@ -2458,13 +2463,10 @@ int media_info::scan()
   av_dict_set(&fopts, "threads", "auto", 0);
   int ret = avformat_open_input(&fmt_ctx, filename, NULL, &fopts);
   av_dict_free(&fopts);
+  if( ret < 0 ) return ret;
+  ret = avformat_find_stream_info(fmt_ctx, NULL);
 
-  if( ret >= 0 )
-    ret = avformat_find_stream_info(fmt_ctx, NULL);
-
-  if( ret >= 0 ) {
-    bit_rate = fmt_ctx->bit_rate;
-  }
+  bit_rate = fmt_ctx->bit_rate;
 
   int ep_pid = -1;
   for( int i=0; ret>=0 && i<(int)fmt_ctx->nb_streams; ++i ) {
@@ -2519,8 +2521,22 @@ int media_info::scan()
     pgm->ep_pid = ep_pid;
     pgm->pmt_pid = 0x1000;
     pgm->pcr_pid = 0x100;
-    for( int jj=0; jj<streams.size(); ++jj )
+    pgm->duration = 0;
+    for( int jj=0; jj<streams.size(); ++jj ) {
+      AVStream *st = fmt_ctx->streams[jj];
+      AVMediaType type = st->codec->codec_type;
+      switch( type ) {
+      case AVMEDIA_TYPE_VIDEO:
+      case AVMEDIA_TYPE_AUDIO:
+        break;
+      default:
+        continue;
+      }
       pgm->strm_idx.append(jj);
+      if( pgm->duration < st->duration )
+        pgm->duration = av_rescale_q(st->duration, st->time_base, clk45k);
+    }
+    programs.append(pgm);
   }
 
   for( int ii=0; ii<npgm; ++ii ) {
@@ -2565,8 +2581,9 @@ int media_info::scan()
   if( ret >= 0 )
     ret = scan(fmt_ctx);
 
-  if( fmt_ctx )
-    avformat_close_input(&fmt_ctx);
+  for( int i=0; i<(int)fmt_ctx->nb_streams; ++i )
+    avcodec_close(fmt_ctx->streams[i]->codec);
+  avformat_close_input(&fmt_ctx);
 
   return ret;
 }
index 68ff296d0013581d695f2bb713d75d4554f764eb..decb3d0078260bf419a7469a16e00d62def79f89 100644 (file)
@@ -409,6 +409,29 @@ int FFStream::read_frame(AVFrame *frame)
        return ret;
 }
 
+int FFStream::write_packet(FFPacket &pkt)
+{
+       bs_filter(pkt);
+       av_packet_rescale_ts(pkt, st->codec->time_base, st->time_base);
+       pkt->stream_index = st->index;
+       return av_interleaved_write_frame(ffmpeg->fmt_ctx, pkt);
+}
+
+int FFStream::flush()
+{
+       int ret = 0;
+       while( ret >= 0 ) {
+               FFPacket pkt;
+               int got_packet = 0;
+               ret = encode_frame(pkt, 0, got_packet);
+               if( ret < 0 || !got_packet ) break;
+               ret = write_packet(pkt);
+       }
+       if( ret < 0 )
+               ff_err(ret, "FFStream::flush");
+       return ret >= 0 ? 0 : 1;
+}
+
 FFAudioStream::FFAudioStream(FFMPEG *ffmpeg, AVStream *strm, int idx)
  : FFStream(ffmpeg, strm, idx)
 {
@@ -596,6 +619,16 @@ int FFAudioStream::encode(double **samples, int len)
        return ret >= 0 ? 0 : 1;
 }
 
+int FFAudioStream::encode_frame(FFPacket &pkt, AVFrame *frame, int &got_packet)
+{
+       int ret = avcodec_encode_audio2(st->codec, pkt, frame, &got_packet);
+       if( ret < 0 ) {
+               ff_err(ret, "FFAudioStream::encode_frame: encode audio failed\n");
+               return -1;
+       }
+       return ret;
+}
+
 FFVideoStream::FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx)
  : FFStream(ffmpeg, strm, idx)
 {
@@ -702,6 +735,15 @@ int FFVideoStream::encode(VFrame *vframe)
        return ret >= 0 ? 0 : 1;
 }
 
+int FFVideoStream::encode_frame(FFPacket &pkt, AVFrame *frame, int &got_packet)
+{
+       int ret = avcodec_encode_video2(st->codec, pkt, frame, &got_packet);
+       if( ret < 0 ) {
+               ff_err(ret, "FFVideoStream::encode_frame: encode video failed\n");
+               return -1;
+       }
+       return ret;
+}
 
 PixelFormat FFVideoStream::color_model_to_pix_fmt(int color_model)
 {
@@ -1776,19 +1818,15 @@ void FFMPEG::flow_ctl()
 int FFMPEG::mux_audio(FFrame *frm)
 {
        FFPacket pkt;
-       AVStream *st = frm->fst->st;
-       AVCodecContext *ctx = st->codec;
+       FFStream *fst = frm->fst;
+       AVCodecContext *ctx = fst->st->codec;
        AVFrame *frame = *frm;
        AVRational tick_rate = {1, ctx->sample_rate};
        frame->pts = av_rescale_q(frm->position, tick_rate, ctx->time_base);
        int got_packet = 0;
-       int ret = avcodec_encode_audio2(ctx, pkt, frame, &got_packet);
-       if( ret >= 0 && got_packet ) {
-               frm->fst->bs_filter(pkt);
-               av_packet_rescale_ts(pkt, ctx->time_base, st->time_base);
-               pkt->stream_index = st->index;
-               ret = av_interleaved_write_frame(fmt_ctx, pkt);
-       }
+       int ret = fst->encode_frame(pkt, frame, got_packet);
+       if( ret >= 0 && got_packet )
+               ret = fst->write_packet(pkt);
        if( ret < 0 )
                ff_err(ret, "FFMPEG::mux_audio");
        return ret >= 0 ? 0 : 1;
@@ -1797,14 +1835,14 @@ int FFMPEG::mux_audio(FFrame *frm)
 int FFMPEG::mux_video(FFrame *frm)
 {
        FFPacket pkt;
-       AVStream *st = frm->fst->st;
+       FFStream *fst = frm->fst;
        AVFrame *frame = *frm;
        frame->pts = frm->position;
        int ret = 1, got_packet = 0;
        if( fmt_ctx->oformat->flags & AVFMT_RAWPICTURE ) {
                /* a hack to avoid data copy with some raw video muxers */
                pkt->flags |= AV_PKT_FLAG_KEY;
-               pkt->stream_index  = st->index;
+               pkt->stream_index  = fst->st->index;
                AVPicture *picture = (AVPicture *)frame;
                pkt->data = (uint8_t *)picture;
                pkt->size = sizeof(AVPicture);
@@ -1812,13 +1850,9 @@ int FFMPEG::mux_video(FFrame *frm)
                got_packet = 1;
        }
        else
-               ret = avcodec_encode_video2(st->codec, pkt, frame, &got_packet);
-       if( ret >= 0 && got_packet ) {
-               frm->fst->bs_filter(pkt);
-               av_packet_rescale_ts(pkt, st->codec->time_base, st->time_base);
-               pkt->stream_index = st->index;
-               ret = av_interleaved_write_frame(fmt_ctx, pkt);
-       }
+               ret = fst->encode_frame(pkt, frame, got_packet);
+       if( ret >= 0 && got_packet )
+               ret = fst->write_packet(pkt);
        if( ret < 0 )
                ff_err(ret, "FFMPEG::mux_video");
        return ret >= 0 ? 0 : 1;
@@ -1866,6 +1900,10 @@ void FFMPEG::run()
                if( !done ) mux();
        }
        mux();
+       for( int i=0; i<ffaudio.size(); ++i )
+               ffaudio[i]->flush();
+       for( int i=0; i<ffvideo.size(); ++i )
+               ffvideo[i]->flush();
 }
 
 
index 28b191489c950117049afe3c0ba23ddc2009a7fe..931e9c4d8902990747613a304a56dca04fbc516f 100644 (file)
@@ -77,9 +77,12 @@ public:
        virtual int encode_activate();
        virtual int decode_activate();
        int read_packet();
+       int write_packet(FFPacket &pkt);
+       int flush();
        int decode(AVFrame *frame);
 
        virtual int decode_frame(AVFrame *frame, int &got_frame) = 0;
+       virtual int encode_frame(FFPacket &pkt, AVFrame *frame, int &got_frame) = 0;
        virtual int init_frame(AVFrame *frame) = 0;
        virtual int create_filter(const char *filter_spec,
                AVCodecContext *src_ctx, AVCodecContext *sink_ctx) = 0;
@@ -153,6 +156,7 @@ public:
        virtual ~FFAudioStream();
        int load_history(uint8_t **data, int len);
        int decode_frame(AVFrame *frame, int &got_frame);
+       int encode_frame(FFPacket &pkt, AVFrame *frame, int &got_frame);
        int create_filter(const char *filter_spec,
                AVCodecContext *src_ctx, AVCodecContext *sink_ctx);
 
@@ -183,6 +187,7 @@ public:
        FFVideoStream(FFMPEG *ffmpeg, AVStream *strm, int idx);
        virtual ~FFVideoStream();
        int decode_frame(AVFrame *frame, int &got_frame);
+       int encode_frame(FFPacket &pkt, AVFrame *frame, int &got_frame);
        int create_filter(const char *filter_spec,
                AVCodecContext *src_ctx, AVCodecContext *sink_ctx);