/* * generic decoding-related code * * 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
*/
/** * This is set to AV_FRAME_FLAG_KEY for decoders of intra-only formats * (those whose codec descriptor has AV_CODEC_PROP_INTRA_ONLY set) * to set the flag generically.
*/ int intra_only_flag;
/** * This is set to AV_PICTURE_TYPE_I for intra only video decoders * and to AV_PICTURE_TYPE_NONE for other decoders. It is used to set * the AVFrame's pict_type before the decoder receives it.
*/ enum AVPictureType initial_pict_type;
/* to prevent infinite loop on errors when draining */ int nb_draining_errors;
/** * The caller has submitted a NULL packet on input.
*/ int draining_started;
int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far
int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far
int64_t pts_correction_last_pts; /// PTS of the last frame
int64_t pts_correction_last_dts; /// DTS of the last frame
/** * Bitmask indicating for which side data types we prefer user-supplied * (global or attached to packets) side data over bytestream.
*/
uint64_t side_data_pref_mask;
FFLCEVCContext *lcevc; int lcevc_frame; int width; int height;
} DecodeContext;
data = av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, &size); if (!data) return 0;
if (!(avctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE)) {
av_log(avctx, AV_LOG_ERROR, "This decoder does not support parameter " "changes, but PARAM_CHANGE side data was sent to it.\n");
ret = AVERROR(EINVAL); goto fail2;
}
if (size < 4) goto fail;
flags = bytestream_get_le32(&data);
size -= 4;
if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { if (size < 4) goto fail;
val = bytestream_get_le32(&data); if (val <= 0 || val > INT_MAX) {
av_log(avctx, AV_LOG_ERROR, "Invalid sample rate");
ret = AVERROR_INVALIDDATA; goto fail2;
}
avctx->sample_rate = val;
size -= 4;
} if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) { if (size < 8) goto fail;
avctx->width = bytestream_get_le32(&data);
avctx->height = bytestream_get_le32(&data);
size -= 8;
ret = ff_set_dimensions(avctx, avctx->width, avctx->height); if (ret < 0) goto fail2;
}
return 0;
fail:
av_log(avctx, AV_LOG_ERROR, "PARAM_CHANGE side data too small.\n");
ret = AVERROR_INVALIDDATA;
fail2: if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n"); if (avctx->err_recognition & AV_EF_EXPLODE) return ret;
} return 0;
}
staticint extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt)
{ int ret = 0;
av_packet_unref(avci->last_pkt_props); if (pkt) {
ret = av_packet_copy_props(avci->last_pkt_props, pkt); #if FF_API_FRAME_PKT if (!ret)
avci->last_pkt_props->stream_index = pkt->size; // Needed for ff_decode_frame_props(). #endif
} return ret;
}
ret = av_bsf_list_parse_str(codec->bsfs, &avci->bsf); if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "Error parsing decoder bitstream filters '%s': %s\n", codec->bsfs, av_err2str(ret)); if (ret != AVERROR(ENOMEM))
ret = AVERROR_BUG; goto fail;
}
/* We do not currently have an API for passing the input timebase into decoders, * but no filters used here should actually need it.
* So we make up some plausible-looking number (the MPEG 90kHz timebase) */
avci->bsf->time_base_in = (AVRational){ 1, 90000 };
ret = avcodec_parameters_from_context(avci->bsf->par_in, avctx); if (ret < 0) goto fail;
ret = av_bsf_init(avci->bsf); if (ret < 0) goto fail;
/* If we are a worker thread, get the next packet from the threading * context. Otherwise we are the main (user-facing) context, so we get the * next packet from the input filterchain.
*/ if (avctx->internal->is_frame_mt) return ff_thread_get_packet(avctx, pkt);
while (1) { int ret = decode_get_packet(avctx, pkt); if (ret == AVERROR(EAGAIN) &&
(!AVPACKET_IS_EMPTY(avci->buffer_pkt) || dc->draining_started)) {
ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt); if (ret >= 0) continue;
/** * Attempt to guess proper monotonic timestamps for decoded video frames * which might have incorrect times. Input timestamps may wrap around, in * which case the output will as well. * * @param pts the pts field of the decoded AVPacket, as passed through * AVFrame.pts * @param dts the dts field of the decoded AVPacket * @return one of the input values, may be AV_NOPTS_VALUE
*/ static int64_t guess_correct_pts(DecodeContext *dc,
int64_t reordered_pts, int64_t dts)
{
int64_t pts = AV_NOPTS_VALUE;
/* * The core of the receive_frame_wrapper for the decoders implementing * the simple API. Certain decoders might consume partial packets without * returning any output, so this function needs to be called in a loop until it * returns EAGAIN.
**/ staticinlineint decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, int64_t *discarded_samples)
{
AVCodecInternal *avci = avctx->internal;
DecodeContext *dc = decode_ctx(avci);
AVPacket *const pkt = avci->in_pkt; const FFCodec *const codec = ffcodec(avctx->codec); int got_frame, consumed; int ret;
if (!pkt->data && !avci->draining) {
av_packet_unref(pkt);
ret = ff_decode_get_packet(avctx, pkt); if (ret < 0 && ret != AVERROR_EOF) return ret;
}
// Some codecs (at least wma lossless) will crash when feeding drain packets // after EOF was signaled. if (avci->draining_done) return AVERROR_EOF;
if (!pkt->data &&
!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) return AVERROR_EOF;
if (ret == AVERROR(EAGAIN))
av_frame_unref(frame);
// FF_CODEC_CB_TYPE_DECODE decoders must not return AVERROR EAGAIN // code later will add AVERROR(EAGAIN) to a pointer
av_assert0(consumed != AVERROR(EAGAIN)); if (consumed < 0)
ret = consumed; if (consumed >= 0 && avctx->codec->type == AVMEDIA_TYPE_VIDEO)
consumed = pkt->size;
if (!ret)
av_assert0(frame->buf[0]); if (ret == AVERROR(EAGAIN))
ret = 0;
/* do not stop draining when got_frame != 0 or ret < 0 */ if (avci->draining && !got_frame) { if (ret < 0) { /* prevent infinite loop if a decoder wrongly always return error on draining */ /* reasonable nb_errors_max = maximum b frames + thread count */ int nb_errors_max = 20 + (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME ?
avctx->thread_count : 1);
if (decode_ctx(avci)->nb_draining_errors++ >= nb_errors_max) {
av_log(avctx, AV_LOG_ERROR, "Too many errors when draining, this is a bug. " "Stop draining and force EOF.\n");
avci->draining_done = 1;
ret = AVERROR_BUG;
}
} else {
avci->draining_done = 1;
}
}
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); if (!sd || !sd->size) return 0;
if (!avci->icc.avctx) {
ret = ff_icc_context_init(&avci->icc, avctx); if (ret < 0) return ret;
}
profile = cmsOpenProfileFromMemTHR(avci->icc.ctx, sd->data, sd->size); if (!profile) return AVERROR_INVALIDDATA;
ret = ff_icc_profile_sanitize(&avci->icc, profile); if (!ret)
ret = ff_icc_profile_read_primaries(&avci->icc, profile, &coeffs); if (!ret)
ret = ff_icc_profile_detect_transfer(&avci->icc, profile, &trc);
cmsCloseProfile(profile); if (ret < 0) return ret;
if (avctx->active_thread_type & FF_THREAD_FRAME)
ret = ff_thread_receive_frame(avctx, frame); else
ret = ff_decode_receive_frame_internal(avctx, frame);
/* preserve ret */
ok = detect_colorspace(avctx, frame); if (ok < 0) {
av_frame_unref(frame); return ok;
}
if (!ret) { if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { if (!frame->width)
frame->width = avctx->width; if (!frame->height)
frame->height = avctx->height;
}
ret = fill_frame_props(avctx, frame); if (ret < 0) {
av_frame_unref(frame); return ret;
}
/* the only case where decode data is not set should be decoders
* that do not call ff_get_buffer() */
av_assert0((frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) ||
!(avctx->codec->capabilities & AV_CODEC_CAP_DR1));
if (frame->private_ref) {
FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data;
if (fdd->post_process) {
ret = fdd->post_process(avctx, frame); if (ret < 0) {
av_frame_unref(frame); return ret;
}
}
}
}
/* free the per-frame decode data */
av_buffer_unref(&frame->private_ref);
return ret;
}
int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
{
AVCodecInternal *avci = avctx->internal;
DecodeContext *dc = decode_ctx(avci); int ret;
if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) return AVERROR(EINVAL);
if (dc->draining_started) return AVERROR_EOF;
if (avpkt && !avpkt->size && avpkt->data) return AVERROR(EINVAL);
if (avpkt && (avpkt->data || avpkt->side_data_elems)) { if (!AVPACKET_IS_EMPTY(avci->buffer_pkt)) return AVERROR(EAGAIN);
ret = av_packet_ref(avci->buffer_pkt, avpkt); if (ret < 0) return ret;
} else
dc->draining_started = 1;
if (!avci->buffer_frame->buf[0] && !dc->draining_started) {
ret = decode_receive_frame_internal(avctx, avci->buffer_frame); if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) return ret;
}
return 0;
}
staticint apply_cropping(AVCodecContext *avctx, AVFrame *frame)
{ /* make sure we are noisy about decoders returning invalid cropping data */ if (frame->crop_left >= INT_MAX - frame->crop_right ||
frame->crop_top >= INT_MAX - frame->crop_bottom ||
(frame->crop_left + frame->crop_right) >= frame->width ||
(frame->crop_top + frame->crop_bottom) >= frame->height) {
av_log(avctx, AV_LOG_WARNING, "Invalid cropping information set by a decoder: " "%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER"/%"SIZE_SPECIFIER" " "(frame size %dx%d). This is a bug, please report it\n",
frame->crop_left, frame->crop_right, frame->crop_top, frame->crop_bottom,
frame->width, frame->height);
frame->crop_left = 0;
frame->crop_right = 0;
frame->crop_top = 0;
frame->crop_bottom = 0; return 0;
}
// make sure frames returned to the caller are valid staticint frame_validate(AVCodecContext *avctx, AVFrame *frame)
{ if (!frame->buf[0] || frame->format < 0) goto fail;
switch (avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: if (frame->width <= 0 || frame->height <= 0) goto fail; break; case AVMEDIA_TYPE_AUDIO: if (!av_channel_layout_check(&frame->ch_layout) ||
frame->sample_rate <= 0) goto fail;
break; default: av_assert0(0);
}
return 0;
fail:
av_log(avctx, AV_LOG_ERROR, "An invalid frame was output by a decoder. " "This is a bug, please report it.\n"); return AVERROR_BUG;
}
int ff_decode_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{
AVCodecInternal *avci = avctx->internal; int ret;
if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) return AVERROR(EINVAL);
if (avci->buffer_frame->buf[0]) {
av_frame_move_ref(frame, avci->buffer_frame);
} else {
ret = decode_receive_frame_internal(avctx, frame); if (ret < 0) return ret;
}
ret = frame_validate(avctx, frame); if (ret < 0) goto fail;
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
ret = apply_cropping(avctx, frame); if (ret < 0) goto fail;
}
avctx->frame_num++;
#if FF_API_DROPCHANGED if (avctx->flags & AV_CODEC_FLAG_DROPCHANGED) {
if (avctx->frame_num == 1) {
avci->initial_format = frame->format; switch(avctx->codec_type) { case AVMEDIA_TYPE_VIDEO:
avci->initial_width = frame->width;
avci->initial_height = frame->height; break; case AVMEDIA_TYPE_AUDIO:
avci->initial_sample_rate = frame->sample_rate ? frame->sample_rate :
avctx->sample_rate;
ret = av_channel_layout_copy(&avci->initial_ch_layout, &frame->ch_layout); if (ret < 0) goto fail; break;
}
}
if (avctx->frame_num > 1) { int changed = avci->initial_format != frame->format;
if (inl >= INT_MAX / UTF8_MAX_BYTES - AV_INPUT_BUFFER_PADDING_SIZE) {
av_log(avctx, AV_LOG_ERROR, "Subtitles packet is too big for recoding\n"); return AVERROR(ERANGE);
}
cd = iconv_open("UTF-8", avctx->sub_charenc);
av_assert0(cd != (iconv_t)-1);
ret = av_new_packet(buf_pkt, inl * UTF8_MAX_BYTES); if (ret < 0) goto end;
ret = av_packet_copy_props(buf_pkt, inpkt); if (ret < 0) goto end;
outb = buf_pkt->data;
outl = buf_pkt->size;
for (unsigned i = 0; i < sub->num_rects; i++) { if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_IGNORE &&
sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) {
av_log(avctx, AV_LOG_ERROR, "Invalid UTF-8 in decoded subtitles text; " "maybe missing -sub_charenc option\n");
avsubtitle_free(sub);
*got_sub_ptr = 0; return AVERROR_INVALIDDATA;
}
}
if (*got_sub_ptr)
avctx->frame_num++;
}
return ret;
}
enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *avctx, constenum AVPixelFormat *fmt)
{ const AVPixFmtDescriptor *desc; const AVCodecHWConfig *config; int i, n;
// If a device was supplied when the codec was opened, assume that the // user wants to use it. if (avctx->hw_device_ctx && ffcodec(avctx->codec)->hw_configs) {
AVHWDeviceContext *device_ctx =
(AVHWDeviceContext*)avctx->hw_device_ctx->data; for (i = 0;; i++) {
config = &ffcodec(avctx->codec)->hw_configs[i]->public; if (!config) break; if (!(config->methods &
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) continue; if (device_ctx->type != config->device_type) continue; for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) { if (config->pix_fmt == fmt[n]) return fmt[n];
}
}
} // No device or other setup, so we have to choose from things which // don't any other external information.
// If the last element of the list is a software format, choose it // (this should be best software format if any exist). for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++);
desc = av_pix_fmt_desc_get(fmt[n - 1]); if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) return fmt[n - 1];
// Finally, traverse the list in order and choose the first entry // with no external dependencies (if there is no hardware configuration // information available then this just picks the first entry). for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) { for (i = 0;; i++) {
config = avcodec_get_hw_config(avctx->codec, i); if (!config) break; if (config->pix_fmt == fmt[n]) break;
} if (!config) { // No specific config available, so the decoder must be able // to handle this format without any additional setup. return fmt[n];
} if (config->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL) { // Usable with only internal setup. return fmt[n];
}
}
// Nothing is usable, give up. return AV_PIX_FMT_NONE;
}
int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, enum AVHWDeviceType dev_type)
{
AVHWDeviceContext *device_ctx;
AVHWFramesContext *frames_ctx; int ret;
if (!avctx->hwaccel) return AVERROR(ENOSYS);
if (avctx->hw_frames_ctx) return 0; if (!avctx->hw_device_ctx) {
av_log(avctx, AV_LOG_ERROR, "A hardware frames or device context is " "required for hardware accelerated decoding.\n"); return AVERROR(EINVAL);
}
device_ctx = (AVHWDeviceContext *)avctx->hw_device_ctx->data; if (device_ctx->type != dev_type) {
av_log(avctx, AV_LOG_ERROR, "Device type %s expected for hardware " "decoding, but got %s.\n", av_hwdevice_get_type_name(dev_type),
av_hwdevice_get_type_name(device_ctx->type)); return AVERROR(EINVAL);
}
ret = avcodec_get_hw_frames_parameters(avctx,
avctx->hw_device_ctx,
avctx->hwaccel->pix_fmt,
&avctx->hw_frames_ctx); if (ret < 0) return ret;
if (frames_ctx->initial_pool_size) { // We guarantee 4 base work surfaces. The function above guarantees 1 // (the absolute minimum), so add the missing count.
frames_ctx->initial_pool_size += 3;
}
ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); if (ret < 0) {
av_buffer_unref(&avctx->hw_frames_ctx); return ret;
}
return 0;
}
int avcodec_get_hw_frames_parameters(AVCodecContext *avctx,
AVBufferRef *device_ref, enum AVPixelFormat hw_pix_fmt,
AVBufferRef **out_frames_ref)
{
AVBufferRef *frames_ref = NULL; const AVCodecHWConfigInternal *hw_config; const FFHWAccel *hwa; int i, ret; bool clean_priv_data = false;
for (i = 0;; i++) {
hw_config = ffcodec(avctx->codec)->hw_configs[i]; if (!hw_config) return AVERROR(ENOENT); if (hw_config->public.pix_fmt == hw_pix_fmt) break;
}
hwa = hw_config->hwaccel; if (!hwa || !hwa->frame_params) return AVERROR(ENOENT);
frames_ref = av_hwframe_ctx_alloc(device_ref); if (!frames_ref) return AVERROR(ENOMEM);
if (!avctx->internal->hwaccel_priv_data) {
avctx->internal->hwaccel_priv_data =
av_mallocz(hwa->priv_data_size); if (!avctx->internal->hwaccel_priv_data) {
av_buffer_unref(&frames_ref); return AVERROR(ENOMEM);
}
clean_priv_data = true;
}
ret = hwa->frame_params(avctx, frames_ref); if (ret >= 0) {
AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frames_ref->data;
if (frames_ctx->initial_pool_size) { // If the user has requested that extra output surfaces be // available then add them here. if (avctx->extra_hw_frames > 0)
frames_ctx->initial_pool_size += avctx->extra_hw_frames;
// If frame threading is enabled then an extra surface per thread // is also required. if (avctx->active_thread_type & FF_THREAD_FRAME)
frames_ctx->initial_pool_size += avctx->thread_count;
}
if (!avctx->internal->hwaccel_priv_data && hwaccel->priv_data_size) {
avctx->internal->hwaccel_priv_data =
av_mallocz(hwaccel->priv_data_size); if (!avctx->internal->hwaccel_priv_data) return AVERROR(ENOMEM);
}
avctx->hwaccel = &hwaccel->p; if (hwaccel->init) {
err = hwaccel->init(avctx); if (err < 0) {
av_log(avctx, AV_LOG_ERROR, "Failed setup for format %s: " "hwaccel initialisation returned error.\n",
av_get_pix_fmt_name(hwaccel->p.pix_fmt));
av_freep(&avctx->internal->hwaccel_priv_data);
avctx->hwaccel = NULL; return err;
}
}
return 0;
}
void ff_hwaccel_uninit(AVCodecContext *avctx)
{ if (FF_HW_HAS_CB(avctx, uninit))
FF_HW_SIMPLE_CALL(avctx, uninit);
av_freep(&avctx->internal->hwaccel_priv_data);
avctx->hwaccel = NULL;
av_buffer_unref(&avctx->hw_frames_ctx);
}
int ff_get_format(AVCodecContext *avctx, constenum AVPixelFormat *fmt)
{ const AVPixFmtDescriptor *desc; enum AVPixelFormat *choices; enum AVPixelFormat ret, user_choice; const AVCodecHWConfigInternal *hw_config; const AVCodecHWConfig *config; int i, n, err;
// Find end of list. for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++); // Must contain at least one entry.
av_assert0(n >= 1); // If a software format is available, it must be the last entry.
desc = av_pix_fmt_desc_get(fmt[n - 1]); if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { // No software format is available.
} else {
avctx->sw_pix_fmt = fmt[n - 1];
}
for (;;) { // Remove the previous hwaccel, if there was one.
ff_hwaccel_uninit(avctx);
user_choice = avctx->get_format(avctx, choices); if (user_choice == AV_PIX_FMT_NONE) { // Explicitly chose nothing, give up.
ret = AV_PIX_FMT_NONE; break;
}
desc = av_pix_fmt_desc_get(user_choice); if (!desc) {
av_log(avctx, AV_LOG_ERROR, "Invalid format returned by " "get_format() callback.\n");
ret = AV_PIX_FMT_NONE; break;
}
av_log(avctx, AV_LOG_DEBUG, "Format %s chosen by get_format().\n",
desc->name);
for (i = 0; i < n; i++) { if (choices[i] == user_choice) break;
} if (i == n) {
av_log(avctx, AV_LOG_ERROR, "Invalid return from get_format(): " "%s not in possible list.\n", desc->name);
ret = AV_PIX_FMT_NONE; break;
}
if (ffcodec(avctx->codec)->hw_configs) { for (i = 0;; i++) {
hw_config = ffcodec(avctx->codec)->hw_configs[i]; if (!hw_config) break; if (hw_config->public.pix_fmt == user_choice) break;
}
} else {
hw_config = NULL;
}
if (!hw_config) { // No config available, so no extra setup required.
ret = user_choice; break;
}
config = &hw_config->public;
if (config->methods &
AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX &&
avctx->hw_frames_ctx) { const AVHWFramesContext *frames_ctx =
(AVHWFramesContext*)avctx->hw_frames_ctx->data; if (frames_ctx->format != user_choice) {
av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " "does not match the format of the provided frames " "context.\n", desc->name); goto try_again;
}
} elseif (config->methods &
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
avctx->hw_device_ctx) { const AVHWDeviceContext *device_ctx =
(AVHWDeviceContext*)avctx->hw_device_ctx->data; if (device_ctx->type != config->device_type) {
av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " "does not match the type of the provided device " "context.\n", desc->name); goto try_again;
}
} elseif (config->methods &
AV_CODEC_HW_CONFIG_METHOD_INTERNAL) { // Internal-only setup, no additional configuration.
} elseif (config->methods &
AV_CODEC_HW_CONFIG_METHOD_AD_HOC) { // Some ad-hoc configuration we can't see and can't check.
} else {
av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: " "missing configuration.\n", desc->name); goto try_again;
} if (hw_config->hwaccel) {
av_log(avctx, AV_LOG_DEBUG, "Format %s requires hwaccel %s " "initialisation.\n", desc->name, hw_config->hwaccel->p.name);
err = hwaccel_init(avctx, hw_config->hwaccel); if (err < 0) goto try_again;
}
ret = user_choice; break;
try_again:
av_log(avctx, AV_LOG_DEBUG, "Format %s not usable, retrying " "get_format() without it.\n", desc->name); for (i = 0; i < n; i++) { if (choices[i] == user_choice) break;
} for (; i + 1 < n; i++)
choices[i] = choices[i + 1];
--n;
}
if (ret < 0)
ff_hwaccel_uninit(avctx);
av_freep(&choices); return ret;
}
staticconst AVPacketSideData*
packet_side_data_get(const AVPacketSideData *sd, int nb_sd, enum AVPacketSideDataType type)
{ for (int i = 0; i < nb_sd; i++) if (sd[i].type == type) return &sd[i];
sd_pkt = packet_side_data_get(sd_src, nb_sd_src, type_pkt); if (!sd_pkt) continue;
sd_frame = av_frame_get_side_data(dst, type_frame); if (sd_frame) { if (type_frame == AV_FRAME_DATA_STEREO3D) { int ret = side_data_stereo3d_merge(sd_frame, sd_pkt); if (ret < 0) return ret;
}
continue;
}
sd_frame = av_frame_new_side_data(dst, type_frame, sd_pkt->size); if (!sd_frame) return AVERROR(ENOMEM);
ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, ff_sd_global_map); if (ret < 0) return ret;
ret = side_data_map(frame, pkt->side_data, pkt->side_data_elems, sd); if (ret < 0) return ret;
add_metadata_from_side_data(pkt, frame);
if (pkt->flags & AV_PKT_FLAG_DISCARD) {
frame->flags |= AV_FRAME_FLAG_DISCARD;
}
if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { int ret = av_buffer_replace(&frame->opaque_ref, pkt->opaque_ref); if (ret < 0) return ret;
frame->opaque = pkt->opaque;
}
return 0;
}
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
{ int ret;
ret = side_data_map(frame, avctx->coded_side_data, avctx->nb_coded_side_data,
ff_sd_global_map); if (ret < 0) return ret;
if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { const AVPacket *pkt = avctx->internal->last_pkt_props;
ret = ff_decode_frame_props_from_pkt(avctx, frame, pkt); if (ret < 0) return ret; #if FF_API_FRAME_PKT
FF_DISABLE_DEPRECATION_WARNINGS
frame->pkt_size = pkt->stream_index;
FF_ENABLE_DEPRECATION_WARNINGS #endif
}
ret = fill_frame_props(avctx, frame); if (ret < 0) return ret;
staticvoid validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame)
{ if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { int i; int num_planes = av_pix_fmt_count_planes(frame->format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); int flags = desc ? desc->flags : 0; if (num_planes == 1 && (flags & AV_PIX_FMT_FLAG_PAL))
num_planes = 2; for (i = 0; i < num_planes; i++) {
av_assert0(frame->data[i]);
} // For formats without data like hwaccel allow unused pointers to be non-NULL. for (i = num_planes; num_planes > 0 && i < FF_ARRAY_ELEMS(frame->data); i++) { if (frame->data[i])
av_log(avctx, AV_LOG_ERROR, "Buffer returned by get_buffer2() did not zero unused plane pointers\n");
frame->data[i] = NULL;
}
}
}
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
{ const FFHWAccel *hwaccel = ffhwaccel(avctx->hwaccel); int override_dimensions = 1; int ret;
if ((flags & FF_REGET_BUFFER_FLAG_READONLY) || av_frame_is_writable(frame)) return ff_decode_frame_props(avctx, frame);
tmp = av_frame_alloc(); if (!tmp) return AVERROR(ENOMEM);
av_frame_move_ref(tmp, frame);
ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); if (ret < 0) {
av_frame_free(&tmp); return ret;
}
av_frame_copy(frame, tmp);
av_frame_free(&tmp);
return 0;
}
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
{ int ret = reget_buffer_internal(avctx, frame, flags); if (ret < 0)
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return ret;
}
int ff_decode_preinit(AVCodecContext *avctx)
{
AVCodecInternal *avci = avctx->internal;
DecodeContext *dc = decode_ctx(avci); int ret = 0;
dc->initial_pict_type = AV_PICTURE_TYPE_NONE; if (avctx->codec_descriptor->props & AV_CODEC_PROP_INTRA_ONLY) {
dc->intra_only_flag = AV_FRAME_FLAG_KEY; if (avctx->codec_type == AVMEDIA_TYPE_VIDEO)
dc->initial_pict_type = AV_PICTURE_TYPE_I;
}
/* if the decoder init function was already called previously,
* free the already allocated subtitle_header before overwriting it */
av_freep(&avctx->subtitle_header);
if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) {
av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
avctx->codec->max_lowres);
avctx->lowres = avctx->codec->max_lowres;
} if (avctx->sub_charenc) { if (avctx->codec_type != AVMEDIA_TYPE_SUBTITLE) {
av_log(avctx, AV_LOG_ERROR, "Character encoding is only " "supported with subtitles codecs\n"); return AVERROR(EINVAL);
} elseif (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB) {
av_log(avctx, AV_LOG_WARNING, "Codec '%s' is bitmap-based, " "subtitles character encoding will be ignored\n",
avctx->codec_descriptor->name);
avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_DO_NOTHING;
} else { /* input character encoding is set for a text based subtitle
* codec at this point */ if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_AUTOMATIC)
avctx->sub_charenc_mode = FF_SUB_CHARENC_MODE_PRE_DECODER;
if (avctx->sub_charenc_mode == FF_SUB_CHARENC_MODE_PRE_DECODER) { #if CONFIG_ICONV
iconv_t cd = iconv_open("UTF-8", avctx->sub_charenc); if (cd == (iconv_t)-1) {
ret = AVERROR(errno);
av_log(avctx, AV_LOG_ERROR, "Unable to open iconv context " "with input character encoding \"%s\"\n", avctx->sub_charenc); return ret;
}
iconv_close(cd); #else
av_log(avctx, AV_LOG_ERROR, "Character encoding subtitles " "conversion needs a libavcodec built with iconv support " "for this codec\n"); return AVERROR(ENOSYS); #endif
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.