/* * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdbit.h> #include "libavutil/avassert.h"#include "libavutil/avstring.h"#include "libavutil/dict.h"#include "libavutil/error.h"#include "libavutil/log.h"#include "libavutil/mem.h"#include "libavutil/opt.h"#include "libavutil/pixdesc.h"#include "libavutil/pixfmt.h"#include "libavutil/stereo3d.h"#include "libavutil/time.h"#include "libavutil/timestamp.h" #include "libavcodec/avcodec.h"#include "libavcodec/codec.h" #include "ffmpeg.h" typedef struct DecoderPriv { Decoder dec; AVCodecContext *dec_ctx; AVFrame *frame; AVFrame *frame_tmp_ref; AVPacket *pkt; // override output video sample aspect ratio with this value AVRational sar_override; AVRational framerate_in; // a combination of DECODER_FLAG_*, provided to dec_open() int flags; int apply_cropping; enum AVPixelFormat hwaccel_pix_fmt; enum HWAccelID hwaccel_id; enum AVHWDeviceType hwaccel_device_type; enum AVPixelFormat hwaccel_output_format; // pts/estimated duration of the last decoded frame // * in decoder timebase for video, // * in last_frame_tb (may change during decoding) for audio int64_t last_frame_pts; int64_t last_frame_duration_est; AVRational last_frame_tb; int64_t last_filter_in_rescale_delta; int last_frame_sample_rate; /* previous decoded subtitles */ AVFrame *sub_prev[2]; AVFrame *sub_heartbeat; Scheduler *sch; unsigned sch_idx; // this decoder's index in decoders or -1 int index; void *log_parent; char log_name[32]; char *parent_name; // user specified decoder multiview options manually int multiview_user_config; struct { ViewSpecifier vs; unsigned out_idx; } *views_requested; int nb_views_requested; /* A map of view ID to decoder outputs. * MUST NOT be accessed outside of get_format()/get_buffer() */ struct { unsigned id; uintptr_t out_mask; } *view_map; int nb_view_map; struct { AVDictionary *opts; const AVCodec *codec; } standalone_init;} DecoderPriv; static DecoderPriv *dp_from_dec(Decoder *d){ return (DecoderPriv*)d;} // data that is local to the decoder thread and not visible outside of ittypedef struct DecThreadContext { AVFrame *frame; AVPacket *pkt;} DecThreadContext; void dec_free(Decoder **pdec){ Decoder *dec = *pdec; DecoderPriv *dp; if (!dec) return; dp = dp_from_dec(dec); avcodec_free_context(&dp->dec_ctx); av_frame_free(&dp->frame); av_frame_free(&dp->frame_tmp_ref); av_packet_free(&dp->pkt); av_dict_free(&dp->standalone_init.opts); for (int i = 0; i < FF_ARRAY_ELEMS(dp->sub_prev); i++) av_frame_free(&dp->sub_prev[i]); av_frame_free(&dp->sub_heartbeat); av_freep(&dp->parent_name); av_freep(&dp->views_requested); av_freep(&dp->view_map); av_freep(pdec);} static const char *dec_item_name(void *obj){ const DecoderPriv *dp = obj; return dp->log_name;} static const AVClass dec_class = { .class_name = "Decoder", .version = LIBAVUTIL_VERSION_INT, .parent_log_context_offset = offsetof(DecoderPriv, log_parent), .item_name = dec_item_name,}; static int decoder_thread(void *arg); static int dec_alloc(DecoderPriv **pdec, Scheduler *sch, int send_end_ts){ DecoderPriv *dp; int ret = 0; *pdec = NULL; dp = av_mallocz(sizeof(*dp)); if (!dp) return AVERROR(ENOMEM); dp->frame = av_frame_alloc(); if (!dp->frame) goto fail; dp->pkt = av_packet_alloc(); if (!dp->pkt) goto fail; dp->index = -1; dp->dec.class = &dec_class; dp->last_filter_in_rescale_delta = AV_NOPTS_VALUE; dp->last_frame_pts = AV_NOPTS_VALUE; dp->last_frame_tb = (AVRational){ 1, 1 }; dp->hwaccel_pix_fmt = AV_PIX_FMT_NONE; ret = sch_add_dec(sch, decoder_thread, dp, send_end_ts); if (ret < 0) goto fail; dp->sch = sch; dp->sch_idx = ret; *pdec = dp; return 0;fail: dec_free((Decoder**)&dp); return ret >= 0 ? AVERROR(ENOMEM) : ret;} static AVRational audio_samplerate_update(DecoderPriv *dp, const AVFrame *frame){ const int prev = dp->last_frame_tb.den; const int sr = frame->sample_rate; AVRational tb_new; int64_t gcd; if (frame->sample_rate == dp->last_frame_sample_rate) goto finish; gcd = av_gcd(prev, sr); if (prev / gcd >= INT_MAX / sr) { av_log(dp, AV_LOG_WARNING, "Audio timestamps cannot be represented exactly after " "sample rate change: %d -> %d\n", prev, sr); // LCM of 192000, 44100, allows to represent all common samplerates tb_new = (AVRational){ 1, 28224000 }; } else tb_new = (AVRational){ 1, prev / gcd * sr }; // keep the frame timebase if it is strictly better than // the samplerate-defined one if (frame->time_base.num == 1 && frame->time_base.den > tb_new.den && !(frame->time_base.den % tb_new.den)) tb_new = frame->time_base; if (dp->last_frame_pts != AV_NOPTS_VALUE) dp->last_frame_pts = av_rescale_q(dp->last_frame_pts, dp->last_frame_tb, tb_new); dp->last_frame_duration_est = av_rescale_q(dp->last_frame_duration_est, dp->last_frame_tb, tb_new); dp->last_frame_tb = tb_new; dp->last_frame_sample_rate = frame->sample_rate; finish: return dp->last_frame_tb;} static void audio_ts_process(DecoderPriv *dp, AVFrame *frame){ AVRational tb_filter = (AVRational){1, frame->sample_rate}; AVRational tb; int64_t pts_pred; // on samplerate change, choose a new internal timebase for timestamp // generation that can represent timestamps from all the samplerates // seen so far tb = audio_samplerate_update(dp, frame); pts_pred = dp->last_frame_pts == AV_NOPTS_VALUE ? 0 : dp->last_frame_pts + dp->last_frame_duration_est; if (frame->pts == AV_NOPTS_VALUE) { frame->pts = pts_pred; frame->time_base = tb; } else if (dp->last_frame_pts != AV_NOPTS_VALUE && frame->pts > av_rescale_q_rnd(pts_pred, tb, frame->time_base, AV_ROUND_UP)) { // there was a gap in timestamps, reset conversion state dp->last_filter_in_rescale_delta = AV_NOPTS_VALUE; } frame->pts = av_rescale_delta(frame->time_base, frame->pts, tb, frame->nb_samples, &dp->last_filter_in_rescale_delta, tb); dp->last_frame_pts = frame->pts; dp->last_frame_duration_est = av_rescale_q(frame->nb_samples, tb_filter, tb); // finally convert to filtering timebase frame->pts = av_rescale_q(frame->pts, tb, tb_filter); frame->duration = frame->nb_samples; frame->time_base = tb_filter;} static int64_t video_duration_estimate(const DecoderPriv *dp, const AVFrame *frame){ const int ts_unreliable = dp->flags & DECODER_FLAG_TS_UNRELIABLE; const int fr_forced = dp->flags & DECODER_FLAG_FRAMERATE_FORCED; int64_t codec_duration = 0; // difference between this and last frame's timestamps const int64_t ts_diff = (frame->pts != AV_NOPTS_VALUE && dp->last_frame_pts != AV_NOPTS_VALUE) ? frame->pts - dp->last_frame_pts : -1; // XXX lavf currently makes up frame durations when they are not provided by // the container. As there is no way to reliably distinguish real container // durations from the fake made-up ones, we use heuristics based on whether // the container has timestamps. Eventually lavf should stop making up // durations, then this should be simplified. // frame duration is unreliable (typically guessed by lavf) when it is equal // to 1 and the actual duration of the last frame is more than 2x larger const int duration_unreliable = frame->duration == 1 && ts_diff > 2 * frame->duration; // prefer frame duration for containers with timestamps if (fr_forced || (frame->duration > 0 && !ts_unreliable && !duration_unreliable)) return frame->duration; if (dp->dec_ctx->framerate.den && dp->dec_ctx->framerate.num) { int fields = frame->repeat_pict + 2; AVRational field_rate = av_mul_q(dp->dec_ctx->framerate, (AVRational){ 2, 1 }); codec_duration = av_rescale_q(fields, av_inv_q(field_rate), frame->time_base); } // prefer codec-layer duration for containers without timestamps if (codec_duration > 0 && ts_unreliable) return codec_duration; // when timestamps are available, repeat last frame's actual duration // (i.e. pts difference between this and last frame) if (ts_diff > 0) return ts_diff; // try frame/codec duration if (frame->duration > 0) return frame->duration; if (codec_duration > 0) return codec_duration; // try average framerate if (dp->framerate_in.num && dp->framerate_in.den) { int64_t d = av_rescale_q(1, av_inv_q(dp->framerate_in), frame->time_base); if (d > 0) return d; } // last resort is last frame's estimated duration, and 1 return FFMAX(dp->last_frame_duration_est, 1);} static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input){ DecoderPriv *dp = avctx->opaque; AVFrame *output = NULL; enum AVPixelFormat output_format = dp->hwaccel_output_format; int err; if (input->format == output_format) { // Nothing to do. return 0; } output = av_frame_alloc(); if (!output) return AVERROR(ENOMEM); output->format = output_format; err = av_hwframe_transfer_data(output, input, 0); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to " "output frame: %d.\n", err); goto fail; } err = av_frame_copy_props(output, input); if (err < 0) { av_frame_unref(output); goto fail; } av_frame_unref(input); av_frame_move_ref(input, output); av_frame_free(&output); return 0; fail: av_frame_free(&output); return err;} static int video_frame_process(DecoderPriv *dp, AVFrame *frame, unsigned *outputs_mask){#if FFMPEG_OPT_TOP if (dp->flags & DECODER_FLAG_TOP_FIELD_FIRST) { av_log(dp, AV_LOG_WARNING, "-top is deprecated, use the setfield filter instead\n"); frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; }#endif if (frame->format == dp->hwaccel_pix_fmt) { int err = hwaccel_retrieve_data(dp->dec_ctx, frame); if (err < 0) return err; } frame->pts = frame->best_effort_timestamp; // forced fixed framerate if (dp->flags & DECODER_FLAG_FRAMERATE_FORCED) { frame->pts = AV_NOPTS_VALUE; frame->duration = 1; frame->time_base = av_inv_q(dp->framerate_in); } // no timestamp available - extrapolate from previous frame duration if (frame->pts == AV_NOPTS_VALUE) frame->pts = dp->last_frame_pts == AV_NOPTS_VALUE ? 0 : dp->last_frame_pts + dp->last_frame_duration_est; // update timestamp history dp->last_frame_duration_est = video_duration_estimate(dp, frame); dp->last_frame_pts = frame->pts; dp->last_frame_tb = frame->time_base; if (debug_ts) { av_log(dp, AV_LOG_INFO, "decoder -> pts:%s pts_time:%s " "pkt_dts:%s pkt_dts_time:%s " "duration:%s duration_time:%s " "keyframe:%d frame_type:%d time_base:%d/%d\n", av_ts2str(frame->pts), av_ts2timestr(frame->pts, &frame->time_base), av_ts2str(frame->pkt_dts), av_ts2timestr(frame->pkt_dts, &frame->time_base), av_ts2str(frame->duration), av_ts2timestr(frame->duration, &frame->time_base), !!(frame->flags & AV_FRAME_FLAG_KEY), frame->pict_type, frame->time_base.num, frame->time_base.den); } if (dp->sar_override.num) frame->sample_aspect_ratio = dp->sar_override; if (dp->apply_cropping) { // lavfi does not require aligned frame data int ret = av_frame_apply_cropping(frame, AV_FRAME_CROP_UNALIGNED); if (ret < 0) { av_log(dp, AV_LOG_ERROR, "Error applying decoder cropping\n"); return ret; } } if (frame->opaque) *outputs_mask = (uintptr_t)frame->opaque; return 0;} static int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src){ int ret = AVERROR_BUG; AVSubtitle tmp = { .format = src->format, .start_display_time = src->start_display_time, .end_display_time = src->end_display_time, .num_rects = 0, .rects = NULL, .pts = src->pts }; if (!src->num_rects) goto success; if (!(tmp.rects = av_calloc(src->num_rects, sizeof(*tmp.rects)))) return AVERROR(ENOMEM); for (int i = 0; i < src->num_rects; i++) { AVSubtitleRect *src_rect = src->rects[i]; AVSubtitleRect *dst_rect; if (!(dst_rect = tmp.rects[i] = av_mallocz(sizeof(*tmp.rects[0])))) { ret = AVERROR(ENOMEM); goto cleanup; } tmp.num_rects++; dst_rect->type = src_rect->type; dst_rect->flags = src_rect->flags; dst_rect->x = src_rect->x; dst_rect->y = src_rect->y; dst_rect->w = src_rect->w; dst_rect->h = src_rect->h; dst_rect->nb_colors = src_rect->nb_colors; if (src_rect->text) if (!(dst_rect->text = av_strdup(src_rect->text))) { ret = AVERROR(ENOMEM); goto cleanup; } if (src_rect->ass) if (!(dst_rect->ass = av_strdup(src_rect->ass))) { ret = AVERROR(ENOMEM);Lines 1–500 of 1770. Load more
/* * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdbit.h> #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" #include "libavutil/error.h" #include "libavutil/log.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" #include "libavutil/stereo3d.h" #include "libavutil/time.h" #include "libavutil/timestamp.h" #include "libavcodec/avcodec.h" #include "libavcodec/codec.h" #include "ffmpeg.h" typedef struct DecoderPriv { Decoder dec; AVCodecContext *dec_ctx; AVFrame *frame; AVFrame *frame_tmp_ref; AVPacket *pkt; // override output video sample aspect ratio with this value AVRational sar_override; AVRational framerate_in; // a combination of DECODER_FLAG_*, provided to dec_open() int flags; int apply_cropping; enum AVPixelFormat hwaccel_pix_fmt; enum HWAccelID hwaccel_id; enum AVHWDeviceType hwaccel_device_type; enum AVPixelFormat hwaccel_output_format; // pts/estimated duration of the last decoded frame // * in decoder timebase for video, // * in last_frame_tb (may change during decoding) for audio int64_t last_frame_pts; int64_t last_frame_duration_est; AVRational last_frame_tb; int64_t last_filter_in_rescale_delta; int last_frame_sample_rate; /* previous decoded subtitles */ AVFrame *sub_prev[2]; AVFrame *sub_heartbeat; Scheduler *sch; unsigned sch_idx; // this decoder's index in decoders or -1 int index; void *log_parent; char log_name[32]; char *parent_name; // user specified decoder multiview options manually int multiview_user_config; struct { ViewSpecifier vs; unsigned out_idx; } *views_requested; int nb_views_requested; /* A map of view ID to decoder outputs. * MUST NOT be accessed outside of get_format()/get_buffer() */ struct { unsigned id; uintptr_t out_mask; } *view_map; int nb_view_map; struct { AVDictionary *opts; const AVCodec *codec; } standalone_init; } DecoderPriv; static DecoderPriv *dp_from_dec(Decoder *d) { return (DecoderPriv*)d; } // data that is local to the decoder thread and not visible outside of it typedef struct DecThreadContext { AVFrame *frame; AVPacket *pkt; } DecThreadContext; void dec_free(Decoder **pdec) { Decoder *dec = *pdec; DecoderPriv *dp; if (!dec) return; dp = dp_from_dec(dec); avcodec_free_context(&dp->dec_ctx); av_frame_free(&dp->frame); av_frame_free(&dp->frame_tmp_ref); av_packet_free(&dp->pkt); av_dict_free(&dp->standalone_init.opts); for (int i = 0; i < FF_ARRAY_ELEMS(dp->sub_prev); i++) av_frame_free(&dp->sub_prev[i]); av_frame_free(&dp->sub_heartbeat); av_freep(&dp->parent_name); av_freep(&dp->views_requested); av_freep(&dp->view_map); av_freep(pdec); } static const char *dec_item_name(void *obj) { const DecoderPriv *dp = obj; return dp->log_name; } static const AVClass dec_class = { .class_name = "Decoder", .version = LIBAVUTIL_VERSION_INT, .parent_log_context_offset = offsetof(DecoderPriv, log_parent), .item_name = dec_item_name, }; static int decoder_thread(void *arg); static int dec_alloc(DecoderPriv **pdec, Scheduler *sch, int send_end_ts) { DecoderPriv *dp; int ret = 0; *pdec = NULL; dp = av_mallocz(sizeof(*dp)); if (!dp) return AVERROR(ENOMEM); dp->frame = av_frame_alloc(); if (!dp->frame) goto fail; dp->pkt = av_packet_alloc(); if (!dp->pkt) goto fail; dp->index = -1; dp->dec.class = &dec_class; dp->last_filter_in_rescale_delta = AV_NOPTS_VALUE; dp->last_frame_pts = AV_NOPTS_VALUE; dp->last_frame_tb = (AVRational){ 1, 1 }; dp->hwaccel_pix_fmt = AV_PIX_FMT_NONE; ret = sch_add_dec(sch, decoder_thread, dp, send_end_ts); if (ret < 0) goto fail; dp->sch = sch; dp->sch_idx = ret; *pdec = dp; return 0; fail: dec_free((Decoder**)&dp); return ret >= 0 ? AVERROR(ENOMEM) : ret; } static AVRational audio_samplerate_update(DecoderPriv *dp, const AVFrame *frame) { const int prev = dp->last_frame_tb.den; const int sr = frame->sample_rate; AVRational tb_new; int64_t gcd; if (frame->sample_rate == dp->last_frame_sample_rate) goto finish; gcd = av_gcd(prev, sr); if (prev / gcd >= INT_MAX / sr) { av_log(dp, AV_LOG_WARNING, "Audio timestamps cannot be represented exactly after " "sample rate change: %d -> %d\n", prev, sr); // LCM of 192000, 44100, allows to represent all common samplerates tb_new = (AVRational){ 1, 28224000 }; } else tb_new = (AVRational){ 1, prev / gcd * sr }; // keep the frame timebase if it is strictly better than // the samplerate-defined one if (frame->time_base.num == 1 && frame->time_base.den > tb_new.den && !(frame->time_base.den % tb_new.den)) tb_new = frame->time_base; if (dp->last_frame_pts != AV_NOPTS_VALUE) dp->last_frame_pts = av_rescale_q(dp->last_frame_pts, dp->last_frame_tb, tb_new); dp->last_frame_duration_est = av_rescale_q(dp->last_frame_duration_est, dp->last_frame_tb, tb_new); dp->last_frame_tb = tb_new; dp->last_frame_sample_rate = frame->sample_rate; finish: return dp->last_frame_tb; } static void audio_ts_process(DecoderPriv *dp, AVFrame *frame) { AVRational tb_filter = (AVRational){1, frame->sample_rate}; AVRational tb; int64_t pts_pred; // on samplerate change, choose a new internal timebase for timestamp // generation that can represent timestamps from all the samplerates // seen so far tb = audio_samplerate_update(dp, frame); pts_pred = dp->last_frame_pts == AV_NOPTS_VALUE ? 0 : dp->last_frame_pts + dp->last_frame_duration_est; if (frame->pts == AV_NOPTS_VALUE) { frame->pts = pts_pred; frame->time_base = tb; } else if (dp->last_frame_pts != AV_NOPTS_VALUE && frame->pts > av_rescale_q_rnd(pts_pred, tb, frame->time_base, AV_ROUND_UP)) { // there was a gap in timestamps, reset conversion state dp->last_filter_in_rescale_delta = AV_NOPTS_VALUE; } frame->pts = av_rescale_delta(frame->time_base, frame->pts, tb, frame->nb_samples, &dp->last_filter_in_rescale_delta, tb); dp->last_frame_pts = frame->pts; dp->last_frame_duration_est = av_rescale_q(frame->nb_samples, tb_filter, tb); // finally convert to filtering timebase frame->pts = av_rescale_q(frame->pts, tb, tb_filter); frame->duration = frame->nb_samples; frame->time_base = tb_filter; } static int64_t video_duration_estimate(const DecoderPriv *dp, const AVFrame *frame) { const int ts_unreliable = dp->flags & DECODER_FLAG_TS_UNRELIABLE; const int fr_forced = dp->flags & DECODER_FLAG_FRAMERATE_FORCED; int64_t codec_duration = 0; // difference between this and last frame's timestamps const int64_t ts_diff = (frame->pts != AV_NOPTS_VALUE && dp->last_frame_pts != AV_NOPTS_VALUE) ? frame->pts - dp->last_frame_pts : -1; // XXX lavf currently makes up frame durations when they are not provided by // the container. As there is no way to reliably distinguish real container // durations from the fake made-up ones, we use heuristics based on whether // the container has timestamps. Eventually lavf should stop making up // durations, then this should be simplified. // frame duration is unreliable (typically guessed by lavf) when it is equal // to 1 and the actual duration of the last frame is more than 2x larger const int duration_unreliable = frame->duration == 1 && ts_diff > 2 * frame->duration; // prefer frame duration for containers with timestamps if (fr_forced || (frame->duration > 0 && !ts_unreliable && !duration_unreliable)) return frame->duration; if (dp->dec_ctx->framerate.den && dp->dec_ctx->framerate.num) { int fields = frame->repeat_pict + 2; AVRational field_rate = av_mul_q(dp->dec_ctx->framerate, (AVRational){ 2, 1 }); codec_duration = av_rescale_q(fields, av_inv_q(field_rate), frame->time_base); } // prefer codec-layer duration for containers without timestamps if (codec_duration > 0 && ts_unreliable) return codec_duration; // when timestamps are available, repeat last frame's actual duration // (i.e. pts difference between this and last frame) if (ts_diff > 0) return ts_diff; // try frame/codec duration if (frame->duration > 0) return frame->duration; if (codec_duration > 0) return codec_duration; // try average framerate if (dp->framerate_in.num && dp->framerate_in.den) { int64_t d = av_rescale_q(1, av_inv_q(dp->framerate_in), frame->time_base); if (d > 0) return d; } // last resort is last frame's estimated duration, and 1 return FFMAX(dp->last_frame_duration_est, 1); } static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) { DecoderPriv *dp = avctx->opaque; AVFrame *output = NULL; enum AVPixelFormat output_format = dp->hwaccel_output_format; int err; if (input->format == output_format) { // Nothing to do. return 0; } output = av_frame_alloc(); if (!output) return AVERROR(ENOMEM); output->format = output_format; err = av_hwframe_transfer_data(output, input, 0); if (err < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to " "output frame: %d.\n", err); goto fail; } err = av_frame_copy_props(output, input); if (err < 0) { av_frame_unref(output); goto fail; } av_frame_unref(input); av_frame_move_ref(input, output); av_frame_free(&output); return 0; fail: av_frame_free(&output); return err; } static int video_frame_process(DecoderPriv *dp, AVFrame *frame, unsigned *outputs_mask) { #if FFMPEG_OPT_TOP if (dp->flags & DECODER_FLAG_TOP_FIELD_FIRST) { av_log(dp, AV_LOG_WARNING, "-top is deprecated, use the setfield filter instead\n"); frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST; } #endif if (frame->format == dp->hwaccel_pix_fmt) { int err = hwaccel_retrieve_data(dp->dec_ctx, frame); if (err < 0) return err; } frame->pts = frame->best_effort_timestamp; // forced fixed framerate if (dp->flags & DECODER_FLAG_FRAMERATE_FORCED) { frame->pts = AV_NOPTS_VALUE; frame->duration = 1; frame->time_base = av_inv_q(dp->framerate_in); } // no timestamp available - extrapolate from previous frame duration if (frame->pts == AV_NOPTS_VALUE) frame->pts = dp->last_frame_pts == AV_NOPTS_VALUE ? 0 : dp->last_frame_pts + dp->last_frame_duration_est; // update timestamp history dp->last_frame_duration_est = video_duration_estimate(dp, frame); dp->last_frame_pts = frame->pts; dp->last_frame_tb = frame->time_base; if (debug_ts) { av_log(dp, AV_LOG_INFO, "decoder -> pts:%s pts_time:%s " "pkt_dts:%s pkt_dts_time:%s " "duration:%s duration_time:%s " "keyframe:%d frame_type:%d time_base:%d/%d\n", av_ts2str(frame->pts), av_ts2timestr(frame->pts, &frame->time_base), av_ts2str(frame->pkt_dts), av_ts2timestr(frame->pkt_dts, &frame->time_base), av_ts2str(frame->duration), av_ts2timestr(frame->duration, &frame->time_base), !!(frame->flags & AV_FRAME_FLAG_KEY), frame->pict_type, frame->time_base.num, frame->time_base.den); } if (dp->sar_override.num) frame->sample_aspect_ratio = dp->sar_override; if (dp->apply_cropping) { // lavfi does not require aligned frame data int ret = av_frame_apply_cropping(frame, AV_FRAME_CROP_UNALIGNED); if (ret < 0) { av_log(dp, AV_LOG_ERROR, "Error applying decoder cropping\n"); return ret; } } if (frame->opaque) *outputs_mask = (uintptr_t)frame->opaque; return 0; } static int copy_av_subtitle(AVSubtitle *dst, const AVSubtitle *src) { int ret = AVERROR_BUG; AVSubtitle tmp = { .format = src->format, .start_display_time = src->start_display_time, .end_display_time = src->end_display_time, .num_rects = 0, .rects = NULL, .pts = src->pts }; if (!src->num_rects) goto success; if (!(tmp.rects = av_calloc(src->num_rects, sizeof(*tmp.rects)))) return AVERROR(ENOMEM); for (int i = 0; i < src->num_rects; i++) { AVSubtitleRect *src_rect = src->rects[i]; AVSubtitleRect *dst_rect; if (!(dst_rect = tmp.rects[i] = av_mallocz(sizeof(*tmp.rects[0])))) { ret = AVERROR(ENOMEM); goto cleanup; } tmp.num_rects++; dst_rect->type = src_rect->type; dst_rect->flags = src_rect->flags; dst_rect->x = src_rect->x; dst_rect->y = src_rect->y; dst_rect->w = src_rect->w; dst_rect->h = src_rect->h; dst_rect->nb_colors = src_rect->nb_colors; if (src_rect->text) if (!(dst_rect->text = av_strdup(src_rect->text))) { ret = AVERROR(ENOMEM); goto cleanup; } if (src_rect->ass) if (!(dst_rect->ass = av_strdup(src_rect->ass))) { ret = AVERROR(ENOMEM);