diff --git a/SOURCES/gegl04-ff.patch b/SOURCES/gegl04-ff.patch new file mode 100644 index 0000000..99a1ff9 --- /dev/null +++ b/SOURCES/gegl04-ff.patch @@ -0,0 +1,1264 @@ +diff --git a/operations/external/ff-load.c b/operations/external/ff-load.c +index 0d9a4f3fbef422a8ff548820ee8843e0a2ffa7ec..ec3b747f976a31cfabe811ba03fb7487839342f0 100644 +--- a/operations/external/ff-load.c ++++ b/operations/external/ff-load.c +@@ -62,9 +62,11 @@ property_audio_fragment (audio, _("audio"), 0) + #include + #include + ++#include + #include + #include + #include ++#include + #include + + +@@ -74,11 +76,12 @@ typedef struct + gint height; + gdouble fps; + gint codec_delay; ++ int64_t first_dts; + + gchar *loadedfilename; /* to remember which file is "cached" */ + + AVFormatContext *audio_fcontext; +- AVCodec *audio_codec; ++ const AVCodec *audio_codec; + int audio_index; + GList *audio_track; + long audio_cursor_pos; +@@ -90,8 +93,10 @@ typedef struct + AVFormatContext *video_fcontext; + int video_index; + AVStream *video_stream; ++ AVCodecContext *video_ctx; + AVStream *audio_stream; +- AVCodec *video_codec; ++ AVCodecContext *audio_ctx; ++ const AVCodec *video_codec; + AVFrame *lavc_frame; + AVFrame *rgb_frame; + glong prevframe; /* previously decoded frame number */ +@@ -140,10 +145,8 @@ ff_cleanup (GeglProperties *o) + { + clear_audio_track (o); + g_free (p->loadedfilename); +- if (p->video_stream && p->video_stream->codec) +- avcodec_close (p->video_stream->codec); +- if (p->audio_stream && p->audio_stream->codec) +- avcodec_close (p->audio_stream->codec); ++ avcodec_free_context (&p->video_ctx); ++ avcodec_free_context (&p->audio_ctx); + if (p->video_fcontext) + avformat_close_input(&p->video_fcontext); + if (p->audio_fcontext) +@@ -202,14 +205,14 @@ decode_audio (GeglOperation *operation, + if (av_seek_frame (p->audio_fcontext, p->audio_stream->index, seek_target, (AVSEEK_FLAG_BACKWARD)) < 0) + fprintf (stderr, "audio seek error!\n"); + else +- avcodec_flush_buffers (p->audio_stream->codec); ++ avcodec_flush_buffers (p->audio_ctx); + + } + + while (p->prevapts <= pts2) + { + AVPacket pkt = {0,}; +- int decoded_bytes; ++ int ret; + + if (av_read_frame (p->audio_fcontext, &pkt) < 0) + { +@@ -219,77 +222,93 @@ decode_audio (GeglOperation *operation, + if (pkt.stream_index==p->audio_index && p->audio_stream) + { + static AVFrame frame; +- int got_frame; + +- decoded_bytes = avcodec_decode_audio4(p->audio_stream->codec, +- &frame, &got_frame, &pkt); +- +- if (decoded_bytes < 0) ++ ret = avcodec_send_packet (p->audio_ctx, &pkt); ++ if (ret < 0) + { +- fprintf (stderr, "avcodec_decode_audio4 failed for %s\n", ++ fprintf (stderr, "avcodec_send_packet failed for %s\n", + o->path); + } +- +- if (got_frame) { +- int samples_left = frame.nb_samples; +- int si = 0; +- +- while (samples_left) ++ while (ret == 0) + { +- int sample_count = samples_left; +- int channels = MIN(p->audio_stream->codecpar->channels, GEGL_MAX_AUDIO_CHANNELS); +- GeglAudioFragment *af = gegl_audio_fragment_new (o->audio_sample_rate, channels, +- AV_CH_LAYOUT_STEREO, samples_left); +-//); +- switch (p->audio_stream->codec->sample_fmt) +- { +- case AV_SAMPLE_FMT_FLT: +- for (gint i = 0; i < sample_count; i++) +- for (gint c = 0; c < channels; c++) +- af->data[c][i] = ((int16_t *)frame.data[0])[(i + si) * channels + c]; +- break; +- case AV_SAMPLE_FMT_FLTP: +- for (gint i = 0; i < sample_count; i++) +- for (gint c = 0; c < channels; c++) +- { +- af->data[c][i] = ((float *)frame.data[c])[i + si]; +- } +- break; +- case AV_SAMPLE_FMT_S16: +- for (gint i = 0; i < sample_count; i++) +- for (gint c = 0; c < channels; c++) +- af->data[c][i] = ((int16_t *)frame.data[0])[(i + si) * channels + c] / 32768.0; +- break; +- case AV_SAMPLE_FMT_S16P: +- for (gint i = 0; i < sample_count; i++) +- for (gint c = 0; c < channels; c++) +- af->data[c][i] = ((int16_t *)frame.data[c])[i + si] / 32768.0; +- break; +- case AV_SAMPLE_FMT_S32: +- for (gint i = 0; i < sample_count; i++) +- for (gint c = 0; c < channels; c++) +- af->data[c][i] = ((int32_t *)frame.data[0])[(i + si) * channels + c] / 2147483648.0; ++ ret = avcodec_receive_frame (p->audio_ctx, &frame); ++ if (ret == AVERROR(EAGAIN)) ++ { ++ // no more frames; should send the next packet now ++ ret = 0; + break; +- case AV_SAMPLE_FMT_S32P: +- for (gint i = 0; i < sample_count; i++) +- for (gint c = 0; c < channels; c++) +- af->data[c][i] = ((int32_t *)frame.data[c])[i + si] / 2147483648.0; ++ } ++ else if (ret < 0) ++ { ++ fprintf (stderr, "avcodec_receive_frame failed for %s\n", ++ o->path); + break; +- default: +- g_warning ("undealt with sample format\n"); + } +- gegl_audio_fragment_set_sample_count (af, sample_count); +- gegl_audio_fragment_set_pos (af, +- (long int)av_rescale_q ((pkt.pts), p->audio_stream->time_base, AV_TIME_BASE_Q) * o->audio_sample_rate /AV_TIME_BASE); +- +- p->audio_pos += sample_count; +- p->audio_track = g_list_append (p->audio_track, af); +- +- samples_left -= sample_count; +- si += sample_count; +- } +- p->prevapts = pkt.pts * av_q2d (p->audio_stream->time_base); +- } ++ int samples_left = frame.nb_samples; ++ int si = 0; ++ ++ while (samples_left) ++ { ++ int sample_count = samples_left; ++ int channels = MIN(p->audio_stream->codecpar->channels, GEGL_MAX_AUDIO_CHANNELS); ++ GeglAudioFragment *af = gegl_audio_fragment_new (o->audio_sample_rate, channels, ++ AV_CH_LAYOUT_STEREO, samples_left); ++ //); ++ switch (p->audio_ctx->sample_fmt) ++ { ++ case AV_SAMPLE_FMT_FLT: ++ for (gint i = 0; i < sample_count; i++) ++ for (gint c = 0; c < channels; c++) ++ af->data[c][i] = ((int16_t *)frame.data[0])[(i + si) * channels + c]; ++ break; ++ case AV_SAMPLE_FMT_FLTP: ++ for (gint i = 0; i < sample_count; i++) ++ for (gint c = 0; c < channels; c++) ++ { ++ af->data[c][i] = ((float *)frame.data[c])[i + si]; ++ } ++ break; ++ case AV_SAMPLE_FMT_S16: ++ for (gint i = 0; i < sample_count; i++) ++ for (gint c = 0; c < channels; c++) ++ af->data[c][i] = ((int16_t *)frame.data[0])[(i + si) * channels + c] / 32768.0; ++ break; ++ case AV_SAMPLE_FMT_S16P: ++ for (gint i = 0; i < sample_count; i++) ++ for (gint c = 0; c < channels; c++) ++ af->data[c][i] = ((int16_t *)frame.data[c])[i + si] / 32768.0; ++ break; ++ case AV_SAMPLE_FMT_S32: ++ for (gint i = 0; i < sample_count; i++) ++ for (gint c = 0; c < channels; c++) ++ af->data[c][i] = ((int32_t *)frame.data[0])[(i + si) * channels + c] / 2147483648.0; ++ break; ++ case AV_SAMPLE_FMT_S32P: ++ for (gint i = 0; i < sample_count; i++) ++ for (gint c = 0; c < channels; c++) ++ af->data[c][i] = ((int32_t *)frame.data[c])[i + si] / 2147483648.0; ++ break; ++ default: ++ g_warning ("undealt with sample format\n"); ++ } ++ gegl_audio_fragment_set_sample_count (af, sample_count); ++ gegl_audio_fragment_set_pos ( ++ af, ++ (long int)av_rescale_q ( ++ (pkt.pts), ++ p->audio_stream->time_base, ++ AV_TIME_BASE_Q ++ ) * o->audio_sample_rate / AV_TIME_BASE ++ ); ++ ++ p->audio_pos += sample_count; ++ p->audio_track = g_list_append (p->audio_track, af); ++ ++ samples_left -= sample_count; ++ si += sample_count; ++ } ++ p->prevapts = pkt.pts * av_q2d (p->audio_stream->time_base); ++ } + } + av_packet_unref (&pkt); + } +@@ -325,12 +344,12 @@ decode_frame (GeglOperation *operation, + if (frame < 2 || frame > prevframe + 64 || frame < prevframe ) + { + int64_t seek_target = av_rescale_q (((frame) * AV_TIME_BASE * 1.0) / o->frame_rate +-, AV_TIME_BASE_Q, p->video_stream->time_base) / p->video_stream->codec->ticks_per_frame; ++, AV_TIME_BASE_Q, p->video_stream->time_base) / p->video_ctx->ticks_per_frame; + + if (av_seek_frame (p->video_fcontext, p->video_index, seek_target, (AVSEEK_FLAG_BACKWARD )) < 0) + fprintf (stderr, "video seek error!\n"); + else +- avcodec_flush_buffers (p->video_stream->codec); ++ avcodec_flush_buffers (p->video_ctx); + + prevframe = -1; + } +@@ -340,7 +359,7 @@ decode_frame (GeglOperation *operation, + int got_picture = 0; + do + { +- int decoded_bytes; ++ int ret; + AVPacket pkt = {0,}; + + do +@@ -354,33 +373,52 @@ decode_frame (GeglOperation *operation, + } + while (pkt.stream_index != p->video_index); + +- decoded_bytes = avcodec_decode_video2 ( +- p->video_stream->codec, p->lavc_frame, +- &got_picture, &pkt); +- if (decoded_bytes < 0) ++ ret = avcodec_send_packet (p->video_ctx, &pkt); ++ if (ret < 0) + { +- fprintf (stderr, "avcodec_decode_video failed for %s\n", ++ fprintf (stderr, "avcodec_send_packet failed for %s\n", + o->path); + return -1; + } +- +- if(got_picture) +- { +- if ((pkt.dts == pkt.pts) || (p->lavc_frame->key_frame!=0)) +- { +- p->lavc_frame->pts = (p->video_stream->cur_dts - +- p->video_stream->first_dts); +- p->prevpts = av_rescale_q (p->lavc_frame->pts, +- p->video_stream->time_base, +- AV_TIME_BASE_Q) * 1.0 / AV_TIME_BASE; +- decodeframe = roundf( p->prevpts * o->frame_rate); +- } +- else +- { +- p->prevpts += 1.0 / o->frame_rate; +- decodeframe = roundf ( p->prevpts * o->frame_rate); +- } +- } ++ while (ret == 0) ++ { ++ if (!p->first_dts) ++ p->first_dts = pkt.dts; ++ ret = avcodec_receive_frame (p->video_ctx, p->lavc_frame); ++ if (ret == AVERROR(EAGAIN)) ++ { ++ // no more frames; should send the next packet now ++ ret = 0; ++ break; ++ } ++ else if (ret < 0) ++ { ++ fprintf (stderr, "avcodec_receive_frame failed for %s\n", ++ o->path); ++ break; ++ } ++ got_picture = 1; ++ if ((pkt.dts == pkt.pts) || (p->lavc_frame->key_frame!=0)) ++ { ++ // cur_dts and first_dts are moved to libavformat/internal.h ++ /* ++ p->lavc_frame->pts = (p->video_stream->cur_dts - ++ p->video_stream->first_dts); ++ */ ++ p->lavc_frame->pts = pkt.dts - p->first_dts; ++ p->prevpts = av_rescale_q (p->lavc_frame->pts, ++ p->video_stream->time_base, ++ AV_TIME_BASE_Q) * 1.0 / AV_TIME_BASE; ++ decodeframe = roundf( p->prevpts * o->frame_rate); ++ } ++ else ++ { ++ p->prevpts += 1.0 / o->frame_rate; ++ decodeframe = roundf ( p->prevpts * o->frame_rate); ++ } ++ if (decodeframe > frame + p->codec_delay) ++ break; ++ } + #if 0 + if (decoded_bytes != pkt.size) + fprintf (stderr, "bytes left!\n"); +@@ -429,6 +467,7 @@ prepare (GeglOperation *operation) + if (err < 0) + { + print_error (o->path, err); ++ return; + } + err = avformat_find_stream_info (p->video_fcontext, NULL); + if (err < 0) +@@ -440,6 +479,7 @@ prepare (GeglOperation *operation) + if (err < 0) + { + print_error (o->path, err); ++ return; + } + err = avformat_find_stream_info (p->audio_fcontext, NULL); + if (err < 0) +@@ -467,16 +507,26 @@ prepare (GeglOperation *operation) + { + p->video_codec = avcodec_find_decoder (p->video_stream->codecpar->codec_id); + if (p->video_codec == NULL) +- g_warning ("video codec not found"); +- p->video_stream->codec->err_recognition = AV_EF_IGNORE_ERR | ++ { ++ g_warning ("video codec not found"); ++ p->video_ctx = NULL; ++ return; ++ } ++ p->video_ctx = avcodec_alloc_context3 (p->video_codec); ++ if (avcodec_parameters_to_context (p->video_ctx, p->video_stream->codecpar) < 0) ++ { ++ fprintf (stderr, "cannot copy video codec parameters\n"); ++ return; ++ } ++ p->video_ctx->err_recognition = AV_EF_IGNORE_ERR | + AV_EF_BITSTREAM | + AV_EF_BUFFER; +- p->video_stream->codec->workaround_bugs = FF_BUG_AUTODETECT; ++ p->video_ctx->workaround_bugs = FF_BUG_AUTODETECT; + + +- if (avcodec_open2 (p->video_stream->codec, p->video_codec, NULL) < 0) ++ if (avcodec_open2 (p->video_ctx, p->video_codec, NULL) < 0) + { +- g_warning ("error opening codec %s", p->video_stream->codec->codec->name); ++ g_warning ("error opening codec %s", p->video_ctx->codec->name); + return; + } + } +@@ -485,10 +535,20 @@ prepare (GeglOperation *operation) + { + p->audio_codec = avcodec_find_decoder (p->audio_stream->codecpar->codec_id); + if (p->audio_codec == NULL) +- g_warning ("audio codec not found"); +- else if (avcodec_open2 (p->audio_stream->codec, p->audio_codec, NULL) < 0) + { +- g_warning ("error opening codec %s", p->audio_stream->codec->codec->name); ++ g_warning ("audio codec not found"); ++ p->audio_ctx = NULL; ++ return; ++ } ++ p->audio_ctx = avcodec_alloc_context3 (p->audio_codec); ++ if (avcodec_parameters_to_context (p->audio_ctx, p->audio_stream->codecpar) < 0) ++ { ++ fprintf (stderr, "cannot copy audio codec parameters\n"); ++ return; ++ } ++ if (avcodec_open2 (p->audio_ctx, p->audio_codec, NULL) < 0) ++ { ++ g_warning ("error opening codec %s", p->audio_ctx->codec->name); + } + else + { +@@ -544,7 +604,7 @@ prepare (GeglOperation *operation) + fprintf (stdout, "duration: %02i:%02i:%02i\n", h, m, s); + } + #endif +- p->codec_delay = p->video_stream->codec->delay; ++ p->codec_delay = p->video_ctx->delay; + + if (!strcmp (o->video_codec, "mpeg1video")) + p->codec_delay = 1; +@@ -736,7 +796,7 @@ process (GeglOperation *operation, + if (p->video_stream == NULL) + return TRUE; + +- if (p->video_stream->codec->pix_fmt == AV_PIX_FMT_RGB24) ++ if (p->video_ctx->pix_fmt == AV_PIX_FMT_RGB24) + { + GeglRectangle extent = {0,0,p->width,p->height}; + gegl_buffer_set (output, &extent, 0, babl_format("R'G'B' u8"), p->lavc_frame->data[0], GEGL_AUTO_ROWSTRIDE); +@@ -746,7 +806,7 @@ process (GeglOperation *operation, + struct SwsContext *img_convert_ctx; + GeglRectangle extent = {0,0,p->width,p->height}; + +- img_convert_ctx = sws_getContext(p->width, p->height, p->video_stream->codec->pix_fmt, ++ img_convert_ctx = sws_getContext(p->width, p->height, p->video_ctx->pix_fmt, + p->width, p->height, AV_PIX_FMT_RGB24, + SWS_BICUBIC, NULL, NULL, NULL); + if (!p->rgb_frame) +diff --git a/operations/external/ff-save.c b/operations/external/ff-save.c +index 8dfb3ee89894d8f1d7c73496775c95520082467f..320ad029b59ac5066852cb3a1430c6016c084072 100644 +--- a/operations/external/ff-save.c ++++ b/operations/external/ff-save.c +@@ -82,6 +82,8 @@ property_int (me_subpel_quality, _("me-subpel-quality"), 0) + + #include "gegl-op.h" + ++#include ++#include + #include + #include + #include +@@ -106,6 +108,7 @@ typedef struct + AVOutputFormat *fmt; + AVFormatContext *oc; + AVStream *video_st; ++ AVCodecContext *video_ctx; + + AVFrame *picture, *tmp_picture; + uint8_t *video_outbuf; +@@ -117,6 +120,7 @@ typedef struct + * using gggl directly,. without needing to link with the oxide library + */ + AVStream *audio_st; ++ AVCodecContext *audio_ctx; + + uint32_t sample_rate; + uint32_t bits; +@@ -247,8 +251,6 @@ init (GeglProperties *o) + + if (!inited) + { +- av_register_all (); +- avcodec_register_all (); + inited = 1; + } + +@@ -282,7 +284,7 @@ static void write_audio_frame (GeglProperties *o, + static AVStream * + add_audio_stream (GeglProperties *o, AVFormatContext * oc, int codec_id) + { +- AVCodecContext *c; ++ AVCodecParameters *cp; + AVStream *st; + + st = avformat_new_stream (oc, NULL); +@@ -292,12 +294,26 @@ add_audio_stream (GeglProperties *o, AVFormatContext * oc, int codec_id) + exit (1); + } + +- c = st->codec; +- c->codec_id = codec_id; +- c->codec_type = AVMEDIA_TYPE_AUDIO; ++ cp = st->codecpar; ++ cp->codec_id = codec_id; ++ cp->codec_type = AVMEDIA_TYPE_AUDIO; ++ cp->bit_rate = o->audio_bit_rate * 1000; + +- if (oc->oformat->flags & AVFMT_GLOBALHEADER) +- c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; ++ if (o->audio_sample_rate == -1) ++ { ++ if (o->audio) ++ { ++ if (gegl_audio_fragment_get_sample_rate (o->audio) == 0) ++ { ++ gegl_audio_fragment_set_sample_rate (o->audio, 48000); // XXX: should skip adding audiostream instead ++ } ++ o->audio_sample_rate = gegl_audio_fragment_get_sample_rate (o->audio); ++ } ++ } ++ cp->sample_rate = o->audio_sample_rate; ++ ++ cp->channel_layout = AV_CH_LAYOUT_STEREO; ++ cp->channels = 2; + + return st; + } +@@ -306,49 +322,44 @@ add_audio_stream (GeglProperties *o, AVFormatContext * oc, int codec_id) + static gboolean + open_audio (GeglProperties *o, AVFormatContext * oc, AVStream * st) + { ++ Priv *p = (Priv*)o->user_data; + AVCodecContext *c; +- AVCodec *codec; ++ AVCodecParameters *cp; ++ const AVCodec *codec; + int i; + +- c = st->codec; ++ cp = st->codecpar; + + /* find the audio encoder */ +- codec = avcodec_find_encoder (c->codec_id); ++ codec = avcodec_find_encoder (cp->codec_id); + if (!codec) + { ++ p->audio_ctx = NULL; + fprintf (stderr, "codec not found\n"); + return FALSE; + } +- c->bit_rate = o->audio_bit_rate * 1000; +- c->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; +- +- if (o->audio_sample_rate == -1) +- { +- if (o->audio) ++ p->audio_ctx = c = avcodec_alloc_context3 (codec); ++ cp->format = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; ++ if (codec->supported_samplerates) + { +- if (gegl_audio_fragment_get_sample_rate (o->audio) == 0) +- { +- gegl_audio_fragment_set_sample_rate (o->audio, 48000); // XXX: should skip adding audiostream instead +- } +- o->audio_sample_rate = gegl_audio_fragment_get_sample_rate (o->audio); ++ for (i = 0; codec->supported_samplerates[i]; i++) ++ { ++ if (codec->supported_samplerates[i] == cp->sample_rate) ++ break; ++ } ++ if (!codec->supported_samplerates[i]) ++ cp->sample_rate = codec->supported_samplerates[0]; + } +- } +- c->sample_rate = o->audio_sample_rate; +- c->channel_layout = AV_CH_LAYOUT_STEREO; +- c->channels = 2; +- +- +- if (codec->supported_samplerates) +- { +- c->sample_rate = codec->supported_samplerates[0]; +- for (i = 0; codec->supported_samplerates[i]; i++) ++ if (avcodec_parameters_to_context (c, cp) < 0) + { +- if (codec->supported_samplerates[i] == o->audio_sample_rate) +- c->sample_rate = o->audio_sample_rate; ++ fprintf (stderr, "cannot copy codec parameters\n"); ++ return FALSE; + } +- } +- //st->time_base = (AVRational){1, c->sample_rate}; +- st->time_base = (AVRational){1, o->audio_sample_rate}; ++ if (p->oc->oformat->flags & AVFMT_GLOBALHEADER) ++ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; ++ ++ st->time_base = (AVRational){1, c->sample_rate}; ++ //st->time_base = (AVRational){1, o->audio_sample_rate}; + + c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; // ffmpeg AAC is not quite stable yet + +@@ -358,7 +369,11 @@ open_audio (GeglProperties *o, AVFormatContext * oc, AVStream * st) + fprintf (stderr, "could not open codec\n"); + return FALSE; + } +- ++ if (avcodec_parameters_from_context (cp, c) < 0) ++ { ++ fprintf (stderr, "cannot copy back the audio codec parameters\n"); ++ return FALSE; ++ } + return TRUE; + } + +@@ -393,19 +408,13 @@ static void encode_audio_fragments (Priv *p, AVFormatContext *oc, AVStream *st, + { + while (p->audio_pos - p->audio_read_pos > frame_size) + { +- AVCodecContext *c = st->codec; ++ AVCodecContext *c = p->audio_ctx; + long i; + int ret; +- int got_packet = 0; + static AVPacket pkt = { 0 }; /* XXX: static, should be stored in instance somehow */ + AVFrame *frame = alloc_audio_frame (c->sample_fmt, c->channel_layout, + c->sample_rate, frame_size); + +- if (pkt.size == 0) +- { +- av_init_packet (&pkt); +- } +- + av_frame_make_writable (frame); + switch (c->sample_fmt) { + case AV_SAMPLE_FMT_FLT: +@@ -469,19 +478,34 @@ static void encode_audio_fragments (Priv *p, AVFormatContext *oc, AVStream *st, + frame->pts = p->next_apts; + p->next_apts += frame_size; + +- //ret = avcodec_send_frame (c, frame); +- ret = avcodec_encode_audio2 (c, &pkt, frame, &got_packet); +- +- if (ret < 0) { +- fprintf (stderr, "Error encoding audio frame: %s\n", av_err2str (ret)); +- } +- if (got_packet) +- { +- av_packet_rescale_ts (&pkt, st->codec->time_base, st->time_base); +- pkt.stream_index = st->index; +- av_interleaved_write_frame (oc, &pkt); +- av_packet_unref (&pkt); +- } ++ ret = avcodec_send_frame (c, frame); ++ if (ret < 0) ++ { ++ fprintf (stderr, "avcodec_send_frame failed: %s\n", av_err2str (ret)); ++ } ++ while (ret == 0) ++ { ++ if (pkt.size == 0) ++ { ++ av_init_packet (&pkt); ++ } ++ ret = avcodec_receive_packet (c, &pkt); ++ if (ret == AVERROR(EAGAIN)) ++ { ++ // no more packets; should send the next frame now ++ } ++ else if (ret < 0) ++ { ++ fprintf (stderr, "avcodec_receive_packet failed: %s\n", av_err2str (ret)); ++ } ++ else ++ { ++ av_packet_rescale_ts (&pkt, c->time_base, st->time_base); ++ pkt.stream_index = st->index; ++ av_interleaved_write_frame (oc, &pkt); ++ av_packet_unref (&pkt); ++ } ++ } + av_frame_free (&frame); + p->audio_read_pos += frame_size; + } +@@ -492,7 +516,7 @@ void + write_audio_frame (GeglProperties *o, AVFormatContext * oc, AVStream * st) + { + Priv *p = (Priv*)o->user_data; +- AVCodecContext *c = st->codec; ++ AVCodecContext *c = p->audio_ctx; + int sample_count = 100000; + + if (o->audio) +@@ -549,8 +573,7 @@ write_audio_frame (GeglProperties *o, AVFormatContext * oc, AVStream * st) + void + close_audio (Priv * p, AVFormatContext * oc, AVStream * st) + { +- avcodec_close (st->codec); +- ++ avcodec_free_context (&p->audio_ctx); + } + + /* add a video output stream */ +@@ -559,7 +582,7 @@ add_video_stream (GeglProperties *o, AVFormatContext * oc, int codec_id) + { + Priv *p = (Priv*)o->user_data; + +- AVCodecContext *c; ++ AVCodecParameters *cp; + AVStream *st; + + st = avformat_new_stream (oc, NULL); +@@ -569,78 +592,23 @@ add_video_stream (GeglProperties *o, AVFormatContext * oc, int codec_id) + exit (1); + } + +- c = st->codec; +- c->codec_id = codec_id; +- c->codec_type = AVMEDIA_TYPE_VIDEO; ++ cp = st->codecpar; ++ cp->codec_id = codec_id; ++ cp->codec_type = AVMEDIA_TYPE_VIDEO; + /* put sample propeters */ +- c->bit_rate = o->video_bit_rate * 1000; ++ cp->bit_rate = o->video_bit_rate * 1000; + #ifdef USE_FINE_GRAINED_FFMPEG +- c->rc_min_rate = o->video_bit_rate_min * 1000; +- c->rc_max_rate = o->video_bit_rate_max * 1000; ++ cp->rc_min_rate = o->video_bit_rate_min * 1000; ++ cp->rc_max_rate = o->video_bit_rate_max * 1000; + if (o->video_bit_rate_tolerance >= 0) +- c->bit_rate_tolerance = o->video_bit_rate_tolerance * 1000; ++ cp->bit_rate_tolerance = o->video_bit_rate_tolerance * 1000; + #endif + /* resolution must be a multiple of two */ +- c->width = p->width; +- c->height = p->height; ++ cp->width = p->width; ++ cp->height = p->height; + /* frames per second */ + st->time_base =(AVRational){1000, o->frame_rate * 1000}; +- c->time_base = st->time_base; +- +- c->pix_fmt = AV_PIX_FMT_YUV420P; +- +- if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) +- { +- c->max_b_frames = 2; +- } +- +- if (c->codec_id == AV_CODEC_ID_H264) +- { +- c->qcompress = 0.6; // qcomp=0.6 +- c->me_range = 16; // me_range=16 +- c->gop_size = 250; // g=250 +- c->max_b_frames = 3; // bf=3 +- } +- +- if (o->video_bufsize) +- c->rc_buffer_size = o->video_bufsize * 1000; +-#if USE_FINE_GRAINED_FFMPEG +- if (o->global_quality) +- c->global_quality = o->global_quality; +- if (o->qcompress != 0.0) +- c->qcompress = o->qcompress; +- if (o->qblur != 0.0) +- c->qblur = o->qblur; +- if (o->max_qdiff != 0) +- c->max_qdiff = o->max_qdiff; +- if (o->me_subpel_quality != 0) +- c->me_subpel_quality = o->me_subpel_quality; +- if (o->i_quant_factor != 0.0) +- c->i_quant_factor = o->i_quant_factor; +- if (o->i_quant_offset != 0.0) +- c->i_quant_offset = o->i_quant_offset; +- if (o->max_b_frames) +- c->max_b_frames = o->max_b_frames; +- if (o->me_range) +- c->me_range = o->me_range; +- if (o->noise_reduction) +- c->noise_reduction = o->noise_reduction; +- if (o->scenechange_threshold) +- c->scenechange_threshold = o->scenechange_threshold; +- if (o->trellis) +- c->trellis = o->trellis; +- if (o->qmin) +- c->qmin = o->qmin; +- if (o->qmax) +- c->qmax = o->qmax; +- if (o->gop_size) +- c->gop_size = o->gop_size; +- if (o->keyint_min) +- c->keyint_min = o->keyint_min; +-#endif +- +- if (oc->oformat->flags & AVFMT_GLOBALHEADER) +- c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; ++ cp->format = AV_PIX_FMT_YUV420P; + + return st; + } +@@ -656,14 +624,15 @@ alloc_picture (int pix_fmt, int width, int height) + picture = av_frame_alloc (); + if (!picture) + return NULL; +- size = avpicture_get_size (pix_fmt, width + 1, height + 1); ++ size = av_image_get_buffer_size(pix_fmt, width + 1, height + 1, 1); + picture_buf = malloc (size); + if (!picture_buf) + { + av_free (picture); + return NULL; + } +- avpicture_fill ((AVPicture *) picture, picture_buf, pix_fmt, width, height); ++ av_image_fill_arrays (picture->data, picture->linesize, ++ picture_buf, pix_fmt, width, height, 1); + return picture; + } + +@@ -671,36 +640,99 @@ static gboolean + open_video (GeglProperties *o, AVFormatContext * oc, AVStream * st) + { + Priv *p = (Priv*)o->user_data; +- AVCodec *codec; ++ const AVCodec *codec; + AVCodecContext *c; ++ AVCodecParameters *cp; + AVDictionary *codec_options = {0}; + int ret; + +- c = st->codec; ++ cp = st->codecpar; + + /* find the video encoder */ +- codec = avcodec_find_encoder (c->codec_id); ++ codec = avcodec_find_encoder (cp->codec_id); + if (!codec) + { ++ p->video_ctx = NULL; + fprintf (stderr, "codec not found\n"); + return FALSE; + } +- +- if (codec->pix_fmts){ +- int i = 0; +- c->pix_fmt = codec->pix_fmts[0]; +- while (codec->pix_fmts[i] !=-1) ++ p->video_ctx = c = avcodec_alloc_context3 (codec); ++ if (codec->pix_fmts) + { +- if (codec->pix_fmts[i] == AV_PIX_FMT_RGB24) +- c->pix_fmt = AV_PIX_FMT_RGB24; +- i++; ++ int i = 0; ++ cp->format = codec->pix_fmts[0]; ++ while (codec->pix_fmts[i] != -1) ++ { ++ if (codec->pix_fmts[i] == AV_PIX_FMT_RGB24) ++ { ++ cp->format = AV_PIX_FMT_RGB24; ++ break; ++ } ++ i++; ++ } + } +- } ++ if (avcodec_parameters_to_context (c, cp) < 0) ++ { ++ fprintf (stderr, "cannot copy codec parameters\n"); ++ return FALSE; ++ } ++ c->time_base = st->time_base; ++ if (cp->codec_id == AV_CODEC_ID_MPEG2VIDEO) ++ { ++ c->max_b_frames = 2; ++ } ++ if (cp->codec_id == AV_CODEC_ID_H264) ++ { ++ c->qcompress = 0.6; // qcomp=0.6 ++ c->me_range = 16; // me_range=16 ++ c->gop_size = 250; // g=250 ++ c->max_b_frames = 3; // bf=3 ++ } ++ if (o->video_bufsize) ++ c->rc_buffer_size = o->video_bufsize * 1000; ++ if (p->oc->oformat->flags & AVFMT_GLOBALHEADER) ++ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; ++ + #if 0 + if (o->video_preset[0]) + av_dict_set (&codec_options, "preset", o->video_preset, 0); + #endif + ++#if USE_FINE_GRAINED_FFMPEG ++ if (o->global_quality) ++ c->global_quality = o->global_quality; ++ if (o->qcompress != 0.0) ++ c->qcompress = o->qcompress; ++ if (o->qblur != 0.0) ++ c->qblur = o->qblur; ++ if (o->max_qdiff != 0) ++ c->max_qdiff = o->max_qdiff; ++ if (o->me_subpel_quality != 0) ++ c->me_subpel_quality = o->me_subpel_quality; ++ if (o->i_quant_factor != 0.0) ++ c->i_quant_factor = o->i_quant_factor; ++ if (o->i_quant_offset != 0.0) ++ c->i_quant_offset = o->i_quant_offset; ++ if (o->max_b_frames) ++ c->max_b_frames = o->max_b_frames; ++ if (o->me_range) ++ c->me_range = o->me_range; ++ if (o->noise_reduction) ++ c->noise_reduction = o->noise_reduction; ++ if (o->scenechange_threshold) ++ c->scenechange_threshold = o->scenechange_threshold; ++ if (o->trellis) ++ c->trellis = o->trellis; ++ if (o->qmin) ++ c->qmin = o->qmin; ++ if (o->qmax) ++ c->qmax = o->qmax; ++ if (o->gop_size) ++ c->gop_size = o->gop_size; ++ if (o->keyint_min) ++ c->keyint_min = o->keyint_min; ++#endif ++ + /* open the codec */ + if ((ret = avcodec_open2 (c, codec, &codec_options)) < 0) + { +@@ -739,6 +771,11 @@ open_video (GeglProperties *o, AVFormatContext * oc, AVStream * st) + return FALSE; + } + } ++ if (avcodec_parameters_from_context (cp, c) < 0) ++ { ++ fprintf (stderr, "cannot copy back the video codec parameters\n"); ++ return FALSE; ++ } + + return TRUE; + } +@@ -746,7 +783,7 @@ open_video (GeglProperties *o, AVFormatContext * oc, AVStream * st) + static void + close_video (Priv * p, AVFormatContext * oc, AVStream * st) + { +- avcodec_close (st->codec); ++ avcodec_free_context (&p->video_ctx); + av_free (p->picture->data[0]); + av_free (p->picture); + if (p->tmp_picture) +@@ -778,7 +815,7 @@ write_video_frame (GeglProperties *o, + AVCodecContext *c; + AVFrame *picture_ptr; + +- c = st->codec; ++ c = p->video_ctx; + + if (c->pix_fmt != AV_PIX_FMT_RGB24) + { +@@ -838,15 +875,34 @@ write_video_frame (GeglProperties *o, + else + #endif + { +- /* encode the image */ +- AVPacket pkt2; +- int got_packet = 0; +- av_init_packet(&pkt2); +- pkt2.data = p->video_outbuf; +- pkt2.size = p->video_outbuf_size; +- +- out_size = avcodec_encode_video2(c, &pkt2, picture_ptr, &got_packet); +- ++ // int got_packet = 0; ++ int key_frame = 0; ++ ret = avcodec_send_frame (c, picture_ptr); ++ while (ret == 0) ++ { ++ /* encode the image */ ++ AVPacket pkt2; ++ av_init_packet(&pkt2); ++ // pkt2 will use its own buffer ++ // we may remove video_outbuf and video_outbuf_size too ++ //pkt2.data = p->video_outbuf; ++ //pkt2.size = p->video_outbuf_size; ++ ret = avcodec_receive_packet (c, &pkt2); ++ if (ret == AVERROR(EAGAIN)) ++ { ++ // no more packets ++ ret = 0; ++ break; ++ } ++ else if (ret < 0) ++ { ++ break; ++ } ++ // out_size = 0; ++ // got_packet = 1; ++ key_frame = !!(pkt2.flags & AV_PKT_FLAG_KEY); ++ // coded_frame is removed by https://github.com/FFmpeg/FFmpeg/commit/11bc79089378a5ec00547d0f85bc152afdf30dfa ++ /* + if (!out_size && got_packet && c->coded_frame) + { + c->coded_frame->pts = pkt2.pts; +@@ -854,38 +910,32 @@ write_video_frame (GeglProperties *o, + if (c->codec->capabilities & AV_CODEC_CAP_INTRA_ONLY) + c->coded_frame->pict_type = AV_PICTURE_TYPE_I; + } +- +- if (pkt2.side_data_elems > 0) +- { +- int i; +- for (i = 0; i < pkt2.side_data_elems; i++) +- av_free(pkt2.side_data[i].data); +- av_freep(&pkt2.side_data); +- pkt2.side_data_elems = 0; +- } +- +- if (!out_size) +- out_size = pkt2.size; +- +- /* if zero size, it means the image was buffered */ +- if (out_size != 0) +- { +- AVPacket pkt; +- av_init_packet (&pkt); +- if (c->coded_frame->key_frame) +- pkt.flags |= AV_PKT_FLAG_KEY; +- pkt.stream_index = st->index; +- pkt.data = p->video_outbuf; +- pkt.size = out_size; +- pkt.pts = picture_ptr->pts; +- pkt.dts = picture_ptr->pts; +- av_packet_rescale_ts (&pkt, c->time_base, st->time_base); +- /* write the compressed frame in the media file */ +- ret = av_write_frame (oc, &pkt); +- } +- else +- { +- ret = 0; ++ */ ++ if (pkt2.side_data_elems > 0) ++ { ++ int i; ++ for (i = 0; i < pkt2.side_data_elems; i++) ++ av_free(pkt2.side_data[i].data); ++ av_freep(&pkt2.side_data); ++ pkt2.side_data_elems = 0; ++ } ++ out_size = pkt2.size; ++ /* if zero size, it means the image was buffered */ ++ if (out_size != 0) ++ { ++ AVPacket pkt; ++ av_init_packet (&pkt); ++ if (key_frame) ++ pkt.flags |= AV_PKT_FLAG_KEY; ++ pkt.stream_index = st->index; ++ pkt.data = pkt2.data; ++ pkt.size = out_size; ++ pkt.pts = picture_ptr->pts; ++ pkt.dts = picture_ptr->pts; ++ av_packet_rescale_ts (&pkt, c->time_base, st->time_base); ++ /* write the compressed frame in the media file */ ++ ret = av_write_frame (oc, &pkt); ++ } + } + } + if (ret != 0) +@@ -901,17 +951,18 @@ tfile (GeglProperties *o) + { + Priv *p = (Priv*)o->user_data; + ++ const AVOutputFormat *shared_fmt; + if (strcmp (o->container_format, "auto")) +- p->fmt = av_guess_format (o->container_format, o->path, NULL); ++ shared_fmt = av_guess_format (o->container_format, o->path, NULL); + else +- p->fmt = av_guess_format (NULL, o->path, NULL); ++ shared_fmt = av_guess_format (NULL, o->path, NULL); + +- if (!p->fmt) ++ if (!shared_fmt) + { + fprintf (stderr, + "ff_save couldn't deduce outputformat from file extension: using MPEG.\n%s", + ""); +- p->fmt = av_guess_format ("mpeg", NULL, NULL); ++ shared_fmt = av_guess_format ("mpeg", NULL, NULL); + } + p->oc = avformat_alloc_context (); + if (!p->oc) +@@ -920,23 +971,25 @@ tfile (GeglProperties *o) + return -1; + } + +- p->oc->oformat = p->fmt; +- +- snprintf (p->oc->filename, sizeof (p->oc->filename), "%s", o->path); ++ // The "avio_open" below fills "url" field instead of the "filename" ++ // snprintf (p->oc->filename, sizeof (p->oc->filename), "%s", o->path); + + p->video_st = NULL; + p->audio_st = NULL; + ++ enum AVCodecID audio_codec = shared_fmt->audio_codec; ++ enum AVCodecID video_codec = shared_fmt->video_codec; + if (strcmp (o->video_codec, "auto")) + { +- AVCodec *codec = avcodec_find_encoder_by_name (o->video_codec); +- p->fmt->video_codec = AV_CODEC_ID_NONE; ++ const AVCodec *codec = avcodec_find_encoder_by_name (o->video_codec); ++ video_codec = AV_CODEC_ID_NONE; + if (codec) +- p->fmt->video_codec = codec->id; ++ video_codec = codec->id; + else + { + fprintf (stderr, "didn't find video encoder \"%s\"\navailable codecs: ", o->video_codec); +- while ((codec = av_codec_next (codec))) ++ void *opaque = NULL; ++ while ((codec = av_codec_iterate (&opaque))) + if (av_codec_is_encoder (codec) && + avcodec_get_type (codec->id) == AVMEDIA_TYPE_VIDEO) + fprintf (stderr, "%s ", codec->name); +@@ -945,31 +998,36 @@ tfile (GeglProperties *o) + } + if (strcmp (o->audio_codec, "auto")) + { +- AVCodec *codec = avcodec_find_encoder_by_name (o->audio_codec); +- p->fmt->audio_codec = AV_CODEC_ID_NONE; ++ const AVCodec *codec = avcodec_find_encoder_by_name (o->audio_codec); ++ audio_codec = AV_CODEC_ID_NONE; + if (codec) +- p->fmt->audio_codec = codec->id; ++ audio_codec = codec->id; + else + { + fprintf (stderr, "didn't find audio encoder \"%s\"\navailable codecs: ", o->audio_codec); +- while ((codec = av_codec_next (codec))) ++ void *opaque = NULL; ++ while ((codec = av_codec_iterate (&opaque))) + if (av_codec_is_encoder (codec) && + avcodec_get_type (codec->id) == AVMEDIA_TYPE_AUDIO) + fprintf (stderr, "%s ", codec->name); + fprintf (stderr, "\n"); + } + } ++ p->fmt = av_malloc (sizeof(AVOutputFormat)); ++ *(p->fmt) = *shared_fmt; ++ p->fmt->video_codec = video_codec; ++ p->fmt->audio_codec = audio_codec; ++ p->oc->oformat = p->fmt; + +- if (p->fmt->video_codec != AV_CODEC_ID_NONE) ++ if (video_codec != AV_CODEC_ID_NONE) + { +- p->video_st = add_video_stream (o, p->oc, p->fmt->video_codec); ++ p->video_st = add_video_stream (o, p->oc, video_codec); + } +- if (p->fmt->audio_codec != AV_CODEC_ID_NONE) ++ if (audio_codec != AV_CODEC_ID_NONE) + { +- p->audio_st = add_audio_stream (o, p->oc, p->fmt->audio_codec); ++ p->audio_st = add_audio_stream (o, p->oc, audio_codec); + } + +- + if (p->video_st && ! open_video (o, p->oc, p->video_st)) + return -1; + +@@ -997,25 +1055,35 @@ static void flush_audio (GeglProperties *o) + { + Priv *p = (Priv*)o->user_data; + AVPacket pkt = { 0 }; +- int ret; ++ int ret = 0; + +- int got_packet = 0; + if (!p->audio_st) + return; + +- got_packet = 0; +- av_init_packet (&pkt); +- ret = avcodec_encode_audio2 (p->audio_st->codec, &pkt, NULL, &got_packet); ++ ret = avcodec_send_frame (p->audio_ctx, NULL); + if (ret < 0) +- { +- fprintf (stderr, "audio enc trouble\n"); +- } +- if (got_packet) + { +- pkt.stream_index = p->audio_st->index; +- av_packet_rescale_ts (&pkt, p->audio_st->codec->time_base, p->audio_st->time_base); +- av_interleaved_write_frame (p->oc, &pkt); +- av_packet_unref (&pkt); ++ fprintf (stderr, "avcodec_send_frame failed while entering to draining mode: %s\n", av_err2str (ret)); ++ } ++ av_init_packet (&pkt); ++ while (ret == 0) ++ { ++ ret = avcodec_receive_packet (p->audio_ctx, &pkt); ++ if (ret == AVERROR_EOF) ++ { ++ // no more packets ++ } ++ else if (ret < 0) ++ { ++ fprintf (stderr, "avcodec_receive_packet failed: %s\n", av_err2str (ret)); ++ } ++ else ++ { ++ pkt.stream_index = p->audio_st->index; ++ av_packet_rescale_ts (&pkt, p->audio_ctx->time_base, p->audio_st->time_base); ++ av_interleaved_write_frame (p->oc, &pkt); ++ av_packet_unref (&pkt); ++ } + } + } + +@@ -1062,27 +1130,35 @@ process (GeglOperation *operation, + static void flush_video (GeglProperties *o) + { + Priv *p = (Priv*)o->user_data; +- int got_packet = 0; + long ts = p->frame_count; +- do { +- AVPacket pkt = { 0 }; +- int ret; +- got_packet = 0; +- av_init_packet (&pkt); +- ret = avcodec_encode_video2 (p->video_st->codec, &pkt, NULL, &got_packet); +- if (ret < 0) +- return; +- +- if (got_packet) +- { +- pkt.stream_index = p->video_st->index; +- pkt.pts = ts; +- pkt.dts = ts++; +- av_packet_rescale_ts (&pkt, p->video_st->codec->time_base, p->video_st->time_base); +- av_interleaved_write_frame (p->oc, &pkt); +- av_packet_unref (&pkt); +- } +- } while (got_packet); ++ AVPacket pkt = { 0 }; ++ int ret = 0; ++ ret = avcodec_send_frame (p->video_ctx, NULL); ++ if (ret < 0) ++ { ++ fprintf (stderr, "avcodec_send_frame failed while entering to draining mode: %s\n", av_err2str (ret)); ++ } ++ av_init_packet (&pkt); ++ while (ret == 0) ++ { ++ ret = avcodec_receive_packet (p->video_ctx, &pkt); ++ if (ret == AVERROR_EOF) ++ { ++ // no more packets ++ } ++ else if (ret < 0) ++ { ++ } ++ else ++ { ++ pkt.stream_index = p->video_st->index; ++ pkt.pts = ts; ++ pkt.dts = ts++; ++ av_packet_rescale_ts (&pkt, p->video_ctx->time_base, p->video_st->time_base); ++ av_interleaved_write_frame (p->oc, &pkt); ++ av_packet_unref (&pkt); ++ } ++ } + } + + static void +@@ -1107,6 +1183,7 @@ finalize (GObject *object) + } + + avio_closep (&p->oc->pb); ++ av_freep (&p->fmt); + avformat_free_context (p->oc); + + g_clear_pointer (&o->user_data, g_free); diff --git a/SPECS/gegl04.spec b/SPECS/gegl04.spec index d034196..fcaee15 100644 --- a/SPECS/gegl04.spec +++ b/SPECS/gegl04.spec @@ -13,6 +13,7 @@ Source0: http://download.gimp.org/pub/gegl/%{apiver}/gegl-%{version}.tar. Patch0: gegl04-openexr.patch Patch1: gegl04-gtk.patch +Patch2: gegl04-ff.patch BuildRequires: chrpath BuildRequires: enscript