[FFmpeg-devel] [PATCH 2/5] ffmpeg: use the write_uncoded_frame() API.

Michael Niedermayer michaelni at gmx.at
Sun Jan 19 02:32:00 CET 2014


On Thu, Jan 16, 2014 at 08:20:29PM +0100, Nicolas George wrote:
> Signed-off-by: Nicolas George <george at nsup.org>
> ---
>  ffmpeg.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
>  ffmpeg.h |  1 +
>  2 files changed, 55 insertions(+), 9 deletions(-)
> 
> 
> Changed: the order between av_frame_clone() and asserts.
> 
> 
> diff --git a/ffmpeg.c b/ffmpeg.c
> index 5ccbf10..7ac1f12 100644
> --- a/ffmpeg.c
> +++ b/ffmpeg.c
> @@ -163,6 +163,9 @@ static struct termios oldtty;
>  static int restore_tty;
>  #endif
>  
> +/* Use a different value than the library. */
> +#define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 - (int)sizeof(AVFrame))
> +
>  static void free_input_threads(void);
>  
>  
> @@ -644,7 +647,23 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
>                );
>      }
>  
> -    ret = av_interleaved_write_frame(s, pkt);
> +    if (ost->uncoded_frame) {
> +        AVFrame *frame;
> +        av_assert0(!ost->encoding_needed);
> +        av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
> +        if (!(frame = av_frame_clone((AVFrame *)pkt->data))) {
> +            ret = AVERROR(ENOMEM);
> +        } else {
> +            frame->pts = frame->pkt_pts = pkt->pts;
> +            frame->pkt_dts = pkt->dts;
> +            av_frame_set_pkt_duration(frame, pkt->duration);
> +            ret = av_interleaved_write_uncoded_frame(s, pkt->stream_index, frame);
> +            pkt->size = 0;
> +            pkt->data = NULL;
> +        }
> +    } else {
> +        ret = av_interleaved_write_frame(s, pkt);
> +    }
>      if (ret < 0) {
>          print_error("av_interleaved_write_frame()", ret);
>          exit_program(1);
> @@ -693,6 +712,8 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
>          frame->pts = ost->sync_opts;
>      ost->sync_opts = frame->pts + frame->nb_samples;
>  
> +    if (ost->encoding_needed) {
> +        /* TODO reindent */
>      av_assert0(pkt.size || !pkt.data);
>      update_benchmark(NULL);
>      if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
> @@ -700,6 +721,13 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
>          exit_program(1);
>      }
>      update_benchmark("encode_audio %d.%d", ost->file_index, ost->index);
> +    } else {
> +        av_assert0(ost->uncoded_frame);
> +        pkt.pts = pkt.dts = frame->pts;
> +        pkt.data = (void *)frame;
> +        pkt.size = UNCODED_FRAME_PACKET_SIZE;
> +        got_packet = 1;
> +    }
>  
>      if (got_packet) {
>          if (pkt.pts != AV_NOPTS_VALUE)
> @@ -923,7 +951,7 @@ static void do_video_out(AVFormatContext *s,
>              in_picture->top_field_first = !!ost->top_field_first;
>  
>          if (in_picture->interlaced_frame) {
> -            if (enc->codec->id == AV_CODEC_ID_MJPEG)
> +            if (enc->codec && enc->codec->id == AV_CODEC_ID_MJPEG)
>                  enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB;
>              else
>                  enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
> @@ -968,6 +996,8 @@ static void do_video_out(AVFormatContext *s,
>              av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time);
>          }
>  
> +        if (ost->encoding_needed) {
> +            /* TODO reindent */
>          update_benchmark(NULL);
>          ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet);
>          update_benchmark("encode_video %d.%d", ost->file_index, ost->index);
> @@ -975,6 +1005,13 @@ static void do_video_out(AVFormatContext *s,
>              av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
>              exit_program(1);
>          }
> +        } else {
> +            av_assert0(ost->uncoded_frame);
> +            pkt.pts = pkt.dts = in_picture->pts;
> +            pkt.data = (void *)in_picture;
> +            pkt.size = UNCODED_FRAME_PACKET_SIZE;
> +            got_packet = 1;
> +        }
>  
>          if (got_packet) {
>              if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY))
> @@ -1117,7 +1154,8 @@ static int reap_filters(void)
>                  break;
>              case AVMEDIA_TYPE_AUDIO:
>                  filtered_frame->pts = frame_pts;
> -                if (!(ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE) &&
> +                if (!(ost->st->codec->codec &&
> +                      (ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) &&
>                      ost->st->codec->channels != av_frame_get_channels(filtered_frame)) {
>                      av_log(NULL, AV_LOG_ERROR,
>                             "Audio filter graph output is not normalized and encoder does not support parameter changes\n");
> @@ -1978,7 +2016,8 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
>      for (i = 0; pkt && i < nb_output_streams; i++) {
>          OutputStream *ost = output_streams[i];
>  
> -        if (!check_output_constraints(ist, ost) || ost->encoding_needed)
> +        if (!check_output_constraints(ist, ost) || ost->encoding_needed ||
> +            ost->uncoded_frame)
>              continue;
>  
>          do_streamcopy(ist, ost, pkt);
> @@ -2411,6 +2450,9 @@ static int transcode_init(void)
>                  abort();
>              }
>          } else {
> +            ret = av_write_uncoded_frame_query(oc, ost->index);
> +            if (ret < 0) {
> +                /* TODO reindent */
>              if (!ost->enc)
>                  ost->enc = avcodec_find_encoder(codec->codec_id);
>              if (!ost->enc) {
> @@ -2420,10 +2462,15 @@ static int transcode_init(void)
>                  ret = AVERROR(EINVAL);
>                  goto dump_format;
>              }
> +                ost->encoding_needed = 1;
> +            } else {
> +                av_log(oc, AV_LOG_VERBOSE, "Using uncoded frame output "
> +                       "for stream #%d\n", ost->index);
> +                ost->uncoded_frame = 1;
> +            }
>  
>              if (ist)
>                  ist->decoding_needed++;
> -            ost->encoding_needed = 1;
>  
>              if (!ost->filter &&
>                  (codec->codec_type == AVMEDIA_TYPE_VIDEO ||

why do you need all this special casing and complexity compared to
ramiros patch ?

I mean why isnt a simple if() / else around
av_interleaved_write_frame() enough ?

maybe with setting CODEC_FLAG2_NO_OUTPUT and supporting that in
raw encoders to skip filling the AVPacket.data but that could also
be ommited.

also if pkt.size is set like this then the output statistics will
be wrong unless i miss something (didnt test)


[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No great genius has ever existed without some touch of madness. -- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140119/55888602/attachment.asc>


More information about the ffmpeg-devel mailing list