render config sample/pixel fmt, piped files, ffmpeg raw yuv/rgb
[goodguy/history.git] / cinelerra-5.1 / cinelerra / ffmpeg.C
index fc3726e222487fece097b629c66b06fb412edac7..b0ba1c904be8f03b1543355c2d19305e0fa7fdd0 100644 (file)
@@ -7,6 +7,8 @@
 #include <stdarg.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <ctype.h>
+
 // work arounds (centos)
 #include <lzma.h>
 #ifndef INT64_MAX
 #include "asset.h"
 #include "bccmodels.h"
 #include "bchash.h"
-#include "fileffmpeg.h"
+#include "edl.h"
+#include "edlsession.h"
 #include "file.h"
+#include "fileffmpeg.h"
+#include "filesystem.h"
 #include "ffmpeg.h"
 #include "indexfile.h"
 #include "interlacemodes.h"
@@ -251,6 +256,10 @@ FFStream::FFStream(FFMPEG *ffmpeg, AVStream *st, int fidx)
        need_packet = 1;
        frame = fframe = 0;
        bsfc = 0;
+       stats_fp = 0;
+       stats_filename = 0;
+       stats_in = 0;
+       pass = 0;
 }
 
 FFStream::~FFStream()
@@ -264,6 +273,9 @@ FFStream::~FFStream()
        if( frame ) av_frame_free(&frame);
        if( fframe ) av_frame_free(&fframe);
        delete frm_lock;
+       if( stats_fp ) fclose(stats_fp);
+       if( stats_in ) av_freep(&stats_in);
+       delete [] stats_filename;
 }
 
 void FFStream::ff_lock(const char *cp)
@@ -475,6 +487,10 @@ int FFStream::encode_frame(AVFrame *frame)
                ret = write_packet(opkt);
                if( ret < 0 ) break;
                ++pkts;
+               if( frame && stats_fp ) {
+                       ret = write_stats_file();
+                       if( ret < 0 ) break;
+               }
        }
        ff_err(ret, "FFStream::encode_frame: encode failed\n");
        return -1;
@@ -485,11 +501,75 @@ int FFStream::flush()
        if( writing < 0 )
                return -1;
        int ret = encode_frame(0);
+       if( ret >= 0 && stats_fp ) {
+               ret = write_stats_file();
+               close_stats_file();
+       }
        if( ret < 0 )
                ff_err(ret, "FFStream::flush");
        return ret >= 0 ? 0 : 1;
 }
 
+
+int FFStream::open_stats_file()
+{
+       stats_fp = fopen(stats_filename,"w");
+       return stats_fp ? 0 : AVERROR(errno);
+}
+
+int FFStream::close_stats_file()
+{
+       if( stats_fp ) {
+               fclose(stats_fp);  stats_fp = 0;
+       }
+       return 0;
+}
+
+int FFStream::read_stats_file()
+{
+       int64_t len = 0;  struct stat stats_st;
+       int fd = open(stats_filename, O_RDONLY);
+       int ret = fd >= 0 ? 0: ENOENT;
+       if( !ret && fstat(fd, &stats_st) )
+               ret = EINVAL;
+       if( !ret ) {
+               len = stats_st.st_size;
+               stats_in = (char *)av_malloc(len+1);
+               if( !stats_in )
+                       ret = ENOMEM;
+       }
+       if( !ret && read(fd, stats_in, len+1) != len )
+               ret = EIO;
+       if( !ret ) {
+               stats_in[len] = 0;
+               avctx->stats_in = stats_in;
+       }
+       if( fd >= 0 )
+               close(fd);
+       return !ret ? 0 : AVERROR(ret);
+}
+
+int FFStream::write_stats_file()
+{
+       int ret = 0;
+       if( avctx->stats_out && (ret=strlen(avctx->stats_out)) > 0 ) {
+               int len = fwrite(avctx->stats_out, 1, ret, stats_fp);
+               if( ret != len )
+                       ff_err(ret = AVERROR(errno), "FFStream::write_stats_file");
+       }
+       return ret;
+}
+
+int FFStream::init_stats_file()
+{
+       int ret = 0;
+       if( (pass & 2) && (ret = read_stats_file()) < 0 )
+               ff_err(ret, "stat file read: %s", stats_filename);
+       if( (pass & 1) && (ret=open_stats_file()) < 0 )
+               ff_err(ret, "stat file open: %s", stats_filename);
+       return ret >= 0 ? 0 : ret;
+}
+
 int FFStream::seek(int64_t no, double rate)
 {
 // default ffmpeg native seek
@@ -970,6 +1050,7 @@ AVPixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model)
        case BC_RGB161616:      return AV_PIX_FMT_RGB48LE;
        case BC_RGBA16161616:   return AV_PIX_FMT_RGBA64LE;
        case BC_AYUV16161616:   return AV_PIX_FMT_AYUV64LE;
+       case BC_GBRP:           return AV_PIX_FMT_GBRP;
        default: break;
        }
 
@@ -995,6 +1076,7 @@ int FFVideoConvert::pix_fmt_to_color_model(AVPixelFormat pix_fmt)
        case AV_PIX_FMT_RGB48LE:        return BC_RGB161616;
        case AV_PIX_FMT_RGBA64LE:       return BC_RGBA16161616;
        case AV_PIX_FMT_AYUV64LE:       return BC_AYUV16161616;
+       case AV_PIX_FMT_GBRP:           return BC_GBRP;
        default: break;
        }
 
@@ -1305,6 +1387,37 @@ AVRational FFMPEG::to_time_base(int sample_rate)
        return (AVRational){1, sample_rate};
 }
 
+int FFMPEG::get_fmt_score(AVSampleFormat dst_fmt, AVSampleFormat src_fmt)
+{
+       int score = 0;
+       int dst_planar = av_sample_fmt_is_planar(dst_fmt);
+       int src_planar = av_sample_fmt_is_planar(src_fmt);
+       if( dst_planar != src_planar ) ++score;
+       int dst_bytes = av_get_bytes_per_sample(dst_fmt);
+       int src_bytes = av_get_bytes_per_sample(src_fmt);
+       score += (src_bytes > dst_bytes ? 100 : -10) * (src_bytes - dst_bytes);
+       int src_packed = av_get_packed_sample_fmt(src_fmt);
+       int dst_packed = av_get_packed_sample_fmt(dst_fmt);
+       if( dst_packed == AV_SAMPLE_FMT_S32 && src_packed == AV_SAMPLE_FMT_FLT ) score += 20;
+       if( dst_packed == AV_SAMPLE_FMT_FLT && src_packed == AV_SAMPLE_FMT_S32 ) score += 2;
+       return score;
+}
+
+AVSampleFormat FFMPEG::find_best_sample_fmt_of_list(
+               const AVSampleFormat *sample_fmts, AVSampleFormat src_fmt)
+{
+       AVSampleFormat best = AV_SAMPLE_FMT_NONE;
+       int best_score = get_fmt_score(best, src_fmt);
+       for( int i=0; sample_fmts[i] >= 0; ++i ) {
+               AVSampleFormat sample_fmt = sample_fmts[i];
+               int score = get_fmt_score(sample_fmt, src_fmt);
+               if( score >= best_score ) continue;
+               best = sample_fmt;  best_score = score;
+       }
+       return best;
+}
+
+
 void FFMPEG::set_option_path(char *path, const char *fmt, ...)
 {
        char *ep = path + BCTEXTLEN-1;
@@ -1401,10 +1514,10 @@ int FFMPEG::get_file_format()
        return ret;
 }
 
-int FFMPEG::scan_option_line(char *cp, char *tag, char *val)
+int FFMPEG::scan_option_line(const char *cp, char *tag, char *val)
 {
        while( *cp == ' ' || *cp == '\t' ) ++cp;
-       char *bp = cp;
+       const char *bp = cp;
        while( *cp && *cp != ' ' && *cp != '\t' && *cp != '=' && *cp != '\n' ) ++cp;
        int len = cp - bp;
        if( !len || len > BCSTRLEN-1 ) return 1;
@@ -1422,6 +1535,123 @@ int FFMPEG::scan_option_line(char *cp, char *tag, char *val)
        return 0;
 }
 
+int FFMPEG::can_render(const char *fformat, const char *type)
+{
+       FileSystem fs;
+       char option_path[BCTEXTLEN];
+       FFMPEG::set_option_path(option_path, type);
+       fs.update(option_path);
+       int total_files = fs.total_files();
+       for( int i=0; i<total_files; ++i ) {
+               const char *name = fs.get_entry(i)->get_name();
+               const char *ext = strrchr(name,'.');
+               if( !ext ) continue;
+               if( !strcmp(fformat, ++ext) ) return 1;
+       }
+       return 0;
+}
+
+int FFMPEG::get_ff_option(const char *nm, const char *options, char *value)
+{
+        for( const char *cp=options; *cp!=0; ) {
+                char line[BCTEXTLEN], *bp = line, *ep = bp+sizeof(line)-1;
+                while( bp < ep && *cp && *cp!='\n' ) *bp++ = *cp++;
+                if( *cp ) ++cp;
+                *bp = 0;
+                if( !line[0] || line[0] == '#' || line[0] == ';' ) continue;
+                char key[BCSTRLEN], val[BCTEXTLEN];
+                if( FFMPEG::scan_option_line(line, key, val) ) continue;
+                if( !strcmp(key, nm) ) {
+                        strncpy(value, val, BCSTRLEN);
+                        return 0;
+                }
+        }
+        return 1;
+}
+
+void FFMPEG::scan_audio_options(Asset *asset, EDL *edl)
+{
+       char cin_sample_fmt[BCSTRLEN];
+       int cin_fmt = AV_SAMPLE_FMT_NONE;
+       const char *options = asset->ff_audio_options;
+       if( !get_ff_option("cin_sample_fmt", options, cin_sample_fmt) )
+               cin_fmt = (int)av_get_sample_fmt(cin_sample_fmt);
+       if( cin_fmt < 0 ) {
+               char audio_codec[BCSTRLEN]; audio_codec[0] = 0;
+               AVCodec *av_codec = !FFMPEG::get_codec(audio_codec, "audio", asset->acodec) ?
+                       avcodec_find_encoder_by_name(audio_codec) : 0;
+               if( av_codec && av_codec->sample_fmts )
+                       cin_fmt = find_best_sample_fmt_of_list(av_codec->sample_fmts, AV_SAMPLE_FMT_FLT);
+       }
+       if( cin_fmt < 0 ) cin_fmt = AV_SAMPLE_FMT_S16;
+       const char *name = av_get_sample_fmt_name((AVSampleFormat)cin_fmt);
+       if( !name ) name = _("None");
+       strcpy(asset->ff_sample_format, name);
+
+       char value[BCSTRLEN];
+       if( !get_ff_option("cin_bitrate", options, value) )
+               asset->ff_audio_bitrate = atoi(value);
+       if( !get_ff_option("cin_quality", options, value) )
+               asset->ff_audio_quality = atoi(value);
+}
+
+void FFMPEG::load_audio_options(Asset *asset, EDL *edl)
+{
+       char options_path[BCTEXTLEN];
+       set_option_path(options_path, "audio/%s", asset->acodec);
+        if( !load_options(options_path,
+                       asset->ff_audio_options,
+                       sizeof(asset->ff_audio_options)) )
+               scan_audio_options(asset, edl);
+}
+
+void FFMPEG::scan_video_options(Asset *asset, EDL *edl)
+{
+       char cin_pix_fmt[BCSTRLEN];
+       int cin_fmt = AV_PIX_FMT_NONE;
+       const char *options = asset->ff_video_options;
+       if( !get_ff_option("cin_pix_fmt", options, cin_pix_fmt) )
+                       cin_fmt = (int)av_get_pix_fmt(cin_pix_fmt);
+       if( cin_fmt < 0 ) {
+               char video_codec[BCSTRLEN];  video_codec[0] = 0;
+               AVCodec *av_codec = !get_codec(video_codec, "video", asset->vcodec) ?
+                       avcodec_find_encoder_by_name(video_codec) : 0;
+               if( av_codec && av_codec->pix_fmts ) {
+                       if( edl ) {
+                               int color_model = edl->session->color_model;
+                               int max_bits = BC_CModels::calculate_pixelsize(color_model) * 8;
+                               max_bits /= BC_CModels::components(color_model);
+                               cin_fmt = avcodec_find_best_pix_fmt_of_list(av_codec->pix_fmts,
+                                       (BC_CModels::is_yuv(color_model) ?
+                                               (max_bits > 8 ? AV_PIX_FMT_AYUV64LE : AV_PIX_FMT_YUV444P) :
+                                               (max_bits > 8 ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB24)), 0, 0);
+                       }
+                       else
+                               cin_fmt = av_codec->pix_fmts[0];
+               }
+       }
+       if( cin_fmt < 0 ) cin_fmt = AV_PIX_FMT_YUV420P;
+       const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((AVPixelFormat)cin_fmt);
+       const char *name = desc ? desc->name : _("None");
+       strcpy(asset->ff_pixel_format, name);
+
+       char value[BCSTRLEN];
+       if( !get_ff_option("cin_bitrate", options, value) )
+               asset->ff_video_bitrate = atoi(value);
+       if( !get_ff_option("cin_quality", options, value) )
+               asset->ff_video_quality = atoi(value);
+}
+
+void FFMPEG::load_video_options(Asset *asset, EDL *edl)
+{
+       char options_path[BCTEXTLEN];
+       set_option_path(options_path, "video/%s", asset->vcodec);
+        if( !load_options(options_path,
+                       asset->ff_video_options,
+                       sizeof(asset->ff_video_options)) )
+               scan_video_options(asset, edl);
+}
+
 int FFMPEG::load_defaults(const char *path, const char *type,
                 char *codec, char *codec_options, int len)
 {
@@ -1442,18 +1672,24 @@ int FFMPEG::load_defaults(const char *path, const char *type,
        return load_options(default_file, codec_options, len);
 }
 
-void FFMPEG::set_asset_format(Asset *asset, const char *text)
+void FFMPEG::set_asset_format(Asset *asset, EDL *edl, const char *text)
 {
        if( asset->format != FILE_FFMPEG ) return;
        if( text != asset->fformat )
                strcpy(asset->fformat, text);
-       if( !asset->ff_audio_options[0] ) {
-               asset->audio_data = !load_defaults("audio", text, asset->acodec,
-                       asset->ff_audio_options, sizeof(asset->ff_audio_options));
+       if( asset->audio_data && !asset->ff_audio_options[0] ) {
+               if( !load_defaults("audio", text, asset->acodec,
+                               asset->ff_audio_options, sizeof(asset->ff_audio_options)) )
+                       scan_audio_options(asset, edl);
+               else
+                       asset->audio_data = 0;
        }
-       if( !asset->ff_video_options[0] ) {
-               asset->video_data = !load_defaults("video", text, asset->vcodec,
-                       asset->ff_video_options, sizeof(asset->ff_video_options));
+       if( asset->video_data && !asset->ff_video_options[0] ) {
+               if( !load_defaults("video", text, asset->vcodec,
+                               asset->ff_video_options, sizeof(asset->ff_video_options)) )
+                       scan_video_options(asset, edl);
+               else
+                       asset->video_data = 0;
        }
 }
 
@@ -1465,19 +1701,18 @@ int FFMPEG::get_encoder(const char *options,
                eprintf(_("options open failed %s\n"),options);
                return 1;
        }
-       if( get_encoder(fp, format, codec, bsfilter) )
+       char line[BCTEXTLEN];
+       if( !fgets(line, sizeof(line), fp) ||
+           scan_encoder(line, format, codec, bsfilter) )
                eprintf(_("format/codec not found %s\n"), options);
        fclose(fp);
        return 0;
 }
 
-int FFMPEG::get_encoder(FILE *fp,
+int FFMPEG::scan_encoder(const char *line,
                char *format, char *codec, char *bsfilter)
 {
        format[0] = codec[0] = bsfilter[0] = 0;
-       char line[BCTEXTLEN];
-       if( !fgets(line, sizeof(line), fp) ) return 1;
-       line[sizeof(line)-1] = 0;
        if( scan_option_line(line, format, codec) ) return 1;
        char *cp = codec;
        while( *cp && *cp != '|' ) ++cp;
@@ -1743,8 +1978,11 @@ int FFMPEG::open_decoder()
                        estimated = 1;
                }
        }
-       if( estimated )
+       static int notified = 0;
+       if( !notified && estimated ) {
+               notified = 1;
                printf("FFMPEG::open_decoder: some stream times estimated\n");
+       }
 
        ff_lock("FFMPEG::open_decoder");
        int ret = 0, bad_time = 0;
@@ -1808,14 +2046,18 @@ int FFMPEG::open_decoder()
 
 int FFMPEG::init_encoder(const char *filename)
 {
-       int fd = ::open(filename,O_WRONLY);
-       if( fd < 0 ) fd = open(filename,O_WRONLY+O_CREAT,0666);
-       if( fd < 0 ) {
+// try access first for named pipes
+       int ret = access(filename, W_OK);
+       if( ret ) {
+               int fd = ::open(filename,O_WRONLY);
+               if( fd < 0 ) fd = open(filename,O_WRONLY+O_CREAT,0666);
+               if( fd >= 0 ) { close(fd);  ret = 0; }
+       }
+       if( ret ) {
                eprintf(_("bad file path: %s\n"), filename);
                return 1;
        }
-       ::close(fd);
-       int ret = get_file_format();
+       ret = get_file_format();
        if( ret > 0 ) {
                eprintf(_("bad file format: %s\n"), filename);
                return 1;
@@ -1910,6 +2152,19 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                                sprintf(arg, "%d", asset->ff_audio_bitrate);
                                av_dict_set(&sopts, "b", arg, 0);
                        }
+                       else if( asset->ff_audio_quality >= 0 ) {
+                               ctx->global_quality = asset->ff_audio_quality * FF_QP2LAMBDA;
+                               ctx->qmin    = ctx->qmax =  asset->ff_audio_quality;
+                               ctx->mb_lmin = ctx->qmin * FF_QP2LAMBDA;
+                               ctx->mb_lmax = ctx->qmax * FF_QP2LAMBDA;
+                               ctx->flags |= CODEC_FLAG_QSCALE;
+                               char arg[BCSTRLEN];
+                               av_dict_set(&sopts, "flags", "+qscale", 0);
+                               sprintf(arg, "%d", asset->ff_audio_quality);
+                               av_dict_set(&sopts, "qscale", arg, 0);
+                               sprintf(arg, "%d", ctx->global_quality);
+                               av_dict_set(&sopts, "global_quality", arg, 0);
+                       }
                        int aidx = ffaudio.size();
                        int fidx = aidx + ffvideo.size();
                        FFAudioStream *aud = new FFAudioStream(this, st, aidx, fidx);
@@ -1926,7 +2181,10 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                                break;
                        }
                        ctx->time_base = st->time_base = (AVRational){1, aud->sample_rate};
-                       ctx->sample_fmt = codec->sample_fmts[0];
+                       AVSampleFormat sample_fmt = av_get_sample_fmt(asset->ff_sample_format);
+                       if( sample_fmt == AV_SAMPLE_FMT_NONE )
+                               sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16;
+                       ctx->sample_fmt = sample_fmt;
                        uint64_t layout = av_get_default_channel_layout(ctx->channels);
                        aud->resample_context = swr_alloc_set_opts(NULL,
                                layout, ctx->sample_fmt, aud->sample_rate,
@@ -1973,19 +2231,30 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                        vstrm_index.append(ffidx(vidx, 0));
                        vid->avctx = ctx;  ffvideo.append(vid);  fst = vid;
                        vid->width = asset->width;
-                       ctx->width = (vid->width+3) & ~3;
                        vid->height = asset->height;
-                       ctx->height = (vid->height+3) & ~3;
                        vid->frame_rate = asset->frame_rate;
+
+                       AVPixelFormat pix_fmt = av_get_pix_fmt(asset->ff_pixel_format);
+                       if( pix_fmt == AV_PIX_FMT_NONE )
+                               pix_fmt = codec->pix_fmts ? codec->pix_fmts[0] : AV_PIX_FMT_YUV420P;
+                       ctx->pix_fmt = pix_fmt;
+                       const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
+                       int mask_w = (1<<desc->log2_chroma_w)-1;
+                       ctx->width = (vid->width+mask_w) & ~mask_w;
+                       int mask_h = (1<<desc->log2_chroma_h)-1;
+                       ctx->height = (vid->height+mask_h) & ~mask_h;
                        ctx->sample_aspect_ratio = to_sample_aspect_ratio(asset);
-                       ctx->pix_fmt = codec->pix_fmts ? codec->pix_fmts[0] : AV_PIX_FMT_YUV420P;
                        AVRational frame_rate = check_frame_rate(codec, vid->frame_rate);
                        if( !frame_rate.num || !frame_rate.den ) {
                                eprintf(_("check_frame_rate failed %s\n"), filename);
                                ret = 1;
                                break;
                        }
+                       av_reduce(&frame_rate.num, &frame_rate.den,
+                               frame_rate.num, frame_rate.den, INT_MAX);
+                       ctx->framerate = (AVRational) { frame_rate.num, frame_rate.den };
                        ctx->time_base = (AVRational) { frame_rate.den, frame_rate.num };
+                       st->avg_frame_rate = frame_rate;
                        st->time_base = ctx->time_base;
                        vid->writing = -1;
                        vid->interlaced = asset->interlace_mode == ILACE_MODE_TOP_FIRST ||
@@ -1996,11 +2265,44 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                        eprintf(_("not audio/video, %s:%s\n"), codec_name, filename);
                        ret = 1;
                }
+
+               if( ctx ) {
+                       AVDictionaryEntry *tag;
+                       if( (tag=av_dict_get(sopts, "cin_stats_filename", NULL, 0)) != 0 ) {
+                               char suffix[BCSTRLEN];  sprintf(suffix,"-%d.log",fst->fidx);
+                               fst->stats_filename = cstrcat(2, tag->value, suffix);
+                       }
+                       if( (tag=av_dict_get(sopts, "flags", NULL, 0)) != 0 ) {
+                               int pass = fst->pass;
+                               char *cp = tag->value;
+                               while( *cp ) {
+                                       int ch = *cp++, pfx = ch=='-' ? -1 : ch=='+' ? 1 : 0;
+                                       if( !isalnum(!pfx ? ch : (ch=*cp++)) ) continue;
+                                       char id[BCSTRLEN], *bp = id, *ep = bp+sizeof(id)-1;
+                                       for( *bp++=ch; isalnum(ch=*cp); ++cp )
+                                               if( bp < ep ) *bp++ = ch;
+                                       *bp = 0;
+                                       if( !strcmp(id, "pass1") ) {
+                                               pass = pfx<0 ? (pass&~1) : pfx>0 ? (pass|1) : 1;
+                                       }
+                                       else if( !strcmp(id, "pass2") ) {
+                                               pass = pfx<0 ? (pass&~2) : pfx>0 ? (pass|2) : 2;
+                                       }
+                               }
+                               if( (fst->pass=pass) ) {
+                                       if( pass & 1 ) ctx->flags |= AV_CODEC_FLAG_PASS1;
+                                       if( pass & 2 ) ctx->flags |= AV_CODEC_FLAG_PASS2;
+                               }
+                       }
+               }
        }
        if( !ret ) {
                if( fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER )
                        ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
-
+               if( fst->stats_filename && (ret=fst->init_stats_file()) )
+                       eprintf(_("error: stats file = %s\n"), fst->stats_filename);
+       }
+       if( !ret ) {
                av_dict_set(&sopts, "cin_bitrate", 0, 0);
                av_dict_set(&sopts, "cin_quality", 0, 0);
 
@@ -2012,6 +2314,13 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                        if( ret < 0 )
                                fprintf(stderr, "Could not copy the stream parameters\n");
                }
+               if( ret >= 0 ) {
+_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+                       ret = avcodec_copy_context(st->codec, ctx);
+_Pragma("GCC diagnostic warning \"-Wdeprecated-declarations\"")
+                       if( ret < 0 )
+                               fprintf(stderr, "Could not copy the stream context\n");
+               }
                if( ret < 0 ) {
                        ff_err(ret,"FFMPEG::open_encoder");
                        eprintf(_("open failed %s:%s\n"), codec_name, filename);