#include "config.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
+#include "libavutil/bprint.h"
#include "libavutil/imgutils.h"
#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "frame_thread_encoder.h"
#include "internal.h"
#include "thread.h"
-#if CONFIG_ICONV
-# include <iconv.h>
-#endif
#include "libavutil/ffversion.h"
const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION;
ff_mutex_unlock(&codec_mutex);
}
-#if FF_API_LOCKMGR
-int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
-{
- return 0;
-}
-#endif
-
static int64_t get_bit_rate(AVCodecContext *ctx)
{
int64_t bit_rate;
}
avctx->internal = avci;
-#if FF_API_OLD_ENCDEC
- avci->to_free = av_frame_alloc();
- avci->compat_decode_frame = av_frame_alloc();
- avci->compat_encode_packet = av_packet_alloc();
- if (!avci->to_free || !avci->compat_decode_frame || !avci->compat_encode_packet) {
- ret = AVERROR(ENOMEM);
- goto free_and_end;
- }
-#endif
avci->buffer_frame = av_frame_alloc();
avci->buffer_pkt = av_packet_alloc();
avci->es.in_frame = av_frame_alloc();
ret = AVERROR(EINVAL);
goto free_and_end;
}
- if (av_codec_is_decoder(codec) &&
- codec->type == AVMEDIA_TYPE_AUDIO &&
- !(codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF) &&
- avctx->channels == 0) {
- av_log(avctx, AV_LOG_ERROR, "Decoder requires channel count but channels not set\n");
- ret = AVERROR(EINVAL);
- goto free_and_end;
- }
if (avctx->sample_rate < 0) {
av_log(avctx, AV_LOG_ERROR, "Invalid sample rate: %d\n", avctx->sample_rate);
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)
av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n");
if (!HAVE_THREADS && !(codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS))
avctx->thread_count = 1;
- 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 ( avctx->codec->init && (!(avctx->active_thread_type&FF_THREAD_FRAME)
|| avci->frame_thread_encoder)) {
ret = avctx->codec->init(avctx);
ret = AVERROR(EINVAL);
goto free_and_end;
}
- 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");
- ret = AVERROR(EINVAL);
- goto free_and_end;
- } else if (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);
- goto free_and_end;
- }
- 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");
- ret = AVERROR(ENOSYS);
- goto free_and_end;
-#endif
- }
- }
- }
#if FF_API_AVCTX_TIMEBASE
if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
av_opt_free(avctx);
if (av_codec_is_encoder(avctx->codec)) {
-#if FF_API_CODED_FRAME
-FF_DISABLE_DEPRECATION_WARNINGS
- av_frame_free(&avctx->coded_frame);
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
av_freep(&avctx->extradata);
avctx->extradata_size = 0;
}
av_dict_free(&tmp);
av_freep(&avctx->priv_data);
- av_freep(&avctx->subtitle_header);
+ if (av_codec_is_decoder(avctx->codec))
+ av_freep(&avctx->subtitle_header);
-#if FF_API_OLD_ENCDEC
- av_frame_free(&avci->to_free);
- av_frame_free(&avci->compat_decode_frame);
- av_packet_free(&avci->compat_encode_packet);
-#endif
av_frame_free(&avci->buffer_frame);
av_packet_free(&avci->buffer_pkt);
av_packet_free(&avci->last_pkt_props);
avci->draining_done = 0;
avci->nb_draining_errors = 0;
av_frame_unref(avci->buffer_frame);
-#if FF_API_OLD_ENCDEC
- av_frame_unref(avci->compat_decode_frame);
- av_packet_unref(avci->compat_encode_packet);
-#endif
av_packet_unref(avci->buffer_pkt);
av_packet_unref(avci->last_pkt_props);
if (av_codec_is_decoder(avctx->codec))
av_bsf_flush(avci->bsf);
-
-#if FF_API_OLD_ENCDEC
-FF_DISABLE_DEPRECATION_WARNINGS
- if (!avctx->refcounted_frames)
- av_frame_unref(avci->to_free);
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
}
void avsubtitle_free(AVSubtitle *sub)
return 0;
if (avcodec_is_open(avctx)) {
+ AVCodecInternal *avci = avctx->internal;
+
if (CONFIG_FRAME_THREAD_ENCODER &&
- avctx->internal->frame_thread_encoder && avctx->thread_count > 1) {
+ avci->frame_thread_encoder && avctx->thread_count > 1) {
ff_frame_thread_encoder_free(avctx);
}
- if (HAVE_THREADS && avctx->internal->thread_ctx)
+ if (HAVE_THREADS && avci->thread_ctx)
ff_thread_free(avctx);
if (avctx->codec && avctx->codec->close)
avctx->codec->close(avctx);
- avctx->internal->byte_buffer_size = 0;
- av_freep(&avctx->internal->byte_buffer);
-#if FF_API_OLD_ENCDEC
- av_frame_free(&avctx->internal->to_free);
- av_frame_free(&avctx->internal->compat_decode_frame);
- av_packet_free(&avctx->internal->compat_encode_packet);
-#endif
- av_frame_free(&avctx->internal->buffer_frame);
- av_packet_free(&avctx->internal->buffer_pkt);
- av_packet_unref(avctx->internal->last_pkt_props);
- while (av_fifo_size(avctx->internal->pkt_props) >=
- sizeof(*avctx->internal->last_pkt_props)) {
- av_fifo_generic_read(avctx->internal->pkt_props,
- avctx->internal->last_pkt_props,
- sizeof(*avctx->internal->last_pkt_props),
- NULL);
- av_packet_unref(avctx->internal->last_pkt_props);
+ avci->byte_buffer_size = 0;
+ av_freep(&avci->byte_buffer);
+ av_frame_free(&avci->buffer_frame);
+ av_packet_free(&avci->buffer_pkt);
+ av_packet_unref(avci->last_pkt_props);
+ while (av_fifo_size(avci->pkt_props) >= sizeof(*avci->last_pkt_props)) {
+ av_fifo_generic_read(avci->pkt_props, avci->last_pkt_props,
+ sizeof(*avci->last_pkt_props), NULL);
+ av_packet_unref(avci->last_pkt_props);
}
- av_packet_free(&avctx->internal->last_pkt_props);
- av_fifo_freep(&avctx->internal->pkt_props);
+ av_packet_free(&avci->last_pkt_props);
+ av_fifo_freep(&avci->pkt_props);
- av_packet_free(&avctx->internal->ds.in_pkt);
- av_frame_free(&avctx->internal->es.in_frame);
+ av_packet_free(&avci->ds.in_pkt);
+ av_frame_free(&avci->es.in_frame);
- av_buffer_unref(&avctx->internal->pool);
+ av_buffer_unref(&avci->pool);
if (avctx->hwaccel && avctx->hwaccel->uninit)
avctx->hwaccel->uninit(avctx);
- av_freep(&avctx->internal->hwaccel_priv_data);
+ av_freep(&avci->hwaccel_priv_data);
- av_bsf_free(&avctx->internal->bsf);
+ av_bsf_free(&avci->bsf);
av_freep(&avctx->internal);
}
av_freep(&avctx->priv_data);
if (av_codec_is_encoder(avctx->codec)) {
av_freep(&avctx->extradata);
-#if FF_API_CODED_FRAME
-FF_DISABLE_DEPRECATION_WARNINGS
- av_frame_free(&avctx->coded_frame);
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
- }
+ } else if (av_codec_is_decoder(avctx->codec))
+ av_freep(&avctx->subtitle_header);
+
avctx->codec = NULL;
avctx->active_thread_type = 0;
return 0;
}
+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);
- snprintf(buf, buf_size, "%s: %s", codec_type ? codec_type : "unknown",
- codec_name);
+ 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))
- snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", enc->codec->name);
+ av_bprintf(&bprint, " (%s)", enc->codec->name);
if (profile)
- snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile);
+ av_bprintf(&bprint, " (%s)", profile);
if ( enc->codec_type == AVMEDIA_TYPE_VIDEO
&& av_log_get_level() >= AV_LOG_VERBOSE
&& enc->refs)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %d reference frame%s",
- enc->refs, enc->refs > 1 ? "s" : "");
+ av_bprintf(&bprint, ", %d reference frame%s",
+ enc->refs, enc->refs > 1 ? "s" : "");
if (enc->codec_tag)
- snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s / 0x%04X)",
- av_fourcc2str(enc->codec_tag), 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:
{
- char detail[256] = "(";
+ 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;
- av_strlcat(buf, separator, buf_size);
+ /* 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;
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- "%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" :
- av_get_pix_fmt_name(enc->pix_fmt));
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_strlcatf(detail, sizeof(detail), "%d bpc, ", enc->bits_per_raw_sample);
- if (enc->color_range != AVCOL_RANGE_UNSPECIFIED)
- av_strlcatf(detail, sizeof(detail), "%s, ",
- av_color_range_name(enc->color_range));
+ 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) {
- if (enc->colorspace != (int)enc->color_primaries ||
- enc->colorspace != (int)enc->color_trc) {
+ 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_strlcatf(detail, sizeof(detail), "%s/%s/%s, ",
- av_color_space_name(enc->colorspace),
- av_color_primaries_name(enc->color_primaries),
- av_color_transfer_name(enc->color_trc));
+ av_bprintf(&bprint, "%s/%s/%s, ", col, pri, trc);
} else
- av_strlcatf(detail, sizeof(detail), "%s, ",
- av_get_colorspace_name(enc->colorspace));
+ av_bprintf(&bprint, "%s, ", col);
}
if (enc->field_order != AV_FIELD_UNKNOWN) {
else if (enc->field_order == AV_FIELD_BT)
field_order = "bottom coded first (swapped)";
- av_strlcatf(detail, sizeof(detail), "%s, ", field_order);
+ av_bprintf(&bprint, "%s, ", field_order);
}
if (av_log_get_level() >= AV_LOG_VERBOSE &&
- enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED)
- av_strlcatf(detail, sizeof(detail), "%s, ",
- av_chroma_location_name(enc->chroma_sample_location));
+ enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED &&
+ (str = av_chroma_location_name(enc->chroma_sample_location)))
+ av_bprintf(&bprint, "%s, ", str);
- if (strlen(detail) > 1) {
- detail[strlen(detail) - 2] = 0;
- av_strlcatf(buf, buf_size, "%s)", detail);
+ 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_strlcat(buf, new_line ? separator : ", ", buf_size);
-
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- "%dx%d",
- enc->width, enc->height);
+ av_bprintf(&bprint, "%s%dx%d", new_line ? separator : ", ",
+ enc->width, enc->height);
if (av_log_get_level() >= AV_LOG_VERBOSE &&
(enc->width != enc->coded_width ||
enc->height != enc->coded_height))
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- " (%dx%d)", enc->coded_width, 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);
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- " [SAR %d:%d DAR %d:%d]",
+ 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);
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %d/%d",
- enc->time_base.num / g, enc->time_base.den / g);
+ av_bprintf(&bprint, ", %d/%d",
+ enc->time_base.num / g, enc->time_base.den / g);
}
}
if (encode) {
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", q=%d-%d", enc->qmin, enc->qmax);
+ av_bprintf(&bprint, ", q=%d-%d", enc->qmin, enc->qmax);
} else {
if (enc->properties & FF_CODEC_PROPERTY_CLOSED_CAPTIONS)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", Closed Captions");
+ av_bprintf(&bprint, ", Closed Captions");
if (enc->properties & FF_CODEC_PROPERTY_LOSSLESS)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", lossless");
+ av_bprintf(&bprint, ", lossless");
}
break;
case AVMEDIA_TYPE_AUDIO:
- av_strlcat(buf, separator, buf_size);
+ av_bprintf(&bprint, "%s", separator);
if (enc->sample_rate) {
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- "%d Hz, ", enc->sample_rate);
+ av_bprintf(&bprint, "%d Hz, ", enc->sample_rate);
}
- av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout);
- if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) {
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %s", av_get_sample_fmt_name(enc->sample_fmt));
+ av_bprint_channel_layout(&bprint, enc->channels, enc->channel_layout);
+ 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)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- " (%d bit)", enc->bits_per_raw_sample);
+ av_bprintf(&bprint, " (%d bit)", enc->bits_per_raw_sample);
if (av_log_get_level() >= AV_LOG_VERBOSE) {
if (enc->initial_padding)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", delay %d", enc->initial_padding);
+ av_bprintf(&bprint, ", delay %d", enc->initial_padding);
if (enc->trailing_padding)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", padding %d", 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)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %d/%d",
- enc->time_base.num / g, enc->time_base.den / g);
+ av_bprintf(&bprint, ", %d/%d",
+ enc->time_base.num / g, enc->time_base.den / g);
}
break;
case AVMEDIA_TYPE_SUBTITLE:
if (enc->width)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %dx%d", enc->width, enc->height);
+ av_bprintf(&bprint, ", %dx%d", enc->width, enc->height);
break;
default:
return;
}
if (encode) {
if (enc->flags & AV_CODEC_FLAG_PASS1)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", pass 1");
+ av_bprintf(&bprint, ", pass 1");
if (enc->flags & AV_CODEC_FLAG_PASS2)
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", pass 2");
+ av_bprintf(&bprint, ", pass 2");
}
bitrate = get_bit_rate(enc);
if (bitrate != 0) {
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", %"PRId64" kb/s", bitrate / 1000);
+ av_bprintf(&bprint, ", %"PRId64" kb/s", bitrate / 1000);
} else if (enc->rc_max_rate > 0) {
- snprintf(buf + strlen(buf), buf_size - strlen(buf),
- ", max. %"PRId64" kb/s", enc->rc_max_rate / 1000);
+ av_bprintf(&bprint, ", max. %"PRId64" kb/s", enc->rc_max_rate / 1000);
}
}