update ffmpeg (2.8.4->3.0) giflib,openjpeg,x264,x265
[goodguy/history.git] / cinelerra-5.0 / cinelerra / ffmpeg.C
index a6bbabc15d0ec5bf3019cfd518e8b576c005fd94..e494932799e62ef35f7da82fe3488ad033ac8061 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef INT64_MAX
 #define INT64_MAX 9223372036854775807LL
 #endif
+#define MAX_RETRY 1000
 
 #include "asset.h"
 #include "bccmodels.h"
@@ -53,7 +54,7 @@ FFPacket::FFPacket()
 
 FFPacket::~FFPacket()
 {
-       av_free_packet(&pkt);
+       av_packet_unref(&pkt);
 }
 
 void FFPacket::init()
@@ -350,7 +351,7 @@ int FFStream::read_packet()
 int FFStream::decode(AVFrame *frame)
 {
        int ret = 0;
-       int retries = 1000;
+       int retries = MAX_RETRY;
        int got_frame = 0;
 
        while( ret >= 0 && !flushed && --retries >= 0 && !got_frame ) {
@@ -365,7 +366,7 @@ int FFStream::decode(AVFrame *frame)
                                ipkt->data += ret;
                                ipkt->size -= ret;
                        }
-                       retries = 1000;
+                       retries = MAX_RETRY;
                }
                if( !got_frame ) {
                        need_packet = 1;
@@ -459,34 +460,39 @@ int FFStream::seek(int64_t no, double rate)
                if( no-n < 30*rate ) {
                        if( n < 0 ) n = 0;
                        pos = n;
-                       plmt = marks[i].pos;
-                       npkts = 1000;
+                       if( ++i < marks.size() ) plmt = marks[i].pos;
+                       npkts = MAX_RETRY;
                }
        }
        double secs = pos / rate;
-       int64_t tstmp = secs * st->time_base.den / st->time_base.num;
+       int64_t pkt_ts, tstmp = secs * st->time_base.den / st->time_base.num;
        if( nudge != AV_NOPTS_VALUE ) tstmp += nudge;
-       if( avformat_seek_file(fmt_ctx, st->index,
-               -INT64_MAX, tstmp, INT64_MAX, AVSEEK_FLAG_ANY) < 0 ) return -1;
-       avcodec_flush_buffers(st->codec);
-       need_packet = 0;  flushed = 0;
-       seeked = 1;  st_eof(0);
-       int64_t pkt_ts = AV_NOPTS_VALUE;
-       int ret = 1, retry = 1000;
-
+       int ret = avformat_seek_file(fmt_ctx, st->index,
+               -INT64_MAX, tstmp, INT64_MAX, AVSEEK_FLAG_ANY);
+       if( ret >= 0 ) {
+               avcodec_flush_buffers(st->codec);
+               need_packet = 0;  flushed = 0;
+               seeked = 1;  st_eof(0);
 // read up to retry packets, limited to npkts in stream, and not past pkt.pos plmt
-       while( ret > 0 && npkts > 0 && --retry >= 0 ) {
-               if( (ret=read_packet()) <= 0 ) break;
-               if( ipkt->stream_index != st->index ) continue;
-               if( (pkt_ts=ipkt->dts) == AV_NOPTS_VALUE ) pkt_ts = ipkt->pts;
-               if( pkt_ts != AV_NOPTS_VALUE && pkt_ts >= tstmp ) break;
-               if( plmt >= 0 && ipkt->pos >= plmt ) break;
-               --npkts;
+               for( int retry=MAX_RETRY; ret>=0 && --retry>=0; ) {
+                       if( read_packet() <= 0 ) { ret = -1;  break; }
+                       if( plmt >= 0 && ipkt->pos >= plmt ) break;
+                       if( ipkt->stream_index != st->index ) continue;
+                       if( --npkts <= 0 ) break;
+                       if( (pkt_ts=ipkt->dts) == AV_NOPTS_VALUE &&
+                           (pkt_ts=ipkt->pts) == AV_NOPTS_VALUE ) continue;
+                       if( pkt_ts >= tstmp ) break;
+               }
        }
-
-       if( ret <= 0 || retry < 0 ) return -1;
+       if( ret < 0 ) {
+//printf("** seek fail %ld, %ld\n", pos, tstmp);
+               seeked = need_packet = 0;
+               st_eof(flushed=1);
+               return -1;
+       }
+//printf("seeked pos = %ld, %ld\n", pos, tstmp);
        seek_pos = curr_pos = pos;
-       return npkts > 0 ? 1 : 0;
+       return 0;
 }
 
 FFAudioStream::FFAudioStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx)
@@ -628,7 +634,7 @@ int FFAudioStream::load(int64_t pos, int len)
        if( mbsz < len ) mbsz = len;
        int64_t end_pos = pos + len;
        int ret = 0;
-       for( int i=0; ret>=0 && !flushed && curr_pos<end_pos && i<1000; ++i ) {
+       for( int i=0; ret>=0 && !flushed && curr_pos<end_pos && i<MAX_RETRY; ++i ) {
                ret = read_frame(frame);
                if( ret > 0 ) {
                        load_history(&frame->extended_data[0], frame->nb_samples);
@@ -742,13 +748,13 @@ int FFVideoStream::load(VFrame *vframe, int64_t pos)
                fprintf(stderr, "FFVideoStream::load: av_frame_alloc failed\n");
                return -1;
        }
-       for( int i=0; ret>=0 && !flushed && curr_pos<=pos && i<1000; ++i ) {
+       for( int i=0; ret>=0 && !flushed && curr_pos<=pos && i<MAX_RETRY; ++i ) {
                ret = read_frame(frame);
                if( ret > 0 ) ++curr_pos;
        }
-       if( ret > 0 ) {
+       if( ret >= 0 ) {
                AVCodecContext *ctx = st->codec;
-               ret = convert_cmodel(vframe, (AVPicture *)frame,
+               ret = convert_cmodel(vframe, frame,
                        ctx->pix_fmt, ctx->width, ctx->height);
        }
        ret = ret > 0 ? 1 : ret < 0 ? -1 : 0;
@@ -791,7 +797,7 @@ int FFVideoStream::encode(VFrame *vframe)
                AVFrame *frame = *picture;
                frame->pts = curr_pos;
                AVCodecContext *ctx = st->codec;
-               ret = convert_pixfmt(vframe, (AVPicture*)frame,
+               ret = convert_pixfmt(vframe, frame,
                        ctx->pix_fmt, ctx->width, ctx->height);
        }
        if( ret >= 0 ) {
@@ -815,7 +821,7 @@ int FFVideoStream::encode_frame(AVPacket *pkt, AVFrame *frame, int &got_packet)
        return ret;
 }
 
-PixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model)
+AVPixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model)
 {
        switch( color_model ) { 
        case BC_YUV422:         return AV_PIX_FMT_YUYV422;
@@ -836,7 +842,7 @@ PixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model)
        return AV_PIX_FMT_NB;
 }
 
-int FFVideoConvert::pix_fmt_to_color_model(PixelFormat pix_fmt)
+int FFVideoConvert::pix_fmt_to_color_model(AVPixelFormat pix_fmt)
 {
        switch (pix_fmt) { 
        case AV_PIX_FMT_YUYV422:        return BC_YUV422;
@@ -858,14 +864,14 @@ int FFVideoConvert::pix_fmt_to_color_model(PixelFormat pix_fmt)
 }
 
 int FFVideoConvert::convert_picture_vframe(VFrame *frame,
-               AVPicture *ip, PixelFormat ifmt, int iw, int ih)
+               AVFrame *ip, AVPixelFormat ifmt, int iw, int ih)
 {
-       AVPicture opic;
+       AVFrame opic;
        int cmodel = frame->get_color_model();
-       PixelFormat ofmt = color_model_to_pix_fmt(cmodel);
+       AVPixelFormat ofmt = color_model_to_pix_fmt(cmodel);
        if( ofmt == AV_PIX_FMT_NB ) return -1;
-       int size = avpicture_fill(&opic, frame->get_data(), ofmt, 
-                                 frame->get_w(), frame->get_h());
+       int size = av_image_fill_arrays(opic.data, opic.linesize,
+               frame->get_data(), ofmt, frame->get_w(), frame->get_h(), 1);
        if( size < 0 ) return -1;
 
        // transfer line sizes must match also
@@ -875,7 +881,7 @@ int FFVideoConvert::convert_picture_vframe(VFrame *frame,
        if( packed_width != opic.linesize[0] )  return -1;
 
        if( planar ) {
-               // override avpicture_fill() for planar types
+               // override av_image_fill_arrays() for planar types
                opic.data[0] = frame->get_y();
                opic.data[1] = frame->get_u();
                opic.data[2] = frame->get_v();
@@ -898,7 +904,7 @@ int FFVideoConvert::convert_picture_vframe(VFrame *frame,
 }
 
 int FFVideoConvert::convert_cmodel(VFrame *frame,
-                AVPicture *ip, PixelFormat ifmt, int iw, int ih)
+                AVFrame *ip, AVPixelFormat ifmt, int iw, int ih)
 {
        // try direct transfer
        if( !convert_picture_vframe(frame, ip, ifmt, iw, ih) ) return 1;
@@ -906,7 +912,7 @@ int FFVideoConvert::convert_cmodel(VFrame *frame,
        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(ifmt);
        int max_bits = 0;
        for( int i = 0; i <desc->nb_components; ++i ) {
-               int bits = desc->comp[i].depth_minus1 + 1;
+               int bits = desc->comp[i].depth;
                if( bits > max_bits ) max_bits = bits;
        }
 // from libavcodec/pixdesc.c
@@ -922,9 +928,9 @@ int FFVideoConvert::convert_cmodel(VFrame *frame,
 }
 
 int FFVideoConvert::transfer_cmodel(VFrame *frame,
-                AVFrame *ifp, PixelFormat ifmt, int iw, int ih)
+                AVFrame *ifp, AVPixelFormat ifmt, int iw, int ih)
 {
-       int ret = convert_cmodel(frame, (AVPicture *)ifp, ifmt, iw, ih);
+       int ret = convert_cmodel(frame, ifp, ifmt, iw, ih);
        if( ret > 0 ) {
                const AVDictionary *src = av_frame_get_metadata(ifp);
                AVDictionaryEntry *t = NULL;
@@ -937,14 +943,14 @@ int FFVideoConvert::transfer_cmodel(VFrame *frame,
 }
 
 int FFVideoConvert::convert_vframe_picture(VFrame *frame,
-               AVPicture *op, PixelFormat ofmt, int ow, int oh)
+               AVFrame *op, AVPixelFormat ofmt, int ow, int oh)
 {
-       AVPicture opic;
+       AVFrame opic;
        int cmodel = frame->get_color_model();
-       PixelFormat ifmt = color_model_to_pix_fmt(cmodel);
+       AVPixelFormat ifmt = color_model_to_pix_fmt(cmodel);
        if( ifmt == AV_PIX_FMT_NB ) return -1;
-       int size = avpicture_fill(&opic, frame->get_data(), ifmt, 
-                                 frame->get_w(), frame->get_h());
+       int size = av_image_fill_arrays(opic.data, opic.linesize,
+                frame->get_data(), ifmt, frame->get_w(), frame->get_h(), 1);
        if( size < 0 ) return -1;
 
        // transfer line sizes must match also
@@ -954,7 +960,7 @@ int FFVideoConvert::convert_vframe_picture(VFrame *frame,
        if( packed_width != opic.linesize[0] )  return -1;
 
        if( planar ) {
-               // override avpicture_fill() for planar types
+               // override av_image_fill_arrays() for planar types
                opic.data[0] = frame->get_y();
                opic.data[1] = frame->get_u();
                opic.data[2] = frame->get_v();
@@ -977,7 +983,7 @@ int FFVideoConvert::convert_vframe_picture(VFrame *frame,
 }
 
 int FFVideoConvert::convert_pixfmt(VFrame *frame,
-                AVPicture *op, PixelFormat ofmt, int ow, int oh)
+                AVFrame *op, AVPixelFormat ofmt, int ow, int oh)
 {
        // try direct transfer
        if( !convert_vframe_picture(frame, op, ofmt, ow, oh) ) return 1;
@@ -995,9 +1001,9 @@ int FFVideoConvert::convert_pixfmt(VFrame *frame,
 }
 
 int FFVideoConvert::transfer_pixfmt(VFrame *frame,
-                AVFrame *ofp, PixelFormat ofmt, int ow, int oh)
+                AVFrame *ofp, AVPixelFormat ofmt, int ow, int oh)
 {
-       int ret = convert_pixfmt(frame, (AVPicture *)ofp, ofmt, ow, oh);
+       int ret = convert_pixfmt(frame, ofp, ofmt, ow, oh);
        if( ret > 0 ) {
                BC_Hash *hp = frame->get_params();
                AVDictionary **dict = avpriv_frame_get_metadatap(ofp);
@@ -1254,9 +1260,9 @@ int FFMPEG::read_options(FILE *fp, const char *options, AVDictionary *&opts)
                if( !ret ) {
                        if( !strcmp(key, "duration") )
                                opt_duration = strtod(val, 0);
-                       if( !strcmp(key, "video_filter") )
+                       else if( !strcmp(key, "video_filter") )
                                opt_video_filter = cstrdup(val);
-                       if( !strcmp(key, "audio_filter") )
+                       else if( !strcmp(key, "audio_filter") )
                                opt_audio_filter = cstrdup(val);
                        else if( !strcmp(key, "loglevel") )
                                set_loglevel(val);
@@ -1559,7 +1565,6 @@ int FFMPEG::init_encoder(const char *filename)
                load_options("encode.opts", opts);
        }
        ff_unlock();
-       start_muxer();
        return ret;
 }
 
@@ -1648,7 +1653,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                        ctx->channel_layout =  av_get_default_channel_layout(ctx->channels);
                        ctx->sample_rate = check_sample_rate(codec, asset->sample_rate);
                        if( !ctx->sample_rate ) {
-                               eprintf("FFMPEG::open_audio_encode:"
+                               eprintf("FFMPEG::open_encoder:"
                                        " check_sample_rate failed %s\n", filename);
                                ret = 1;
                                break;
@@ -1710,7 +1715,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                        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("FFMPEG::open_audio_encode:"
+                               eprintf("FFMPEG::open_encoder:"
                                        " check_frame_rate failed %s\n", filename);
                                ret = 1;
                                break;
@@ -1745,6 +1750,8 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
        }
 
        ff_unlock();
+       if( !ret )
+               start_muxer();
        av_dict_free(&sopts);
        return ret;
 }
@@ -1887,7 +1894,6 @@ int FFMPEG::audio_seek(int stream, int64_t pos)
 {
        int aidx = astrm_index[stream].st_idx;
        FFAudioStream *aud = ffaudio[aidx];
-       pos = pos * aud->sample_rate / file_base->asset->sample_rate + 0.5;
        aud->audio_seek(pos);
        return 0;
 }
@@ -1896,7 +1902,6 @@ int FFMPEG::video_seek(int stream, int64_t pos)
 {
        int vidx = vstrm_index[stream].st_idx;
        FFVideoStream *vid = ffvideo[vidx];
-       pos = pos * vid->frame_rate / file_base->asset->frame_rate + 0.5;
        vid->video_seek(pos);
        return 0;
 }
@@ -1907,7 +1912,6 @@ int FFMPEG::decode(int chn, int64_t pos, double *samples, int len)
        if( !has_audio || chn >= astrm_index.size() ) return -1;
        int aidx = astrm_index[chn].st_idx;
        FFAudioStream *aud = ffaudio[aidx];
-       pos = pos * aud->sample_rate / file_base->asset->sample_rate + 0.5;
        if( aud->load(pos, len) < len ) return -1;
        int ch = astrm_index[chn].st_ch;
        int ret = aud->read(samples,len,ch);
@@ -1919,7 +1923,6 @@ int FFMPEG::decode(int layer, int64_t pos, VFrame *vframe)
        if( !has_video || layer >= vstrm_index.size() ) return -1;
        int vidx = vstrm_index[layer].st_idx;
        FFVideoStream *vid = ffvideo[vidx];
-       pos = pos * vid->frame_rate / file_base->asset->frame_rate + 0.5;
        return vid->load(vframe, pos);
 }
 
@@ -1999,19 +2002,8 @@ int FFMPEG::mux_video(FFrame *frm)
        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  = fst->st->index;
-               AVPicture *picture = (AVPicture *)frame;
-               pkt->data = (uint8_t *)picture;
-               pkt->size = sizeof(AVPicture);
-               pkt->pts = pkt->dts = frame->pts;
-               got_packet = 1;
-       }
-       else
-               ret = fst->encode_frame(pkt, frame, got_packet);
+       int got_packet = 0;
+       int ret = fst->encode_frame(pkt, frame, got_packet);
        if( ret >= 0 && got_packet )
                ret = fst->write_packet(pkt);
        if( ret < 0 )
@@ -2232,7 +2224,7 @@ int FFVideoStream::create_filter(const char *filter_spec,
 {
        avfilter_register_all();
        AVFilter *filter = avfilter_get_by_name(filter_spec);
-       if( !filter || filter->inputs->type != AVMEDIA_TYPE_VIDEO ) {
+       if( !filter || avfilter_pad_get_type(filter->inputs,0) != AVMEDIA_TYPE_VIDEO ) {
                ff_err(AVERROR(EINVAL), "FFVideoStream::create_filter: %s\n", filter_spec);
                return -1;
        }
@@ -2268,7 +2260,7 @@ int FFAudioStream::create_filter(const char *filter_spec,
 {
        avfilter_register_all();
        AVFilter *filter = avfilter_get_by_name(filter_spec);
-       if( !filter || filter->inputs->type != AVMEDIA_TYPE_AUDIO ) {
+       if( !filter || avfilter_pad_get_type(filter->inputs,0) != AVMEDIA_TYPE_AUDIO ) {
                ff_err(AVERROR(EINVAL), "FFAudioStream::create_filter: %s\n", filter_spec);
                return -1;
        }
@@ -2363,7 +2355,7 @@ int FFStream::bs_filter(AVPacket *pkt)
                }
                if( ret > 0 ) {
                        pkt->side_data = 0;  pkt->side_data_elems = 0;
-                       av_free_packet(pkt);
+                       av_packet_unref(pkt);
                        ret = av_packet_from_data(&bspkt, data, size);
                        if( ret < 0 ) break;
                }