X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fffmpeg.C;h=547b7f074f1276262838c65b5d6d5f8a361ce424;hb=b78e8ac7987fbf35a4ba60534c4a3d2b290562b9;hp=10ad05036ee64b71a5cb8d7e2336434fe2e52108;hpb=c8c97de4bed1b06c686fe7155e41ecb85d633b34;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 10ad0503..547b7f07 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -148,10 +148,13 @@ void FFAudioStream::reset_history() { inp = outp = bfr; hpos = 0; + memset(bfr, 0, lmt-bfr); } void FFAudioStream::iseek(int64_t ofs) { + if( ofs > hpos ) ofs = hpos; + if( ofs > sz ) ofs = sz; outp = inp - ofs*nch; if( outp < bfr ) outp += sz*nch; } @@ -320,11 +323,15 @@ int FFStream::decode_activate() ret = AVERROR(ENOMEM); } if( ret >= 0 ) { + av_codec_set_pkt_timebase(avctx, st->time_base); + if( decoder->capabilities & AV_CODEC_CAP_DR1 ) + avctx->flags |= CODEC_FLAG_EMU_EDGE; avcodec_parameters_to_context(avctx, st->codecpar); ret = avcodec_open2(avctx, decoder, &copts); } - if( ret >= 0 ) + if( ret >= 0 ) { reading = 1; + } else eprintf(_("open decoder failed\n")); } @@ -484,7 +491,6 @@ int FFStream::flush() int FFStream::seek(int64_t no, double rate) { - int64_t tstmp = -INT64_MAX+1; // default ffmpeg native seek int npkts = 1; int64_t pos = no, pkt_pos = -1; @@ -501,11 +507,19 @@ int FFStream::seek(int64_t no, double rate) npkts = MAX_RETRY; } } - if( pos > 0 && st->time_base.num > 0 ) { - double secs = pos / rate; - tstmp = secs * st->time_base.den / st->time_base.num; - if( nudge != AV_NOPTS_VALUE ) tstmp += nudge; - } + if( pos == curr_pos ) return 0; + double secs = pos < 0 ? 0. : pos / rate; + AVRational time_base = st->time_base; + int64_t tstmp = time_base.num > 0 ? secs * time_base.den/time_base.num : 0; + if( nudge != AV_NOPTS_VALUE ) tstmp += nudge; + int idx = st->index; +#if 0 +// seek all streams using the default timebase. +// this is how ffmpeg and ffplay work. stream seeks are less tested. + tstmp = av_rescale_q(tstmp, time_base, AV_TIME_BASE_Q); + idx = -1; +#endif + avcodec_flush_buffers(avctx); avformat_flush(fmt_ctx); #if 0 @@ -515,9 +529,9 @@ int FFStream::seek(int64_t no, double rate) seek = pkt_pos; flags = AVSEEK_FLAG_BYTE; } - int ret = avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, seek, INT64_MAX, flags); + int ret = avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, seek, INT64_MAX, flags); #else - int ret = av_seek_frame(fmt_ctx, st->index, tstmp, AVSEEK_FLAG_ANY); + int ret = av_seek_frame(fmt_ctx, idx, tstmp, AVSEEK_FLAG_ANY); #endif int retry = MAX_RETRY; while( ret >= 0 ) { @@ -549,9 +563,9 @@ int FFStream::seek(int64_t no, double rate) } } if( ret < 0 ) { -printf("** seek fail %ld, %ld\n", pos, tstmp); +printf("** seek fail %jd, %jd\n", pos, tstmp); seeked = need_packet = 0; - st_eof(flushed=1); + st_eof(flushed=1); return -1; } //printf("seeked pos = %ld, %ld\n", pos, tstmp); @@ -568,6 +582,7 @@ FFAudioStream::FFAudioStream(FFMPEG *ffmpeg, AVStream *strm, int idx, int fidx) mbsz = 0; length = 0; resample_context = 0; + swr_ichs = swr_ifmt = swr_irate = 0; aud_bfr_sz = 0; aud_bfr = 0; @@ -588,6 +603,28 @@ FFAudioStream::~FFAudioStream() delete [] bfr; } +void FFAudioStream::init_swr(int ichs, int ifmt, int irate) +{ + if( resample_context ) { + if( swr_ichs == ichs && swr_ifmt == ifmt && swr_irate == irate ) + return; + swr_free(&resample_context); + } + swr_ichs = ichs; swr_ifmt = ifmt; swr_irate = irate; + if( ichs == channels && ifmt == AV_SAMPLE_FMT_FLT && irate == sample_rate ) + return; + uint64_t ilayout = av_get_default_channel_layout(ichs); + if( !ilayout ) ilayout = ((uint64_t)1<=0 && !flushed && curr_pos 0 ) { + init_swr(frame->channels, frame->format, frame->sample_rate); load_history(&frame->extended_data[0], frame->nb_samples); curr_pos += frame->nb_samples; } @@ -706,7 +744,7 @@ int FFAudioStream::load(int64_t pos, int len) int FFAudioStream::audio_seek(int64_t pos) { - if( decode_activate() < 0 ) return -1; + if( decode_activate() <= 0 ) return -1; if( !st->codecpar ) return -1; if( in_history(pos) ) return 0; if( pos == curr_pos ) return 0; @@ -759,6 +797,11 @@ int FFAudioStream::encode_frame(AVFrame *frame) return FFStream::encode_frame(frame); } +int FFAudioStream::write_packet(FFPacket &pkt) +{ + return FFStream::write_packet(pkt); +} + void FFAudioStream::load_markers() { IndexState *index_state = ffmpeg->file_base->asset->index_state; @@ -830,7 +873,7 @@ int FFVideoStream::load(VFrame *vframe, int64_t pos) int FFVideoStream::video_seek(int64_t pos) { - if( decode_activate() < 0 ) return -1; + if( decode_activate() <= 0 ) return -1; if( !st->codecpar ) return -1; if( pos == curr_pos-1 && !seeked ) return 0; // if close enough, just read up to current @@ -889,6 +932,13 @@ int FFVideoStream::encode_frame(AVFrame *frame) return FFStream::encode_frame(frame); } +int FFVideoStream::write_packet(FFPacket &pkt) +{ + if( !(ffmpeg->fmt_ctx->oformat->flags & AVFMT_VARIABLE_FPS) ) + pkt->duration = 1; + return FFStream::write_packet(pkt); +} + AVPixelFormat FFVideoConvert::color_model_to_pix_fmt(int color_model) { switch( color_model ) { @@ -1728,16 +1778,7 @@ int FFMPEG::open_decoder() aud->sample_rate = avpar->sample_rate; double secs = to_secs(st->duration, st->time_base); aud->length = secs * aud->sample_rate; - if( avpar->format != AV_SAMPLE_FMT_FLT ) { - uint64_t layout = av_get_default_channel_layout(avpar->channels); - if( !layout ) layout = ((uint64_t)1<channels) - 1; - AVSampleFormat sample_format = (AVSampleFormat)avpar->format; - aud->resample_context = swr_alloc_set_opts(NULL, - layout, AV_SAMPLE_FMT_FLT, avpar->sample_rate, - layout, sample_format, avpar->sample_rate, - 0, NULL); - swr_init(aud->resample_context); - } + aud->init_swr(aud->channels, avpar->format, aud->sample_rate); aud->nudge = st->start_time; aud->reading = -1; if( opt_audio_filter ) @@ -2079,7 +2120,7 @@ int FFMPEG::decode_activate() } } int64_t nudge = vstart_time > min_nudge ? vstart_time : - astart_time > min_nudge ? astart_time : AV_NOPTS_VALUE; + astart_time > min_nudge ? astart_time : 0; for( int vidx=0; vidxnudge == AV_NOPTS_VALUE ) ffvideo[vidx]->nudge = nudge; @@ -2631,27 +2672,27 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) ret = avcodec_open2(avctx, decoder, &copts); } av_dict_free(&copts); - if( ret < 0 ) { - fprintf(stderr,"FFMPEG::scan: "); - fprintf(stderr,_("codec open failed\n")); - continue; - } - AVCodecParameters *avpar = st->codecpar; - switch( avpar->codec_type ) { - case AVMEDIA_TYPE_VIDEO: { - int vidx = ffvideo.size(); - while( --vidx>=0 && ffvideo[vidx]->fidx != i ); - if( vidx < 0 ) break; - ffvideo[vidx]->avctx = avctx; - break; } - case AVMEDIA_TYPE_AUDIO: { - int aidx = ffaudio.size(); - while( --aidx>=0 && ffaudio[aidx]->fidx != i ); - if( aidx < 0 ) continue; - ffaudio[aidx]->avctx = avctx; - break; } - default: break; + if( ret >= 0 ) { + AVCodecParameters *avpar = st->codecpar; + switch( avpar->codec_type ) { + case AVMEDIA_TYPE_VIDEO: { + int vidx = ffvideo.size(); + while( --vidx>=0 && ffvideo[vidx]->fidx != i ); + if( vidx < 0 ) break; + ffvideo[vidx]->avctx = avctx; + continue; } + case AVMEDIA_TYPE_AUDIO: { + int aidx = ffaudio.size(); + while( --aidx>=0 && ffaudio[aidx]->fidx != i ); + if( aidx < 0 ) break; + ffaudio[aidx]->avctx = avctx; + continue; } + default: break; + } } + fprintf(stderr,"FFMPEG::scan: "); + fprintf(stderr,_("codec open failed\n")); + avcodec_free_context(&avctx); } decode_activate(); @@ -2697,6 +2738,7 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) while( --vidx>=0 && ffvideo[vidx]->fidx != i ); if( vidx < 0 ) break; FFVideoStream *vid = ffvideo[vidx]; + if( !vid->avctx ) break; int64_t tstmp = pkt.dts; if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.pts; if( tstmp != AV_NOPTS_VALUE && (pkt.flags & AV_PKT_FLAG_KEY) && pkt.pos > 0 ) { @@ -2717,6 +2759,7 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled) while( --aidx>=0 && ffaudio[aidx]->fidx != i ); if( aidx < 0 ) break; FFAudioStream *aud = ffaudio[aidx]; + if( !aud->avctx ) break; int64_t tstmp = pkt.pts; if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.dts; if( tstmp != AV_NOPTS_VALUE && (pkt.flags & AV_PKT_FLAG_KEY) && pkt.pos > 0 ) { @@ -2736,7 +2779,8 @@ printf("audio%d pad %jd %jd (%jd)\n", aud->idx, pos, aud->curr_pos, pos-aud->cur index_state->pad_data(ch, nch, aud->curr_pos); } while( (ret=aud->decode_frame(frame)) > 0 ) { - if( frame->channels != nch ) break; + //if( frame->channels != nch ) break; + aud->init_swr(frame->channels, frame->format, frame->sample_rate); float *samples; int len = aud->get_samples(samples, &frame->extended_data[0], frame->nb_samples);