X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.0%2Fcinelerra%2Fffmpeg.C;h=89175ff737032e2bf6790c7676f9f4ec280ebd34;hb=955d712ff475171e99d7910ead049a9342ca8b21;hp=ce3d704461ffd0b009b27ed187df70880fe2ee57;hpb=058cf29dcce79444cb57da22ae03d9f2abff745e;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.0/cinelerra/ffmpeg.C b/cinelerra-5.0/cinelerra/ffmpeg.C index ce3d7044..89175ff7 100644 --- a/cinelerra-5.0/cinelerra/ffmpeg.C +++ b/cinelerra-5.0/cinelerra/ffmpeg.C @@ -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) { @@ -899,8 +941,8 @@ FFMPEG::~FFMPEG() delete flow_lock; delete mux_lock; av_dict_free(&opts); - delete opt_video_filter; - delete opt_audio_filter; + delete [] opt_video_filter; + delete [] opt_audio_filter; } int FFMPEG::check_sample_rate(AVCodec *codec, int sample_rate) @@ -958,8 +1000,6 @@ AVRational FFMPEG::to_time_base(int sample_rate) return (AVRational){1, sample_rate}; } -extern void get_exe_path(char *result); // from main.C - void FFMPEG::set_option_path(char *path, const char *fmt, ...) { get_exe_path(path); @@ -1075,12 +1115,14 @@ int FFMPEG::read_options(const char *options, AVDictionary *&opts) return ret; } -int FFMPEG::scan_options(const char *options, AVDictionary *&opts) +int FFMPEG::scan_options(const char *options, AVDictionary *&opts, AVStream *st) { FILE *fp = fmemopen((void *)options,strlen(options),"r"); if( !fp ) return 0; int ret = read_options(fp, options, opts); fclose(fp); + AVDictionaryEntry *tag = av_dict_get(opts, "id", NULL, 0); + if( tag ) st->id = strtol(tag->value,0,0); return ret; } @@ -1437,7 +1479,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) break; } has_audio = 1; - if( scan_options(asset->ff_audio_options, sopts) ) { + if( scan_options(asset->ff_audio_options, sopts, st) ) { eprintf("FFMPEG::open_encoder: bad audio options %s:%s\n", codec_name, filename); ret = 1; @@ -1483,7 +1525,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) break; } has_video = 1; - if( scan_options(asset->ff_video_options, sopts) ) { + if( scan_options(asset->ff_video_options, sopts, st) ) { eprintf("FFMPEG::open_encoder: bad video options %s:%s\n", codec_name, filename); ret = 1; @@ -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; iflush(); + for( int i=0; iflush(); } @@ -2032,6 +2070,11 @@ int FFVideoStream::create_filter(const char *filter_spec, AVCodecContext *src_ctx, AVCodecContext *sink_ctx) { avfilter_register_all(); + AVFilter *filter = avfilter_get_by_name(filter_spec); + if( !filter || filter->inputs->type != AVMEDIA_TYPE_VIDEO ) { + ff_err(AVERROR(EINVAL), "FFVideoStream::create_filter: %s\n", filter_spec); + return -1; + } filter_graph = avfilter_graph_alloc(); AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("buffersink"); @@ -2063,6 +2106,11 @@ int FFAudioStream::create_filter(const char *filter_spec, AVCodecContext *src_ctx, AVCodecContext *sink_ctx) { avfilter_register_all(); + AVFilter *filter = avfilter_get_by_name(filter_spec); + if( !filter || filter->inputs->type != AVMEDIA_TYPE_AUDIO ) { + ff_err(AVERROR(EINVAL), "FFAudioStream::create_filter: %s\n", filter_spec); + return -1; + } filter_graph = avfilter_graph_alloc(); AVFilter *buffersrc = avfilter_get_by_name("abuffer"); AVFilter *buffersink = avfilter_get_by_name("abuffersink");