mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-12 19:18:44 +02:00
5acbdd2264
Reorganize the code such that the frame threading code does not call the decoders directly, but instead calls back into the generic decoding code. This avoids duplicating the logic that wraps the decoder invocation and allows receive_frame()-based decoders to use frame threading. Further work by Timo Rothenpieler <timo@rothenpieler.org>.
709 lines
24 KiB
C
709 lines
24 KiB
C
/*
|
|
* AVCodecContext functions for libavcodec
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* AVCodecContext functions for libavcodec
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "libavutil/avassert.h"
|
|
#include "libavutil/avstring.h"
|
|
#include "libavutil/bprint.h"
|
|
#include "libavutil/channel_layout.h"
|
|
#include "libavutil/emms.h"
|
|
#include "libavutil/fifo.h"
|
|
#include "libavutil/imgutils.h"
|
|
#include "libavutil/mem.h"
|
|
#include "libavutil/opt.h"
|
|
#include "libavutil/thread.h"
|
|
#include "avcodec.h"
|
|
#include "avcodec_internal.h"
|
|
#include "bsf.h"
|
|
#include "codec_desc.h"
|
|
#include "codec_internal.h"
|
|
#include "decode.h"
|
|
#include "encode.h"
|
|
#include "frame_thread_encoder.h"
|
|
#include "hwconfig.h"
|
|
#include "internal.h"
|
|
#include "refstruct.h"
|
|
#include "thread.h"
|
|
|
|
/**
|
|
* Maximum size in bytes of extradata.
|
|
* This value was chosen such that every bit of the buffer is
|
|
* addressable by a 32-bit signed integer as used by get_bits.
|
|
*/
|
|
#define FF_MAX_EXTRADATA_SIZE ((1 << 28) - AV_INPUT_BUFFER_PADDING_SIZE)
|
|
|
|
const SideDataMap ff_sd_global_map[] = {
|
|
{ AV_PKT_DATA_REPLAYGAIN , AV_FRAME_DATA_REPLAYGAIN },
|
|
{ AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX },
|
|
{ AV_PKT_DATA_SPHERICAL, AV_FRAME_DATA_SPHERICAL },
|
|
{ AV_PKT_DATA_STEREO3D, AV_FRAME_DATA_STEREO3D },
|
|
{ AV_PKT_DATA_AUDIO_SERVICE_TYPE, AV_FRAME_DATA_AUDIO_SERVICE_TYPE },
|
|
{ AV_PKT_DATA_MASTERING_DISPLAY_METADATA, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA },
|
|
{ AV_PKT_DATA_CONTENT_LIGHT_LEVEL, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL },
|
|
{ AV_PKT_DATA_ICC_PROFILE, AV_FRAME_DATA_ICC_PROFILE },
|
|
{ AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT,AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT },
|
|
{ AV_PKT_DATA_NB },
|
|
};
|
|
|
|
|
|
int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
size_t offset = i * size;
|
|
int r = func(c, FF_PTR_ADD((char *)arg, offset));
|
|
if (ret)
|
|
ret[i] = r;
|
|
}
|
|
emms_c();
|
|
return 0;
|
|
}
|
|
|
|
int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2, int jobnr, int threadnr), void *arg, int *ret, int count)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
int r = func(c, arg, i, 0);
|
|
if (ret)
|
|
ret[i] = r;
|
|
}
|
|
emms_c();
|
|
return 0;
|
|
}
|
|
|
|
static AVMutex codec_mutex = AV_MUTEX_INITIALIZER;
|
|
|
|
static void lock_avcodec(const FFCodec *codec)
|
|
{
|
|
if (codec->caps_internal & FF_CODEC_CAP_NOT_INIT_THREADSAFE && codec->init)
|
|
ff_mutex_lock(&codec_mutex);
|
|
}
|
|
|
|
static void unlock_avcodec(const FFCodec *codec)
|
|
{
|
|
if (codec->caps_internal & FF_CODEC_CAP_NOT_INIT_THREADSAFE && codec->init)
|
|
ff_mutex_unlock(&codec_mutex);
|
|
}
|
|
|
|
static int64_t get_bit_rate(AVCodecContext *ctx)
|
|
{
|
|
int64_t bit_rate;
|
|
int bits_per_sample;
|
|
|
|
switch (ctx->codec_type) {
|
|
case AVMEDIA_TYPE_VIDEO:
|
|
case AVMEDIA_TYPE_DATA:
|
|
case AVMEDIA_TYPE_SUBTITLE:
|
|
case AVMEDIA_TYPE_ATTACHMENT:
|
|
bit_rate = ctx->bit_rate;
|
|
break;
|
|
case AVMEDIA_TYPE_AUDIO:
|
|
bits_per_sample = av_get_bits_per_sample(ctx->codec_id);
|
|
if (bits_per_sample) {
|
|
bit_rate = ctx->sample_rate * (int64_t)ctx->ch_layout.nb_channels;
|
|
if (bit_rate > INT64_MAX / bits_per_sample) {
|
|
bit_rate = 0;
|
|
} else
|
|
bit_rate *= bits_per_sample;
|
|
} else
|
|
bit_rate = ctx->bit_rate;
|
|
break;
|
|
default:
|
|
bit_rate = 0;
|
|
break;
|
|
}
|
|
return bit_rate;
|
|
}
|
|
|
|
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
|
|
{
|
|
int ret = 0;
|
|
AVCodecInternal *avci;
|
|
const FFCodec *codec2;
|
|
|
|
if (avcodec_is_open(avctx))
|
|
return 0;
|
|
|
|
if (!codec && !avctx->codec) {
|
|
av_log(avctx, AV_LOG_ERROR, "No codec provided to avcodec_open2()\n");
|
|
return AVERROR(EINVAL);
|
|
}
|
|
if (codec && avctx->codec && codec != avctx->codec) {
|
|
av_log(avctx, AV_LOG_ERROR, "This AVCodecContext was allocated for %s, "
|
|
"but %s passed to avcodec_open2()\n", avctx->codec->name, codec->name);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
if (!codec)
|
|
codec = avctx->codec;
|
|
codec2 = ffcodec(codec);
|
|
|
|
if ((avctx->codec_type != AVMEDIA_TYPE_UNKNOWN && avctx->codec_type != codec->type) ||
|
|
(avctx->codec_id != AV_CODEC_ID_NONE && avctx->codec_id != codec->id)) {
|
|
av_log(avctx, AV_LOG_ERROR, "Codec type or id mismatches\n");
|
|
return AVERROR(EINVAL);
|
|
}
|
|
|
|
avctx->codec_type = codec->type;
|
|
avctx->codec_id = codec->id;
|
|
avctx->codec = codec;
|
|
|
|
if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE)
|
|
return AVERROR(EINVAL);
|
|
|
|
avci = av_codec_is_decoder(codec) ?
|
|
ff_decode_internal_alloc() :
|
|
ff_encode_internal_alloc();
|
|
if (!avci) {
|
|
ret = AVERROR(ENOMEM);
|
|
goto end;
|
|
}
|
|
avctx->internal = avci;
|
|
|
|
avci->buffer_frame = av_frame_alloc();
|
|
avci->buffer_pkt = av_packet_alloc();
|
|
if (!avci->buffer_frame || !avci->buffer_pkt) {
|
|
ret = AVERROR(ENOMEM);
|
|
goto free_and_end;
|
|
}
|
|
|
|
if (codec2->priv_data_size > 0) {
|
|
if (!avctx->priv_data) {
|
|
avctx->priv_data = av_mallocz(codec2->priv_data_size);
|
|
if (!avctx->priv_data) {
|
|
ret = AVERROR(ENOMEM);
|
|
goto free_and_end;
|
|
}
|
|
if (codec->priv_class) {
|
|
*(const AVClass **)avctx->priv_data = codec->priv_class;
|
|
av_opt_set_defaults(avctx->priv_data);
|
|
}
|
|
}
|
|
if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, options)) < 0)
|
|
goto free_and_end;
|
|
} else {
|
|
avctx->priv_data = NULL;
|
|
}
|
|
if ((ret = av_opt_set_dict(avctx, options)) < 0)
|
|
goto free_and_end;
|
|
|
|
if (avctx->codec_whitelist && av_match_list(codec->name, avctx->codec_whitelist, ',') <= 0) {
|
|
av_log(avctx, AV_LOG_ERROR, "Codec (%s) not on whitelist \'%s\'\n", codec->name, avctx->codec_whitelist);
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
|
|
// only call ff_set_dimensions() for non H.264/VP6F/DXV codecs so as not to overwrite previously setup dimensions
|
|
if (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height &&
|
|
(avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F || avctx->codec_id == AV_CODEC_ID_DXV))) {
|
|
if (avctx->coded_width && avctx->coded_height)
|
|
ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
|
|
else if (avctx->width && avctx->height)
|
|
ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
|
|
if (ret < 0)
|
|
goto free_and_end;
|
|
}
|
|
|
|
if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height)
|
|
&& ( av_image_check_size2(avctx->coded_width, avctx->coded_height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0
|
|
|| av_image_check_size2(avctx->width, avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0)) {
|
|
av_log(avctx, AV_LOG_WARNING, "Ignoring invalid width/height values\n");
|
|
ff_set_dimensions(avctx, 0, 0);
|
|
}
|
|
|
|
if (avctx->width > 0 && avctx->height > 0) {
|
|
if (av_image_check_sar(avctx->width, avctx->height,
|
|
avctx->sample_aspect_ratio) < 0) {
|
|
av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n",
|
|
avctx->sample_aspect_ratio.num,
|
|
avctx->sample_aspect_ratio.den);
|
|
avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
|
|
}
|
|
}
|
|
|
|
if (avctx->sample_rate < 0) {
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid sample rate: %d\n", avctx->sample_rate);
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
if (avctx->block_align < 0) {
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid block align: %d\n", avctx->block_align);
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
|
|
/* AV_CODEC_CAP_CHANNEL_CONF is a decoder-only flag; so the code below
|
|
* in particular checks that nb_channels is set for all audio encoders. */
|
|
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && !avctx->ch_layout.nb_channels
|
|
&& !(codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)) {
|
|
av_log(avctx, AV_LOG_ERROR, "%s requires channel layout to be set\n",
|
|
av_codec_is_decoder(codec) ? "Decoder" : "Encoder");
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
if (avctx->ch_layout.nb_channels && !av_channel_layout_check(&avctx->ch_layout)) {
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid channel layout\n");
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
if (avctx->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) {
|
|
av_log(avctx, AV_LOG_ERROR, "Too many channels: %d\n", avctx->ch_layout.nb_channels);
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
|
|
avctx->frame_num = 0;
|
|
avctx->codec_descriptor = avcodec_descriptor_get(avctx->codec_id);
|
|
|
|
if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
|
|
avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
|
|
const char *codec_string = av_codec_is_encoder(codec) ? "encoder" : "decoder";
|
|
const AVCodec *codec2;
|
|
av_log(avctx, AV_LOG_ERROR,
|
|
"The %s '%s' is experimental but experimental codecs are not enabled, "
|
|
"add '-strict %d' if you want to use it.\n",
|
|
codec_string, codec->name, FF_COMPLIANCE_EXPERIMENTAL);
|
|
codec2 = av_codec_is_encoder(codec) ? avcodec_find_encoder(codec->id) : avcodec_find_decoder(codec->id);
|
|
if (!(codec2->capabilities & AV_CODEC_CAP_EXPERIMENTAL))
|
|
av_log(avctx, AV_LOG_ERROR, "Alternatively use the non experimental %s '%s'.\n",
|
|
codec_string, codec2->name);
|
|
ret = AVERROR_EXPERIMENTAL;
|
|
goto free_and_end;
|
|
}
|
|
|
|
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO &&
|
|
(!avctx->time_base.num || !avctx->time_base.den)) {
|
|
avctx->time_base.num = 1;
|
|
avctx->time_base.den = avctx->sample_rate;
|
|
}
|
|
|
|
if (av_codec_is_encoder(avctx->codec))
|
|
ret = ff_encode_preinit(avctx);
|
|
else
|
|
ret = ff_decode_preinit(avctx);
|
|
if (ret < 0)
|
|
goto free_and_end;
|
|
|
|
if (HAVE_THREADS && !avci->frame_thread_encoder) {
|
|
/* Frame-threaded decoders call FFCodec.init for their child contexts. */
|
|
lock_avcodec(codec2);
|
|
ret = ff_thread_init(avctx);
|
|
unlock_avcodec(codec2);
|
|
if (ret < 0) {
|
|
goto free_and_end;
|
|
}
|
|
}
|
|
if (!HAVE_THREADS && !(codec2->caps_internal & FF_CODEC_CAP_AUTO_THREADS))
|
|
avctx->thread_count = 1;
|
|
|
|
if (!(avctx->active_thread_type & FF_THREAD_FRAME) ||
|
|
avci->frame_thread_encoder) {
|
|
if (codec2->init) {
|
|
lock_avcodec(codec2);
|
|
ret = codec2->init(avctx);
|
|
unlock_avcodec(codec2);
|
|
if (ret < 0) {
|
|
avci->needs_close = codec2->caps_internal & FF_CODEC_CAP_INIT_CLEANUP;
|
|
goto free_and_end;
|
|
}
|
|
}
|
|
avci->needs_close = 1;
|
|
}
|
|
|
|
ret=0;
|
|
|
|
if (av_codec_is_decoder(avctx->codec)) {
|
|
if (!avctx->bit_rate)
|
|
avctx->bit_rate = get_bit_rate(avctx);
|
|
|
|
/* validate channel layout from the decoder */
|
|
if ((avctx->ch_layout.nb_channels && !av_channel_layout_check(&avctx->ch_layout)) ||
|
|
avctx->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) {
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
if (avctx->bits_per_coded_sample < 0) {
|
|
ret = AVERROR(EINVAL);
|
|
goto free_and_end;
|
|
}
|
|
}
|
|
if (codec->priv_class)
|
|
av_assert0(*(const AVClass **)avctx->priv_data == codec->priv_class);
|
|
|
|
end:
|
|
|
|
return ret;
|
|
free_and_end:
|
|
ff_codec_close(avctx);
|
|
goto end;
|
|
}
|
|
|
|
void avcodec_flush_buffers(AVCodecContext *avctx)
|
|
{
|
|
AVCodecInternal *avci = avctx->internal;
|
|
|
|
if (av_codec_is_encoder(avctx->codec)) {
|
|
int caps = avctx->codec->capabilities;
|
|
|
|
if (!(caps & AV_CODEC_CAP_ENCODER_FLUSH)) {
|
|
// Only encoders that explicitly declare support for it can be
|
|
// flushed. Otherwise, this is a no-op.
|
|
av_log(avctx, AV_LOG_WARNING, "Ignoring attempt to flush encoder "
|
|
"that doesn't support it\n");
|
|
return;
|
|
}
|
|
ff_encode_flush_buffers(avctx);
|
|
} else
|
|
ff_decode_flush_buffers(avctx);
|
|
|
|
avci->draining = 0;
|
|
avci->draining_done = 0;
|
|
if (avci->buffer_frame)
|
|
av_frame_unref(avci->buffer_frame);
|
|
if (avci->buffer_pkt)
|
|
av_packet_unref(avci->buffer_pkt);
|
|
|
|
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME &&
|
|
!avci->is_frame_mt)
|
|
ff_thread_flush(avctx);
|
|
else if (ffcodec(avctx->codec)->flush)
|
|
ffcodec(avctx->codec)->flush(avctx);
|
|
}
|
|
|
|
void avsubtitle_free(AVSubtitle *sub)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sub->num_rects; i++) {
|
|
AVSubtitleRect *const rect = sub->rects[i];
|
|
|
|
av_freep(&rect->data[0]);
|
|
av_freep(&rect->data[1]);
|
|
av_freep(&rect->data[2]);
|
|
av_freep(&rect->data[3]);
|
|
av_freep(&rect->text);
|
|
av_freep(&rect->ass);
|
|
|
|
av_freep(&sub->rects[i]);
|
|
}
|
|
|
|
av_freep(&sub->rects);
|
|
|
|
memset(sub, 0, sizeof(*sub));
|
|
}
|
|
|
|
av_cold void ff_codec_close(AVCodecContext *avctx)
|
|
{
|
|
int i;
|
|
|
|
if (!avctx)
|
|
return;
|
|
|
|
if (avcodec_is_open(avctx)) {
|
|
AVCodecInternal *avci = avctx->internal;
|
|
|
|
if (CONFIG_FRAME_THREAD_ENCODER &&
|
|
avci->frame_thread_encoder && avctx->thread_count > 1) {
|
|
ff_frame_thread_encoder_free(avctx);
|
|
}
|
|
if (HAVE_THREADS && avci->thread_ctx)
|
|
ff_thread_free(avctx);
|
|
if (avci->needs_close && ffcodec(avctx->codec)->close)
|
|
ffcodec(avctx->codec)->close(avctx);
|
|
avci->byte_buffer_size = 0;
|
|
av_freep(&avci->byte_buffer);
|
|
av_frame_free(&avci->buffer_frame);
|
|
av_packet_free(&avci->buffer_pkt);
|
|
av_packet_free(&avci->last_pkt_props);
|
|
|
|
av_packet_free(&avci->in_pkt);
|
|
av_frame_free(&avci->in_frame);
|
|
av_frame_free(&avci->recon_frame);
|
|
|
|
ff_refstruct_unref(&avci->pool);
|
|
ff_refstruct_pool_uninit(&avci->progress_frame_pool);
|
|
|
|
ff_hwaccel_uninit(avctx);
|
|
|
|
av_bsf_free(&avci->bsf);
|
|
|
|
#if FF_API_DROPCHANGED
|
|
av_channel_layout_uninit(&avci->initial_ch_layout);
|
|
#endif
|
|
|
|
#if CONFIG_LCMS2
|
|
ff_icc_context_uninit(&avci->icc);
|
|
#endif
|
|
|
|
av_freep(&avctx->internal);
|
|
}
|
|
|
|
for (i = 0; i < avctx->nb_coded_side_data; i++)
|
|
av_freep(&avctx->coded_side_data[i].data);
|
|
av_freep(&avctx->coded_side_data);
|
|
avctx->nb_coded_side_data = 0;
|
|
av_frame_side_data_free(&avctx->decoded_side_data,
|
|
&avctx->nb_decoded_side_data);
|
|
|
|
av_buffer_unref(&avctx->hw_frames_ctx);
|
|
av_buffer_unref(&avctx->hw_device_ctx);
|
|
|
|
if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
|
|
av_opt_free(avctx->priv_data);
|
|
av_opt_free(avctx);
|
|
av_freep(&avctx->priv_data);
|
|
if (av_codec_is_encoder(avctx->codec)) {
|
|
av_freep(&avctx->extradata);
|
|
avctx->extradata_size = 0;
|
|
} else if (av_codec_is_decoder(avctx->codec))
|
|
av_freep(&avctx->subtitle_header);
|
|
|
|
avctx->codec = NULL;
|
|
avctx->active_thread_type = 0;
|
|
}
|
|
|
|
#if FF_API_AVCODEC_CLOSE
|
|
int avcodec_close(AVCodecContext *avctx)
|
|
{
|
|
ff_codec_close(avctx);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static const char *unknown_if_null(const char *str)
|
|
{
|
|
return str ? str : "unknown";
|
|
}
|
|
|
|
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
|
|
{
|
|
const char *codec_type;
|
|
const char *codec_name;
|
|
const char *profile = NULL;
|
|
AVBPrint bprint;
|
|
int64_t bitrate;
|
|
int new_line = 0;
|
|
AVRational display_aspect_ratio;
|
|
const char *separator = enc->dump_separator ? (const char *)enc->dump_separator : ", ";
|
|
const char *str;
|
|
|
|
if (!buf || buf_size <= 0)
|
|
return;
|
|
av_bprint_init_for_buffer(&bprint, buf, buf_size);
|
|
codec_type = av_get_media_type_string(enc->codec_type);
|
|
codec_name = avcodec_get_name(enc->codec_id);
|
|
profile = avcodec_profile_name(enc->codec_id, enc->profile);
|
|
|
|
av_bprintf(&bprint, "%s: %s", codec_type ? codec_type : "unknown",
|
|
codec_name);
|
|
buf[0] ^= 'a' ^ 'A'; /* first letter in uppercase */
|
|
|
|
if (enc->codec && strcmp(enc->codec->name, codec_name))
|
|
av_bprintf(&bprint, " (%s)", enc->codec->name);
|
|
|
|
if (profile)
|
|
av_bprintf(&bprint, " (%s)", profile);
|
|
if ( enc->codec_type == AVMEDIA_TYPE_VIDEO
|
|
&& av_log_get_level() >= AV_LOG_VERBOSE
|
|
&& enc->refs)
|
|
av_bprintf(&bprint, ", %d reference frame%s",
|
|
enc->refs, enc->refs > 1 ? "s" : "");
|
|
|
|
if (enc->codec_tag)
|
|
av_bprintf(&bprint, " (%s / 0x%04X)",
|
|
av_fourcc2str(enc->codec_tag), enc->codec_tag);
|
|
|
|
switch (enc->codec_type) {
|
|
case AVMEDIA_TYPE_VIDEO:
|
|
{
|
|
unsigned len;
|
|
|
|
av_bprintf(&bprint, "%s%s", separator,
|
|
enc->pix_fmt == AV_PIX_FMT_NONE ? "none" :
|
|
unknown_if_null(av_get_pix_fmt_name(enc->pix_fmt)));
|
|
|
|
av_bprint_chars(&bprint, '(', 1);
|
|
len = bprint.len;
|
|
|
|
/* The following check ensures that '(' has been written
|
|
* and therefore allows us to erase it if it turns out
|
|
* to be unnecessary. */
|
|
if (!av_bprint_is_complete(&bprint))
|
|
return;
|
|
|
|
if (enc->bits_per_raw_sample && enc->pix_fmt != AV_PIX_FMT_NONE &&
|
|
enc->bits_per_raw_sample < av_pix_fmt_desc_get(enc->pix_fmt)->comp[0].depth)
|
|
av_bprintf(&bprint, "%d bpc, ", enc->bits_per_raw_sample);
|
|
if (enc->color_range != AVCOL_RANGE_UNSPECIFIED &&
|
|
(str = av_color_range_name(enc->color_range)))
|
|
av_bprintf(&bprint, "%s, ", str);
|
|
|
|
if (enc->colorspace != AVCOL_SPC_UNSPECIFIED ||
|
|
enc->color_primaries != AVCOL_PRI_UNSPECIFIED ||
|
|
enc->color_trc != AVCOL_TRC_UNSPECIFIED) {
|
|
const char *col = unknown_if_null(av_color_space_name(enc->colorspace));
|
|
const char *pri = unknown_if_null(av_color_primaries_name(enc->color_primaries));
|
|
const char *trc = unknown_if_null(av_color_transfer_name(enc->color_trc));
|
|
if (strcmp(col, pri) || strcmp(col, trc)) {
|
|
new_line = 1;
|
|
av_bprintf(&bprint, "%s/%s/%s, ", col, pri, trc);
|
|
} else
|
|
av_bprintf(&bprint, "%s, ", col);
|
|
}
|
|
|
|
if (enc->field_order != AV_FIELD_UNKNOWN) {
|
|
const char *field_order = "progressive";
|
|
if (enc->field_order == AV_FIELD_TT)
|
|
field_order = "top first";
|
|
else if (enc->field_order == AV_FIELD_BB)
|
|
field_order = "bottom first";
|
|
else if (enc->field_order == AV_FIELD_TB)
|
|
field_order = "top coded first (swapped)";
|
|
else if (enc->field_order == AV_FIELD_BT)
|
|
field_order = "bottom coded first (swapped)";
|
|
|
|
av_bprintf(&bprint, "%s, ", field_order);
|
|
}
|
|
|
|
if (av_log_get_level() >= AV_LOG_VERBOSE &&
|
|
enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED &&
|
|
(str = av_chroma_location_name(enc->chroma_sample_location)))
|
|
av_bprintf(&bprint, "%s, ", str);
|
|
|
|
if (len == bprint.len) {
|
|
bprint.str[len - 1] = '\0';
|
|
bprint.len--;
|
|
} else {
|
|
if (bprint.len - 2 < bprint.size) {
|
|
/* Erase the last ", " */
|
|
bprint.len -= 2;
|
|
bprint.str[bprint.len] = '\0';
|
|
}
|
|
av_bprint_chars(&bprint, ')', 1);
|
|
}
|
|
}
|
|
|
|
if (enc->width) {
|
|
av_bprintf(&bprint, "%s%dx%d", new_line ? separator : ", ",
|
|
enc->width, enc->height);
|
|
|
|
if (av_log_get_level() >= AV_LOG_VERBOSE &&
|
|
enc->coded_width && enc->coded_height &&
|
|
(enc->width != enc->coded_width ||
|
|
enc->height != enc->coded_height))
|
|
av_bprintf(&bprint, " (%dx%d)",
|
|
enc->coded_width, enc->coded_height);
|
|
|
|
if (enc->sample_aspect_ratio.num) {
|
|
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
|
|
enc->width * (int64_t)enc->sample_aspect_ratio.num,
|
|
enc->height * (int64_t)enc->sample_aspect_ratio.den,
|
|
1024 * 1024);
|
|
av_bprintf(&bprint, " [SAR %d:%d DAR %d:%d]",
|
|
enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den,
|
|
display_aspect_ratio.num, display_aspect_ratio.den);
|
|
}
|
|
if (av_log_get_level() >= AV_LOG_DEBUG) {
|
|
int g = av_gcd(enc->time_base.num, enc->time_base.den);
|
|
av_bprintf(&bprint, ", %d/%d",
|
|
enc->time_base.num / g, enc->time_base.den / g);
|
|
}
|
|
}
|
|
if (encode) {
|
|
av_bprintf(&bprint, ", q=%d-%d", enc->qmin, enc->qmax);
|
|
} else {
|
|
if (enc->properties & FF_CODEC_PROPERTY_CLOSED_CAPTIONS)
|
|
av_bprintf(&bprint, ", Closed Captions");
|
|
if (enc->properties & FF_CODEC_PROPERTY_FILM_GRAIN)
|
|
av_bprintf(&bprint, ", Film Grain");
|
|
if (enc->properties & FF_CODEC_PROPERTY_LOSSLESS)
|
|
av_bprintf(&bprint, ", lossless");
|
|
}
|
|
break;
|
|
case AVMEDIA_TYPE_AUDIO:
|
|
av_bprintf(&bprint, "%s", separator);
|
|
|
|
if (enc->sample_rate) {
|
|
av_bprintf(&bprint, "%d Hz, ", enc->sample_rate);
|
|
}
|
|
av_channel_layout_describe_bprint(&enc->ch_layout, &bprint);
|
|
if (enc->sample_fmt != AV_SAMPLE_FMT_NONE &&
|
|
(str = av_get_sample_fmt_name(enc->sample_fmt))) {
|
|
av_bprintf(&bprint, ", %s", str);
|
|
}
|
|
if ( enc->bits_per_raw_sample > 0
|
|
&& enc->bits_per_raw_sample != av_get_bytes_per_sample(enc->sample_fmt) * 8)
|
|
av_bprintf(&bprint, " (%d bit)", enc->bits_per_raw_sample);
|
|
if (av_log_get_level() >= AV_LOG_VERBOSE) {
|
|
if (enc->initial_padding)
|
|
av_bprintf(&bprint, ", delay %d", enc->initial_padding);
|
|
if (enc->trailing_padding)
|
|
av_bprintf(&bprint, ", padding %d", enc->trailing_padding);
|
|
}
|
|
break;
|
|
case AVMEDIA_TYPE_DATA:
|
|
if (av_log_get_level() >= AV_LOG_DEBUG) {
|
|
int g = av_gcd(enc->time_base.num, enc->time_base.den);
|
|
if (g)
|
|
av_bprintf(&bprint, ", %d/%d",
|
|
enc->time_base.num / g, enc->time_base.den / g);
|
|
}
|
|
break;
|
|
case AVMEDIA_TYPE_SUBTITLE:
|
|
if (enc->width)
|
|
av_bprintf(&bprint, ", %dx%d", enc->width, enc->height);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
if (encode) {
|
|
if (enc->flags & AV_CODEC_FLAG_PASS1)
|
|
av_bprintf(&bprint, ", pass 1");
|
|
if (enc->flags & AV_CODEC_FLAG_PASS2)
|
|
av_bprintf(&bprint, ", pass 2");
|
|
}
|
|
bitrate = get_bit_rate(enc);
|
|
if (bitrate != 0) {
|
|
av_bprintf(&bprint, ", %"PRId64" kb/s", bitrate / 1000);
|
|
} else if (enc->rc_max_rate > 0) {
|
|
av_bprintf(&bprint, ", max. %"PRId64" kb/s", enc->rc_max_rate / 1000);
|
|
}
|
|
}
|
|
|
|
int avcodec_is_open(AVCodecContext *s)
|
|
{
|
|
return !!s->internal;
|
|
}
|
|
|
|
int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
|
{
|
|
av_frame_unref(frame);
|
|
|
|
if (av_codec_is_decoder(avctx->codec))
|
|
return ff_decode_receive_frame(avctx, frame);
|
|
return ff_encode_receive_frame(avctx, frame);
|
|
}
|