1770 lines · 55.0 KB · C
RawDownload
/* * 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t