|
|
|
/*
|
|
|
|
* utils for libavcodec
|
|
|
|
* Copyright (c) 2001 Fabrice Bellard
|
|
|
|
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
|
|
|
|
*
|
|
|
|
* This file is part of Libav.
|
|
|
|
*
|
|
|
|
* Libav 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.
|
|
|
|
*
|
|
|
|
* Libav 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 Libav; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* utils.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "libavutil/attributes.h"
|
|
|
|
#include "libavutil/avassert.h"
|
|
|
|
#include "libavutil/avstring.h"
|
|
|
|
#include "libavutil/channel_layout.h"
|
|
|
|
#include "libavutil/crc.h"
|
|
|
|
#include "libavutil/frame.h"
|
|
|
|
#include "libavutil/hwcontext.h"
|
|
|
|
#include "libavutil/internal.h"
|
|
|
|
#include "libavutil/mathematics.h"
|
|
|
|
#include "libavutil/pixdesc.h"
|
|
|
|
#include "libavutil/imgutils.h"
|
|
|
|
#include "libavutil/samplefmt.h"
|
|
|
|
#include "libavutil/dict.h"
|
|
|
|
#include "avcodec.h"
|
|
|
|
#include "decode.h"
|
|
|
|
#include "libavutil/opt.h"
|
|
|
|
#include "me_cmp.h"
|
|
|
|
#include "mpegvideo.h"
|
|
|
|
#include "thread.h"
|
|
|
|
#include "internal.h"
|
|
|
|
#include "bytestream.h"
|
|
|
|
#include "version.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <float.h>
|
|
|
|
|
|
|
|
static int volatile entangled_thread_counter = 0;
|
|
|
|
static int (*lockmgr_cb)(void **mutex, enum AVLockOp op);
|
|
|
|
static void *codec_mutex;
|
|
|
|
static void *avformat_mutex;
|
|
|
|
|
|
|
|
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
|
|
|
|
{
|
|
|
|
void **p = ptr;
|
|
|
|
if (min_size > SIZE_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
|
|
|
|
av_freep(p);
|
|
|
|
*size = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
av_fast_malloc(p, size, min_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
if (*size)
|
|
|
|
memset((uint8_t *)*p + min_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* encoder management */
|
|
|
|
static AVCodec *first_avcodec = NULL;
|
|
|
|
|
|
|
|
AVCodec *av_codec_next(const AVCodec *c)
|
|
|
|
{
|
|
|
|
if (c)
|
|
|
|
return c->next;
|
|
|
|
else
|
|
|
|
return first_avcodec;
|
|
|
|
}
|
|
|
|
|
|
|
|
static av_cold void avcodec_init(void)
|
|
|
|
{
|
|
|
|
static int initialized = 0;
|
|
|
|
|
|
|
|
if (initialized != 0)
|
|
|
|
return;
|
|
|
|
initialized = 1;
|
|
|
|
|
|
|
|
if (CONFIG_ME_CMP)
|
|
|
|
ff_me_cmp_init_static();
|
|
|
|
}
|
|
|
|
|
|
|
|
int av_codec_is_encoder(const AVCodec *codec)
|
|
|
|
{
|
|
|
|
return codec && (codec->encode_sub || codec->encode2 ||codec->send_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
int av_codec_is_decoder(const AVCodec *codec)
|
|
|
|
{
|
decode: restructure the core decoding code
Currently, the new decoding API is pretty much just a wrapper around the
old deprecated one. This is problematic, since it interferes with making
full use of the flexibility added by the new API. The old API should
also be removed at some future point.
Reorganize the code so that the new send_packet/receive_frame functions
call the actual decoding directly and change the old deprecated
avcodec_decode_* functions into wrappers around the new API.
The new internal API for decoders is now changing as well. Before this
commit, it mirrors the public API, so the decoders need to implement
send_packet() and receive_frame() callbacks. This turns out to require
awkward constructs in both the decoders and the generic code. After this
commit, the decoders only implement the receive_frame() callback and
call a new internal function, ff_decode_get_packet() to obtain input
data, in the same manner to how the bitstream filters now work.
avcodec will now always make a reference to the input packet, which means
that non-refcounted input packets will be copied. Keeping the previous
behaviour, where this copy could sometimes be avoided, would make the
code significantly more complex and fragile for only dubious gains,
since packets are typically small and everyone who cares about
performance should use refcounted packets anyway.
8 years ago
|
|
|
return codec && (codec->decode || codec->receive_frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
av_cold void avcodec_register(AVCodec *codec)
|
|
|
|
{
|
|
|
|
AVCodec **p;
|
|
|
|
avcodec_init();
|
|
|
|
p = &first_avcodec;
|
|
|
|
while (*p)
|
|
|
|
p = &(*p)->next;
|
|
|
|
*p = codec;
|
|
|
|
codec->next = NULL;
|
|
|
|
|
|
|
|
if (codec->init_static_data)
|
|
|
|
codec->init_static_data(codec);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if FF_API_EMU_EDGE
|
|
|
|
unsigned avcodec_get_edge_width(void)
|
|
|
|
{
|
|
|
|
return EDGE_WIDTH;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if FF_API_SET_DIMENSIONS
|
|
|
|
void avcodec_set_dimensions(AVCodecContext *s, int width, int height)
|
|
|
|
{
|
|
|
|
ff_set_dimensions(s, width, height);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int ff_set_dimensions(AVCodecContext *s, int width, int height)
|
|
|
|
{
|
|
|
|
int ret = av_image_check_size(width, height, 0, s);
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
width = height = 0;
|
|
|
|
s->width = s->coded_width = width;
|
|
|
|
s->height = s->coded_height = height;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ff_set_sar(AVCodecContext *avctx, AVRational sar)
|
|
|
|
{
|
|
|
|
int ret = av_image_check_sar(avctx->width, avctx->height, sar);
|
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %d/%d\n",
|
|
|
|
sar.num, sar.den);
|
|
|
|
avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
|
|
|
|
return ret;
|
|
|
|
} else {
|
|
|
|
avctx->sample_aspect_ratio = sar;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ff_side_data_update_matrix_encoding(AVFrame *frame,
|
|
|
|
enum AVMatrixEncoding matrix_encoding)
|
|
|
|
{
|
|
|
|
AVFrameSideData *side_data;
|
|
|
|
enum AVMatrixEncoding *data;
|
|
|
|
|
|
|
|
side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_MATRIXENCODING);
|
|
|
|
if (!side_data)
|
|
|
|
side_data = av_frame_new_side_data(frame, AV_FRAME_DATA_MATRIXENCODING,
|
|
|
|
sizeof(enum AVMatrixEncoding));
|
|
|
|
|
|
|
|
if (!side_data)
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
|
|
|
|
data = (enum AVMatrixEncoding*)side_data->data;
|
|
|
|
*data = matrix_encoding;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if HAVE_SIMD_ALIGN_32
|
|
|
|
# define STRIDE_ALIGN 32
|
|
|
|
#elif HAVE_SIMD_ALIGN_16
|
|
|
|
# define STRIDE_ALIGN 16
|
|
|
|
#else
|
|
|
|
# define STRIDE_ALIGN 8
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
|
|
|
|
int linesize_align[AV_NUM_DATA_POINTERS])
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int w_align = 1;
|
|
|
|
int h_align = 1;
|
|
|
|
|
|
|
|
switch (s->pix_fmt) {
|
|
|
|
case AV_PIX_FMT_YUV420P:
|
|
|
|
case AV_PIX_FMT_YUYV422:
|
|
|
|
case AV_PIX_FMT_YVYU422:
|
|
|
|
case AV_PIX_FMT_UYVY422:
|
|
|
|
case AV_PIX_FMT_YUV422P:
|
|
|
|
case AV_PIX_FMT_YUV440P:
|
|
|
|
case AV_PIX_FMT_YUV444P:
|
|
|
|
case AV_PIX_FMT_GBRP:
|
|
|
|
case AV_PIX_FMT_GBRAP:
|
|
|
|
case AV_PIX_FMT_GRAY8:
|
|
|
|
case AV_PIX_FMT_GRAY16BE:
|
|
|
|
case AV_PIX_FMT_GRAY16LE:
|
|
|
|
case AV_PIX_FMT_YUVJ420P:
|
|
|
|
case AV_PIX_FMT_YUVJ422P:
|
|
|
|
case AV_PIX_FMT_YUVJ440P:
|
|
|
|
case AV_PIX_FMT_YUVJ444P:
|
|
|
|
case AV_PIX_FMT_YUVA420P:
|
|
|
|
case AV_PIX_FMT_YUVA422P:
|
|
|
|
case AV_PIX_FMT_YUVA444P:
|
|
|
|
case AV_PIX_FMT_YUV420P9LE:
|
|
|
|
case AV_PIX_FMT_YUV420P9BE:
|
|
|
|
case AV_PIX_FMT_YUV420P10LE:
|
|
|
|
case AV_PIX_FMT_YUV420P10BE:
|
|
|
|
case AV_PIX_FMT_YUV422P9LE:
|
|
|
|
case AV_PIX_FMT_YUV422P9BE:
|
|
|
|
case AV_PIX_FMT_YUV422P10LE:
|
|
|
|
case AV_PIX_FMT_YUV422P10BE:
|
|
|
|
case AV_PIX_FMT_YUVA422P10LE:
|
|
|
|
case AV_PIX_FMT_YUVA422P10BE:
|
|
|
|
case AV_PIX_FMT_YUV444P9LE:
|
|
|
|
case AV_PIX_FMT_YUV444P9BE:
|
|
|
|
case AV_PIX_FMT_YUV444P10LE:
|
|
|
|
case AV_PIX_FMT_YUV444P10BE:
|
|
|
|
case AV_PIX_FMT_YUVA444P10LE:
|
|
|
|
case AV_PIX_FMT_YUVA444P10BE:
|
|
|
|
case AV_PIX_FMT_GBRP9LE:
|
|
|
|
case AV_PIX_FMT_GBRP9BE:
|
|
|
|
case AV_PIX_FMT_GBRP10LE:
|
|
|
|
case AV_PIX_FMT_GBRP10BE:
|
|
|
|
case AV_PIX_FMT_GBRAP12LE:
|
|
|
|
case AV_PIX_FMT_GBRAP12BE:
|
|
|
|
w_align = 16; //FIXME assume 16 pixel per macroblock
|
|
|
|
h_align = 16 * 2; // interlaced needs 2 macroblocks height
|
|
|
|
break;
|
|
|
|
case AV_PIX_FMT_YUV411P:
|
|
|
|
case AV_PIX_FMT_UYYVYY411:
|
|
|
|
w_align = 32;
|
|
|
|
h_align = 8;
|
|
|
|
break;
|
|
|
|
case AV_PIX_FMT_YUV410P:
|
|
|
|
if (s->codec_id == AV_CODEC_ID_SVQ1) {
|
|
|
|
w_align = 64;
|
|
|
|
h_align = 64;
|
|
|
|
}
|
|
|
|
case AV_PIX_FMT_RGB555:
|
|
|
|
if (s->codec_id == AV_CODEC_ID_RPZA) {
|
|
|
|
w_align = 4;
|
|
|
|
h_align = 4;
|
|
|
|
}
|
|
|
|
case AV_PIX_FMT_PAL8:
|
|
|
|
case AV_PIX_FMT_BGR8:
|
|
|
|
case AV_PIX_FMT_RGB8:
|
|
|
|
if (s->codec_id == AV_CODEC_ID_SMC) {
|
|
|
|
w_align = 4;
|
|
|
|
h_align = 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AV_PIX_FMT_BGR24:
|
|
|
|
if ((s->codec_id == AV_CODEC_ID_MSZH) ||
|
|
|
|
(s->codec_id == AV_CODEC_ID_ZLIB)) {
|
|
|
|
w_align = 4;
|
|
|
|
h_align = 4;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
w_align = 1;
|
|
|
|
h_align = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
*width = FFALIGN(*width, w_align);
|
|
|
|
*height = FFALIGN(*height, h_align);
|
|
|
|
if (s->codec_id == AV_CODEC_ID_H264)
|
|
|
|
// some of the optimized chroma MC reads one line too much
|
|
|
|
*height += 2;
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
linesize_align[i] = STRIDE_ALIGN;
|
|
|
|
}
|
|
|
|
|
|
|
|
void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height)
|
|
|
|
{
|
|
|
|
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->pix_fmt);
|
|
|
|
int chroma_shift = desc->log2_chroma_w;
|
|
|
|
int linesize_align[AV_NUM_DATA_POINTERS];
|
|
|
|
int align;
|
|
|
|
|
|
|
|
avcodec_align_dimensions2(s, width, height, linesize_align);
|
|
|
|
align = FFMAX(linesize_align[0], linesize_align[3]);
|
|
|
|
linesize_align[1] <<= chroma_shift;
|
|
|
|
linesize_align[2] <<= chroma_shift;
|
|
|
|
align = FFMAX3(align, linesize_align[1], linesize_align[2]);
|
|
|
|
*width = FFALIGN(*width, align);
|
|
|
|
}
|
|
|
|
|
|
|
|
int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels,
|
|
|
|
enum AVSampleFormat sample_fmt, const uint8_t *buf,
|
|
|
|
int buf_size, int align)
|
|
|
|
{
|
|
|
|
int ch, planar, needed_size, ret = 0;
|
|
|
|
|
|
|
|
needed_size = av_samples_get_buffer_size(NULL, nb_channels,
|
|
|
|
frame->nb_samples, sample_fmt,
|
|
|
|
align);
|
|
|
|
if (buf_size < needed_size)
|
|
|
|
return AVERROR(EINVAL);
|
|
|
|
|
|
|
|
planar = av_sample_fmt_is_planar(sample_fmt);
|
|
|
|
if (planar && nb_channels > AV_NUM_DATA_POINTERS) {
|
|
|
|
if (!(frame->extended_data = av_mallocz(nb_channels *
|
|
|
|
sizeof(*frame->extended_data))))
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
} else {
|
|
|
|
frame->extended_data = frame->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = av_samples_fill_arrays(frame->extended_data, &frame->linesize[0],
|
|
|
|
buf, nb_channels, frame->nb_samples,
|
|
|
|
sample_fmt, align)) < 0) {
|
|
|
|
if (frame->extended_data != frame->data)
|
|
|
|
av_free(frame->extended_data);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (frame->extended_data != frame->data) {
|
|
|
|
for (ch = 0; ch < AV_NUM_DATA_POINTERS; ch++)
|
|
|
|
frame->data[ch] = frame->extended_data[ch];
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
int r = func(c, (char *)arg + i * size);
|
|
|
|
if (ret)
|
|
|
|
ret[i] = r;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
AVDictionary *tmp = NULL;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE)
|
|
|
|
return AVERROR(EINVAL);
|
|
|
|
|
|
|
|
if (options)
|
|
|
|
av_dict_copy(&tmp, *options, 0);
|
|
|
|
|
|
|
|
/* If there is a user-supplied mutex locking routine, call it. */
|
|
|
|
if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) {
|
|
|
|
if (lockmgr_cb) {
|
|
|
|
if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
entangled_thread_counter++;
|
|
|
|
if (entangled_thread_counter != 1) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR,
|
|
|
|
"Insufficient thread locking. At least %d threads are "
|
|
|
|
"calling avcodec_open2() at the same time right now.\n",
|
|
|
|
entangled_thread_counter);
|
|
|
|
ret = -1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->internal = av_mallocz(sizeof(AVCodecInternal));
|
|
|
|
if (!avctx->internal) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool));
|
|
|
|
if (!avctx->internal->pool) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->internal->to_free = av_frame_alloc();
|
|
|
|
if (!avctx->internal->to_free) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
decode: restructure the core decoding code
Currently, the new decoding API is pretty much just a wrapper around the
old deprecated one. This is problematic, since it interferes with making
full use of the flexibility added by the new API. The old API should
also be removed at some future point.
Reorganize the code so that the new send_packet/receive_frame functions
call the actual decoding directly and change the old deprecated
avcodec_decode_* functions into wrappers around the new API.
The new internal API for decoders is now changing as well. Before this
commit, it mirrors the public API, so the decoders need to implement
send_packet() and receive_frame() callbacks. This turns out to require
awkward constructs in both the decoders and the generic code. After this
commit, the decoders only implement the receive_frame() callback and
call a new internal function, ff_decode_get_packet() to obtain input
data, in the same manner to how the bitstream filters now work.
avcodec will now always make a reference to the input packet, which means
that non-refcounted input packets will be copied. Keeping the previous
behaviour, where this copy could sometimes be avoided, would make the
code significantly more complex and fragile for only dubious gains,
since packets are typically small and everyone who cares about
performance should use refcounted packets anyway.
8 years ago
|
|
|
avctx->internal->compat_decode_frame = av_frame_alloc();
|
|
|
|
if (!avctx->internal->compat_decode_frame) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->internal->buffer_frame = av_frame_alloc();
|
|
|
|
if (!avctx->internal->buffer_frame) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->internal->buffer_pkt = av_packet_alloc();
|
|
|
|
if (!avctx->internal->buffer_pkt) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
decode: restructure the core decoding code
Currently, the new decoding API is pretty much just a wrapper around the
old deprecated one. This is problematic, since it interferes with making
full use of the flexibility added by the new API. The old API should
also be removed at some future point.
Reorganize the code so that the new send_packet/receive_frame functions
call the actual decoding directly and change the old deprecated
avcodec_decode_* functions into wrappers around the new API.
The new internal API for decoders is now changing as well. Before this
commit, it mirrors the public API, so the decoders need to implement
send_packet() and receive_frame() callbacks. This turns out to require
awkward constructs in both the decoders and the generic code. After this
commit, the decoders only implement the receive_frame() callback and
call a new internal function, ff_decode_get_packet() to obtain input
data, in the same manner to how the bitstream filters now work.
avcodec will now always make a reference to the input packet, which means
that non-refcounted input packets will be copied. Keeping the previous
behaviour, where this copy could sometimes be avoided, would make the
code significantly more complex and fragile for only dubious gains,
since packets are typically small and everyone who cares about
performance should use refcounted packets anyway.
8 years ago
|
|
|
avctx->internal->ds.in_pkt = av_packet_alloc();
|
|
|
|
if (!avctx->internal->ds.in_pkt) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->internal->last_pkt_props = av_packet_alloc();
|
|
|
|
if (!avctx->internal->last_pkt_props) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (codec->priv_data_size > 0) {
|
|
|
|
if (!avctx->priv_data) {
|
|
|
|
avctx->priv_data = av_mallocz(codec->priv_data_size);
|
|
|
|
if (!avctx->priv_data) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto 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, &tmp)) < 0)
|
|
|
|
goto free_and_end;
|
|
|
|
} else {
|
|
|
|
avctx->priv_data = NULL;
|
|
|
|
}
|
|
|
|
if ((ret = av_opt_set_dict(avctx, &tmp)) < 0)
|
|
|
|
goto free_and_end;
|
|
|
|
|
|
|
|
if (avctx->coded_width && avctx->coded_height && !avctx->width && !avctx->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_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0
|
|
|
|
|| av_image_check_size(avctx->width, avctx->height, 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 the decoder init function was already called previously,
|
|
|
|
* free the already allocated subtitle_header before overwriting it */
|
|
|
|
if (av_codec_is_decoder(codec))
|
|
|
|
av_freep(&avctx->subtitle_header);
|
|
|
|
|
|
|
|
if (avctx->channels > FF_SANE_NB_CHANNELS) {
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->codec = codec;
|
|
|
|
if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) &&
|
|
|
|
avctx->codec_id == AV_CODEC_ID_NONE) {
|
|
|
|
avctx->codec_type = codec->type;
|
|
|
|
avctx->codec_id = codec->id;
|
|
|
|
}
|
|
|
|
if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type
|
|
|
|
&& avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "codec type or id mismatches\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
avctx->frame_number = 0;
|
|
|
|
|
|
|
|
if ((avctx->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) &&
|
|
|
|
avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
|
|
|
|
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 (HAVE_THREADS) {
|
|
|
|
ret = ff_thread_init(avctx);
|
|
|
|
if (ret < 0) {
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!HAVE_THREADS && !(codec->capabilities & AV_CODEC_CAP_AUTO_THREADS))
|
|
|
|
avctx->thread_count = 1;
|
|
|
|
|
|
|
|
if (av_codec_is_encoder(avctx->codec)) {
|
|
|
|
int i;
|
|
|
|
#if FF_API_CODED_FRAME
|
|
|
|
FF_DISABLE_DEPRECATION_WARNINGS
|
|
|
|
avctx->coded_frame = av_frame_alloc();
|
|
|
|
if (!avctx->coded_frame) {
|
|
|
|
ret = AVERROR(ENOMEM);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
FF_ENABLE_DEPRECATION_WARNINGS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avctx->codec->sample_fmts) {
|
|
|
|
for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
|
|
|
|
if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
|
|
|
|
break;
|
|
|
|
if (avctx->channels == 1 &&
|
|
|
|
av_get_planar_sample_fmt(avctx->sample_fmt) ==
|
|
|
|
av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) {
|
|
|
|
avctx->sample_fmt = avctx->codec->sample_fmts[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Specified sample_fmt is not supported.\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (avctx->codec->pix_fmts) {
|
|
|
|
for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++)
|
|
|
|
if (avctx->pix_fmt == avctx->codec->pix_fmts[i])
|
|
|
|
break;
|
|
|
|
if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Specified pix_fmt is not supported\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P ||
|
|
|
|
avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P ||
|
|
|
|
avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P ||
|
|
|
|
avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P)
|
|
|
|
avctx->color_range = AVCOL_RANGE_JPEG;
|
|
|
|
}
|
|
|
|
if (avctx->codec->supported_samplerates) {
|
|
|
|
for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++)
|
|
|
|
if (avctx->sample_rate == avctx->codec->supported_samplerates[i])
|
|
|
|
break;
|
|
|
|
if (avctx->codec->supported_samplerates[i] == 0) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Specified sample_rate is not supported\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (avctx->codec->channel_layouts) {
|
|
|
|
if (!avctx->channel_layout) {
|
|
|
|
av_log(avctx, AV_LOG_WARNING, "channel_layout not specified\n");
|
|
|
|
} else {
|
|
|
|
for (i = 0; avctx->codec->channel_layouts[i] != 0; i++)
|
|
|
|
if (avctx->channel_layout == avctx->codec->channel_layouts[i])
|
|
|
|
break;
|
|
|
|
if (avctx->codec->channel_layouts[i] == 0) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Specified channel_layout is not supported\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (avctx->channel_layout && avctx->channels) {
|
|
|
|
if (av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "channel layout does not match number of channels\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
} else if (avctx->channel_layout) {
|
|
|
|
avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!avctx->rc_initial_buffer_occupancy)
|
|
|
|
avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3 / 4;
|
|
|
|
|
|
|
|
if (avctx->ticks_per_frame &&
|
|
|
|
avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR,
|
|
|
|
"ticks_per_frame %d too large for the timebase %d/%d.",
|
|
|
|
avctx->ticks_per_frame,
|
|
|
|
avctx->time_base.num,
|
|
|
|
avctx->time_base.den);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avctx->hw_frames_ctx) {
|
|
|
|
AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
|
|
|
if (frames_ctx->format != avctx->pix_fmt) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR,
|
|
|
|
"Mismatching AVCodecContext.pix_fmt and AVHWFramesContext.format\n");
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
if (avctx->sw_pix_fmt != AV_PIX_FMT_NONE &&
|
|
|
|
avctx->sw_pix_fmt != frames_ctx->sw_format) {
|
|
|
|
av_log(avctx, AV_LOG_ERROR,
|
|
|
|
"Mismatching AVCodecContext.sw_pix_fmt (%s) "
|
|
|
|
"and AVHWFramesContext.sw_format (%s)\n",
|
|
|
|
av_get_pix_fmt_name(avctx->sw_pix_fmt),
|
|
|
|
av_get_pix_fmt_name(frames_ctx->sw_format));
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
avctx->sw_pix_fmt = frames_ctx->sw_format;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avctx->codec->init && !(avctx->active_thread_type & FF_THREAD_FRAME)) {
|
|
|
|
ret = avctx->codec->init(avctx);
|
|
|
|
if (ret < 0) {
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if FF_API_AUDIOENC_DELAY
|
|
|
|
if (av_codec_is_encoder(avctx->codec))
|
|
|
|
avctx->delay = avctx->initial_padding;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (av_codec_is_decoder(avctx->codec)) {
|
|
|
|
/* validate channel layout from the decoder */
|
|
|
|
if (avctx->channel_layout) {
|
|
|
|
int channels = av_get_channel_layout_nb_channels(avctx->channel_layout);
|
|
|
|
if (!avctx->channels)
|
|
|
|
avctx->channels = channels;
|
|
|
|
else if (channels != avctx->channels) {
|
|
|
|
av_log(avctx, AV_LOG_WARNING,
|
|
|
|
"channel layout does not match number of channels\n");
|
|
|
|
avctx->channel_layout = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (avctx->channels && avctx->channels < 0 ||
|
|
|
|
avctx->channels > FF_SANE_NB_CHANNELS) {
|
|
|
|
ret = AVERROR(EINVAL);
|
|
|
|
goto free_and_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if FF_API_AVCTX_TIMEBASE
|
|
|
|
if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
|
|
|
|
avctx->time_base = av_inv_q(avctx->framerate);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) {
|
|
|
|
entangled_thread_counter--;
|
|
|
|
|
|
|
|
/* Release any user-supplied mutex. */
|
|
|
|
if (lockmgr_cb) {
|
|
|
|
(*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (options) {
|
|
|
|
av_dict_free(options);
|
|
|
|
*options = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
free_and_end:
|
|
|
|
if (avctx->codec &&
|
|
|
|
(avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP))
|
|
|
|
avctx->codec->close(avctx);
|
|
|
|
|
|
|
|
if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
|
|
|
|
av_opt_free(avctx->priv_data);
|
|
|
|
av_opt_free(avctx);
|
|
|
|
|
|
|
|
#if FF_API_CODED_FRAME
|
|
|
|
FF_DISABLE_DEPRECATION_WARNINGS
|
|
|
|
av_frame_free(&avctx->coded_frame);
|
|
|
|
FF_ENABLE_DEPRECATION_WARNINGS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
av_dict_free(&tmp);
|
|
|
|
av_freep(&avctx->priv_data);
|
|
|
|
if (avctx->internal) {
|
|
|
|
av_frame_free(&avctx->internal->to_free);
|
decode: restructure the core decoding code
Currently, the new decoding API is pretty much just a wrapper around the
old deprecated one. This is problematic, since it interferes with making
full use of the flexibility added by the new API. The old API should
also be removed at some future point.
Reorganize the code so that the new send_packet/receive_frame functions
call the actual decoding directly and change the old deprecated
avcodec_decode_* functions into wrappers around the new API.
The new internal API for decoders is now changing as well. Before this
commit, it mirrors the public API, so the decoders need to implement
send_packet() and receive_frame() callbacks. This turns out to require
awkward constructs in both the decoders and the generic code. After this
commit, the decoders only implement the receive_frame() callback and
call a new internal function, ff_decode_get_packet() to obtain input
data, in the same manner to how the bitstream filters now work.
avcodec will now always make a reference to the input packet, which means
that non-refcounted input packets will be copied. Keeping the previous
behaviour, where this copy could sometimes be avoided, would make the
code significantly more complex and fragile for only dubious gains,
since packets are typically small and everyone who cares about
performance should use refcounted packets anyway.
8 years ago
|
|
|
av_frame_free(&avctx->internal->compat_decode_frame);
|
|
|
|
av_frame_free(&avctx->internal->buffer_frame);
|
|
|
|
av_packet_free(&avctx->internal->buffer_pkt);
|
|
|
|
av_packet_free(&avctx->internal->last_pkt_props);
|
decode: restructure the core decoding code
Currently, the new decoding API is pretty much just a wrapper around the
old deprecated one. This is problematic, since it interferes with making
full use of the flexibility added by the new API. The old API should
also be removed at some future point.
Reorganize the code so that the new send_packet/receive_frame functions
call the actual decoding directly and change the old deprecated
avcodec_decode_* functions into wrappers around the new API.
The new internal API for decoders is now changing as well. Before this
commit, it mirrors the public API, so the decoders need to implement
send_packet() and receive_frame() callbacks. This turns out to require
awkward constructs in both the decoders and the generic code. After this
commit, the decoders only implement the receive_frame() callback and
call a new internal function, ff_decode_get_packet() to obtain input
data, in the same manner to how the bitstream filters now work.
avcodec will now always make a reference to the input packet, which means
that non-refcounted input packets will be copied. Keeping the previous
behaviour, where this copy could sometimes be avoided, would make the
code significantly more complex and fragile for only dubious gains,
since packets are typically small and everyone who cares about
performance should use refcounted packets anyway.
8 years ago
|
|
|
|
|
|
|
av_packet_free(&avctx->internal->ds.in_pkt);
|
|
|
|
|
|
|
|
av_freep(&avctx->internal->pool);
|
|
|
|
}
|
|
|
|
av_freep(&avctx->internal);
|
|
|
|
avctx->codec = NULL;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
void avsubtitle_free(AVSubtitle *sub)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < sub->num_rects; i++) {
|
|
|
|
av_freep(&sub->rects[i]->data[0]);
|
|
|
|
av_freep(&sub->rects[i]->data[1]);
|
|
|
|
av_freep(&sub->rects[i]->data[2]);
|
|
|
|
av_freep(&sub->rects[i]->data[3]);
|
|
|
|
av_freep(&sub->rects[i]->text);
|
|
|
|
av_freep(&sub->rects[i]->ass);
|
|
|
|
av_freep(&sub->rects[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
av_freep(&sub->rects);
|
|
|
|
|
|
|
|
memset(sub, 0, sizeof(AVSubtitle));
|
|
|
|
}
|
|
|
|
|
|
|
|
av_cold int avcodec_close(AVCodecContext *avctx)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (avcodec_is_open(avctx)) {
|
|
|
|
FramePool *pool = avctx->internal->pool;
|
|
|
|
|
|
|
|
if (HAVE_THREADS && avctx->internal->thread_ctx)
|
|
|
|
ff_thread_free(avctx);
|
|
|
|
if (avctx->codec && avctx->codec->close)
|
|
|
|
avctx->codec->close(avctx);
|
|
|
|
av_frame_free(&avctx->internal->to_free);
|
decode: restructure the core decoding code
Currently, the new decoding API is pretty much just a wrapper around the
old deprecated one. This is problematic, since it interferes with making
full use of the flexibility added by the new API. The old API should
also be removed at some future point.
Reorganize the code so that the new send_packet/receive_frame functions
call the actual decoding directly and change the old deprecated
avcodec_decode_* functions into wrappers around the new API.
The new internal API for decoders is now changing as well. Before this
commit, it mirrors the public API, so the decoders need to implement
send_packet() and receive_frame() callbacks. This turns out to require
awkward constructs in both the decoders and the generic code. After this
commit, the decoders only implement the receive_frame() callback and
call a new internal function, ff_decode_get_packet() to obtain input
data, in the same manner to how the bitstream filters now work.
avcodec will now always make a reference to the input packet, which means
that non-refcounted input packets will be copied. Keeping the previous
behaviour, where this copy could sometimes be avoided, would make the
code significantly more complex and fragile for only dubious gains,
since packets are typically small and everyone who cares about
performance should use refcounted packets anyway.
8 years ago
|
|
|
av_frame_free(&avctx->internal->compat_decode_frame);
|
|
|
|
av_frame_free(&avctx->internal->buffer_frame);
|
|
|
|
av_packet_free(&avctx->internal->buffer_pkt);
|
|
|
|
av_packet_free(&avctx->internal->last_pkt_props);
|
decode: restructure the core decoding code
Currently, the new decoding API is pretty much just a wrapper around the
old deprecated one. This is problematic, since it interferes with making
full use of the flexibility added by the new API. The old API should
also be removed at some future point.
Reorganize the code so that the new send_packet/receive_frame functions
call the actual decoding directly and change the old deprecated
avcodec_decode_* functions into wrappers around the new API.
The new internal API for decoders is now changing as well. Before this
commit, it mirrors the public API, so the decoders need to implement
send_packet() and receive_frame() callbacks. This turns out to require
awkward constructs in both the decoders and the generic code. After this
commit, the decoders only implement the receive_frame() callback and
call a new internal function, ff_decode_get_packet() to obtain input
data, in the same manner to how the bitstream filters now work.
avcodec will now always make a reference to the input packet, which means
that non-refcounted input packets will be copied. Keeping the previous
behaviour, where this copy could sometimes be avoided, would make the
code significantly more complex and fragile for only dubious gains,
since packets are typically small and everyone who cares about
performance should use refcounted packets anyway.
8 years ago
|
|
|
|
|
|
|
av_packet_free(&avctx->internal->ds.in_pkt);
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
|
|
|
|
av_buffer_pool_uninit(&pool->pools[i]);
|
|
|
|
av_freep(&avctx->internal->pool);
|
|
|
|
|
|
|
|
if (avctx->hwaccel && avctx->hwaccel->uninit)
|
|
|
|
avctx->hwaccel->uninit(avctx);
|
|
|
|
av_freep(&avctx->internal->hwaccel_priv_data);
|
|
|
|
|
|
|
|
ff_decode_bsfs_uninit(avctx);
|
|
|
|
|
|
|
|
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_buffer_unref(&avctx->hw_frames_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);
|
|
|
|
#if FF_API_CODED_FRAME
|
|
|
|
FF_DISABLE_DEPRECATION_WARNINGS
|
|
|
|
av_frame_free(&avctx->coded_frame);
|
|
|
|
FF_ENABLE_DEPRECATION_WARNINGS
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
avctx->codec = NULL;
|
|
|
|
avctx->active_thread_type = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static AVCodec *find_encdec(enum AVCodecID id, int encoder)
|
|
|
|
{
|
|
|
|
AVCodec *p, *experimental = NULL;
|
|
|
|
p = first_avcodec;
|
|
|
|
while (p) {
|
|
|
|
if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) &&
|
|
|
|
p->id == id) {
|
|
|
|
if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) {
|
|
|
|
experimental = p;
|
|
|
|
} else
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
return experimental;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVCodec *avcodec_find_encoder(enum AVCodecID id)
|
|
|
|
{
|
|
|
|
return find_encdec(id, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
AVCodec *avcodec_find_encoder_by_name(const char *name)
|
|
|
|
{
|
|
|
|
AVCodec *p;
|
|
|
|
if (!name)
|
|
|
|
return NULL;
|
|
|
|
p = first_avcodec;
|
|
|
|
while (p) {
|
|
|
|
if (av_codec_is_encoder(p) && strcmp(name, p->name) == 0)
|
|
|
|
return p;
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVCodec *avcodec_find_decoder(enum AVCodecID id)
|
|
|
|
{
|
|
|
|
return find_encdec(id, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
AVCodec *avcodec_find_decoder_by_name(const char *name)
|
|
|
|
{
|
|
|
|
AVCodec *p;
|
|
|
|
if (!name)
|
|
|
|
return NULL;
|
|
|
|
p = first_avcodec;
|
|
|
|
while (p) {
|
|
|
|
if (av_codec_is_decoder(p) && strcmp(name, p->name) == 0)
|
|
|
|
return p;
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_bit_rate(AVCodecContext *ctx)
|
|
|
|
{
|
|
|
|
int 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);
|
|
|
|
bit_rate = bits_per_sample ? ctx->sample_rate * ctx->channels * bits_per_sample : ctx->bit_rate;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
bit_rate = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return bit_rate;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag)
|
|
|
|
{
|
|
|
|
int i, len, ret = 0;
|
|
|
|
|
|
|
|
#define TAG_PRINT(x) \
|
|
|
|
(((x) >= '0' && (x) <= '9') || \
|
|
|
|
((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || \
|
|
|
|
((x) == '.' || (x) == ' '))
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
len = snprintf(buf, buf_size,
|
|
|
|
TAG_PRINT(codec_tag & 0xFF) ? "%c" : "[%d]", codec_tag & 0xFF);
|
|
|
|
buf += len;
|
|
|
|
buf_size = buf_size > len ? buf_size - len : 0;
|
|
|
|
ret += len;
|
|
|
|
codec_tag >>= 8;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
|
|
|
|
{
|
|
|
|
const char *codec_name;
|
|
|
|
const char *profile = NULL;
|
|
|
|
char buf1[32];
|
|
|
|
int bitrate;
|
|
|
|
int new_line = 0;
|
|
|
|
AVRational display_aspect_ratio;
|
|
|
|
const AVCodecDescriptor *desc = avcodec_descriptor_get(enc->codec_id);
|
|
|
|
|
|
|
|
if (desc) {
|
|
|
|
codec_name = desc->name;
|
|
|
|
profile = avcodec_profile_name(enc->codec_id, enc->profile);
|
|
|
|
} else if (enc->codec_id == AV_CODEC_ID_MPEG2TS) {
|
|
|
|
/* fake mpeg2 transport stream codec (currently not
|
|
|
|
* registered) */
|
|
|
|
codec_name = "mpeg2ts";
|
|
|
|
} else {
|
|
|
|
/* output avi tags */
|
|
|
|
char tag_buf[32];
|
|
|
|
av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag);
|
|
|
|
snprintf(buf1, sizeof(buf1), "%s / 0x%04X", tag_buf, enc->codec_tag);
|
|
|
|
codec_name = buf1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (enc->codec_type) {
|
|
|
|
case AVMEDIA_TYPE_VIDEO:
|
|
|
|
snprintf(buf, buf_size,
|
|
|
|
"Video: %s%s",
|
|
|
|
codec_name, enc->mb_decision ? " (hq)" : "");
|
|
|
|
if (profile)
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
" (%s)", profile);
|
|
|
|
if (enc->codec_tag) {
|
|
|
|
char tag_buf[32];
|
|
|
|
av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag);
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
" [%s / 0x%04X]", tag_buf, enc->codec_tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
av_strlcat(buf, "\n ", buf_size);
|
|
|
|
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->color_range != AVCOL_RANGE_UNSPECIFIED)
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s",
|
|
|
|
av_color_range_name(enc->color_range));
|
|
|
|
if (enc->colorspace != AVCOL_SPC_UNSPECIFIED ||
|
|
|
|
enc->color_primaries != AVCOL_PRI_UNSPECIFIED ||
|
|
|
|
enc->color_trc != AVCOL_TRC_UNSPECIFIED) {
|
|
|
|
new_line = 1;
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s/%s/%s",
|
|
|
|
av_color_space_name(enc->colorspace),
|
|
|
|
av_color_primaries_name(enc->color_primaries),
|
|
|
|
av_color_transfer_name(enc->color_trc));
|
|
|
|
}
|
|
|
|
if (av_log_get_level() >= AV_LOG_DEBUG &&
|
|
|
|
enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED)
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s",
|
|
|
|
av_chroma_location_name(enc->chroma_sample_location));
|
|
|
|
|
|
|
|
if (enc->width) {
|
|
|
|
av_strlcat(buf, new_line ? "\n " : ", ", buf_size);
|
|
|
|
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
"%dx%d",
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (enc->sample_aspect_ratio.num) {
|
|
|
|
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
|
|
|
|
enc->width * enc->sample_aspect_ratio.num,
|
|
|
|
enc->height * enc->sample_aspect_ratio.den,
|
|
|
|
1024 * 1024);
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
" [PAR %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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (encode) {
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
", q=%d-%d", enc->qmin, enc->qmax);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AVMEDIA_TYPE_AUDIO:
|
|
|
|
snprintf(buf, buf_size,
|
|
|
|
"Audio: %s",
|
|
|
|
codec_name);
|
|
|
|
if (profile)
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
" (%s)", profile);
|
|
|
|
if (enc->codec_tag) {
|
|
|
|
char tag_buf[32];
|
|
|
|
av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag);
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
" [%s / 0x%04X]", tag_buf, enc->codec_tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
av_strlcat(buf, "\n ", buf_size);
|
|
|
|
if (enc->sample_rate) {
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
"%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));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case AVMEDIA_TYPE_DATA:
|
|
|
|
snprintf(buf, buf_size, "Data: %s", codec_name);
|
|
|
|
break;
|
|
|
|
case AVMEDIA_TYPE_SUBTITLE:
|
|
|
|
snprintf(buf, buf_size, "Subtitle: %s", codec_name);
|
|
|
|
break;
|
|
|
|
case AVMEDIA_TYPE_ATTACHMENT:
|
|
|
|
snprintf(buf, buf_size, "Attachment: %s", codec_name);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
snprintf(buf, buf_size, "Invalid Codec type %d", enc->codec_type);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (encode) {
|
|
|
|
if (enc->flags & AV_CODEC_FLAG_PASS1)
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
", pass 1");
|
|
|
|
if (enc->flags & AV_CODEC_FLAG_PASS2)
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
", pass 2");
|
|
|
|
}
|
|
|
|
bitrate = get_bit_rate(enc);
|
|
|
|
if (bitrate != 0) {
|
|
|
|
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
|
|
|
", %d kb/s", bitrate / 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *av_get_profile_name(const AVCodec *codec, int profile)
|
|
|
|
{
|
|
|
|
const AVProfile *p;
|
|
|
|
if (profile == FF_PROFILE_UNKNOWN || !codec->profiles)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (p = codec->profiles; p->profile != FF_PROFILE_UNKNOWN; p++)
|
|
|
|
if (p->profile == profile)
|
|
|
|
return p->name;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *avcodec_profile_name(enum AVCodecID codec_id, int profile)
|
|
|
|
{
|
|
|
|
const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
|
|
|
|
const AVProfile *p;
|
|
|
|
|
|
|
|
if (profile == FF_PROFILE_UNKNOWN || !desc || !desc->profiles)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (p = desc->profiles; p->profile != FF_PROFILE_UNKNOWN; p++)
|
|
|
|
if (p->profile == profile)
|
|
|
|
return p->name;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned avcodec_version(void)
|
|
|
|
{
|
|
|
|
return LIBAVCODEC_VERSION_INT;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *avcodec_configuration(void)
|
|
|
|
{
|
|
|
|
return LIBAV_CONFIGURATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *avcodec_license(void)
|
|
|
|
{
|
|
|
|
#define LICENSE_PREFIX "libavcodec license: "
|
|
|
|
return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
|
|
|
|
{
|
|
|
|
switch (codec_id) {
|
|
|
|
case AV_CODEC_ID_ADPCM_CT:
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_APC:
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_EA_SEAD:
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_WS:
|
|
|
|
case AV_CODEC_ID_ADPCM_G722:
|
|
|
|
case AV_CODEC_ID_ADPCM_YAMAHA:
|
|
|
|
return 4;
|
|
|
|
case AV_CODEC_ID_PCM_ALAW:
|
|
|
|
case AV_CODEC_ID_PCM_MULAW:
|
|
|
|
case AV_CODEC_ID_PCM_S8:
|
|
|
|
case AV_CODEC_ID_PCM_U8:
|
|
|
|
case AV_CODEC_ID_PCM_ZORK:
|
|
|
|
return 8;
|
|
|
|
case AV_CODEC_ID_PCM_S16BE:
|
|
|
|
case AV_CODEC_ID_PCM_S16BE_PLANAR:
|
|
|
|
case AV_CODEC_ID_PCM_S16LE:
|
|
|
|
case AV_CODEC_ID_PCM_S16LE_PLANAR:
|
|
|
|
case AV_CODEC_ID_PCM_U16BE:
|
|
|
|
case AV_CODEC_ID_PCM_U16LE:
|
|
|
|
return 16;
|
|
|
|
case AV_CODEC_ID_PCM_S24DAUD:
|
|
|
|
case AV_CODEC_ID_PCM_S24BE:
|
|
|
|
case AV_CODEC_ID_PCM_S24LE:
|
|
|
|
case AV_CODEC_ID_PCM_S24LE_PLANAR:
|
|
|
|
case AV_CODEC_ID_PCM_U24BE:
|
|
|
|
case AV_CODEC_ID_PCM_U24LE:
|
|
|
|
return 24;
|
|
|
|
case AV_CODEC_ID_PCM_S32BE:
|
|
|
|
case AV_CODEC_ID_PCM_S32LE:
|
|
|
|
case AV_CODEC_ID_PCM_S32LE_PLANAR:
|
|
|
|
case AV_CODEC_ID_PCM_U32BE:
|
|
|
|
case AV_CODEC_ID_PCM_U32LE:
|
|
|
|
case AV_CODEC_ID_PCM_F32BE:
|
|
|
|
case AV_CODEC_ID_PCM_F32LE:
|
|
|
|
return 32;
|
|
|
|
case AV_CODEC_ID_PCM_F64BE:
|
|
|
|
case AV_CODEC_ID_PCM_F64LE:
|
|
|
|
return 64;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int av_get_bits_per_sample(enum AVCodecID codec_id)
|
|
|
|
{
|
|
|
|
switch (codec_id) {
|
|
|
|
case AV_CODEC_ID_ADPCM_SBPRO_2:
|
|
|
|
return 2;
|
|
|
|
case AV_CODEC_ID_ADPCM_SBPRO_3:
|
|
|
|
return 3;
|
|
|
|
case AV_CODEC_ID_ADPCM_SBPRO_4:
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_WAV:
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_QT:
|
|
|
|
case AV_CODEC_ID_ADPCM_SWF:
|
|
|
|
case AV_CODEC_ID_ADPCM_MS:
|
|
|
|
return 4;
|
|
|
|
default:
|
|
|
|
return av_get_exact_bits_per_sample(codec_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
|
|
|
|
uint32_t tag, int bits_per_coded_sample, int frame_bytes)
|
|
|
|
{
|
|
|
|
int bps = av_get_exact_bits_per_sample(id);
|
|
|
|
|
|
|
|
/* codecs with an exact constant bits per sample */
|
|
|
|
if (bps > 0 && ch > 0 && frame_bytes > 0)
|
|
|
|
return (frame_bytes * 8) / (bps * ch);
|
|
|
|
bps = bits_per_coded_sample;
|
|
|
|
|
|
|
|
/* codecs with a fixed packet duration */
|
|
|
|
switch (id) {
|
|
|
|
case AV_CODEC_ID_ADPCM_ADX: return 32;
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_QT: return 64;
|
|
|
|
case AV_CODEC_ID_ADPCM_EA_XAS: return 128;
|
|
|
|
case AV_CODEC_ID_AMR_NB:
|
|
|
|
case AV_CODEC_ID_GSM:
|
|
|
|
case AV_CODEC_ID_QCELP:
|
|
|
|
case AV_CODEC_ID_RA_144:
|
|
|
|
case AV_CODEC_ID_RA_288: return 160;
|
|
|
|
case AV_CODEC_ID_IMC: return 256;
|
|
|
|
case AV_CODEC_ID_AMR_WB:
|
|
|
|
case AV_CODEC_ID_GSM_MS: return 320;
|
|
|
|
case AV_CODEC_ID_MP1: return 384;
|
|
|
|
case AV_CODEC_ID_ATRAC1: return 512;
|
|
|
|
case AV_CODEC_ID_ATRAC3: return 1024;
|
|
|
|
case AV_CODEC_ID_MP2:
|
|
|
|
case AV_CODEC_ID_MUSEPACK7: return 1152;
|
|
|
|
case AV_CODEC_ID_AC3: return 1536;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sr > 0) {
|
|
|
|
/* calc from sample rate */
|
|
|
|
if (id == AV_CODEC_ID_TTA)
|
|
|
|
return 256 * sr / 245;
|
|
|
|
|
|
|
|
if (ch > 0) {
|
|
|
|
/* calc from sample rate and channels */
|
|
|
|
if (id == AV_CODEC_ID_BINKAUDIO_DCT)
|
|
|
|
return (480 << (sr / 22050)) / ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id == AV_CODEC_ID_MP3)
|
|
|
|
return sr <= 24000 ? 576 : 1152;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ba > 0) {
|
|
|
|
/* calc from block_align */
|
|
|
|
if (id == AV_CODEC_ID_SIPR) {
|
|
|
|
switch (ba) {
|
|
|
|
case 20: return 160;
|
|
|
|
case 19: return 144;
|
|
|
|
case 29: return 288;
|
|
|
|
case 37: return 480;
|
|
|
|
}
|
|
|
|
} else if (id == AV_CODEC_ID_ILBC) {
|
|
|
|
switch (ba) {
|
|
|
|
case 38: return 160;
|
|
|
|
case 50: return 240;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frame_bytes > 0) {
|
|
|
|
/* calc from frame_bytes only */
|
|
|
|
if (id == AV_CODEC_ID_TRUESPEECH)
|
|
|
|
return 240 * (frame_bytes / 32);
|
|
|
|
if (id == AV_CODEC_ID_NELLYMOSER)
|
|
|
|
return 256 * (frame_bytes / 64);
|
|
|
|
|
|
|
|
if (bps > 0) {
|
|
|
|
/* calc from frame_bytes and bits_per_coded_sample */
|
|
|
|
if (id == AV_CODEC_ID_ADPCM_G726)
|
|
|
|
return frame_bytes * 8 / bps;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ch > 0) {
|
|
|
|
/* calc from frame_bytes and channels */
|
|
|
|
switch (id) {
|
|
|
|
case AV_CODEC_ID_ADPCM_4XM:
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_ISS:
|
|
|
|
return (frame_bytes - 4 * ch) * 2 / ch;
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_SMJPEG:
|
|
|
|
return (frame_bytes - 4) * 2 / ch;
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_AMV:
|
|
|
|
return (frame_bytes - 8) * 2 / ch;
|
|
|
|
case AV_CODEC_ID_ADPCM_XA:
|
|
|
|
return (frame_bytes / 128) * 224 / ch;
|
|
|
|
case AV_CODEC_ID_INTERPLAY_DPCM:
|
|
|
|
return (frame_bytes - 6 - ch) / ch;
|
|
|
|
case AV_CODEC_ID_ROQ_DPCM:
|
|
|
|
return (frame_bytes - 8) / ch;
|
|
|
|
case AV_CODEC_ID_XAN_DPCM:
|
|
|
|
return (frame_bytes - 2 * ch) / ch;
|
|
|
|
case AV_CODEC_ID_MACE3:
|
|
|
|
return 3 * frame_bytes / ch;
|
|
|
|
case AV_CODEC_ID_MACE6:
|
|
|
|
return 6 * frame_bytes / ch;
|
|
|
|
case AV_CODEC_ID_PCM_LXF:
|
|
|
|
return 2 * (frame_bytes / (5 * ch));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tag) {
|
|
|
|
/* calc from frame_bytes, channels, and codec_tag */
|
|
|
|
if (id == AV_CODEC_ID_SOL_DPCM) {
|
|
|
|
if (tag == 3)
|
|
|
|
return frame_bytes / ch;
|
|
|
|
else
|
|
|
|
return frame_bytes * 2 / ch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ba > 0) {
|
|
|
|
/* calc from frame_bytes, channels, and block_align */
|
|
|
|
int blocks = frame_bytes / ba;
|
|
|
|
switch (id) {
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_WAV:
|
|
|
|
return blocks * (1 + (ba - 4 * ch) / (4 * ch) * 8);
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_DK3:
|
|
|
|
return blocks * (((ba - 16) * 2 / 3 * 4) / ch);
|
|
|
|
case AV_CODEC_ID_ADPCM_IMA_DK4:
|
|
|
|
return blocks * (1 + (ba - 4 * ch) * 2 / ch);
|
|
|
|
case AV_CODEC_ID_ADPCM_MS:
|
|
|
|
return blocks * (2 + (ba - 7 * ch) * 2 / ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bps > 0) {
|
|
|
|
/* calc from frame_bytes, channels, and bits_per_coded_sample */
|
|
|
|
switch (id) {
|
|
|
|
case AV_CODEC_ID_PCM_DVD:
|
|
|
|
return 2 * (frame_bytes / ((bps * 2 / 8) * ch));
|
|
|
|
case AV_CODEC_ID_PCM_BLURAY:
|
|
|
|
return frame_bytes / ((FFALIGN(ch, 2) * bps) / 8);
|
|
|
|
case AV_CODEC_ID_S302M:
|
|
|
|
return 2 * (frame_bytes / ((bps + 4) / 4)) / ch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
|
|
|
|
{
|
|
|
|
return get_audio_frame_duration(avctx->codec_id, avctx->sample_rate,
|
|
|
|
avctx->channels, avctx->block_align,
|
|
|
|
avctx->codec_tag, avctx->bits_per_coded_sample,
|
|
|
|
frame_bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes)
|
|
|
|
{
|
|
|
|
return get_audio_frame_duration(par->codec_id, par->sample_rate,
|
|
|
|
par->channels, par->block_align,
|
|
|
|
par->codec_tag, par->bits_per_coded_sample,
|
|
|
|
frame_bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !HAVE_THREADS
|
|
|
|
int ff_thread_init(AVCodecContext *s)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
unsigned int av_xiphlacing(unsigned char *s, unsigned int v)
|
|
|
|
{
|
|
|
|
unsigned int n = 0;
|
|
|
|
|
|
|
|
while (v >= 0xff) {
|
|
|
|
*s++ = 0xff;
|
|
|
|
v -= 0xff;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
*s = v;
|
|
|
|
n++;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < size && !(tab[i][0] == a && tab[i][1] == b); i++) ;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if FF_API_MISSING_SAMPLE
|
|
|
|
FF_DISABLE_DEPRECATION_WARNINGS
|
|
|
|
void av_log_missing_feature(void *avc, const char *feature, int want_sample)
|
|
|
|
{
|
|
|
|
av_log(avc, AV_LOG_WARNING, "%s is not implemented. Update your Libav "
|
|
|
|
"version to the newest one from Git. If the problem still "
|
|
|
|
"occurs, it means that your file has a feature which has not "
|
|
|
|
"been implemented.\n", feature);
|
|
|
|
if(want_sample)
|
|
|
|
av_log_ask_for_sample(avc, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void av_log_ask_for_sample(void *avc, const char *msg, ...)
|
|
|
|
{
|
|
|
|
va_list argument_list;
|
|
|
|
|
|
|
|
va_start(argument_list, msg);
|
|
|
|
|
|
|
|
if (msg)
|
|
|
|
av_vlog(avc, AV_LOG_WARNING, msg, argument_list);
|
|
|
|
av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample "
|
|
|
|
"of this file to ftp://upload.libav.org/incoming/ "
|
|
|
|
"and contact the libav-devel mailing list.\n");
|
|
|
|
|
|
|
|
va_end(argument_list);
|
|
|
|
}
|
|
|
|
FF_ENABLE_DEPRECATION_WARNINGS
|
|
|
|
#endif /* FF_API_MISSING_SAMPLE */
|
|
|
|
|
|
|
|
static AVHWAccel *first_hwaccel = NULL;
|
|
|
|
|
|
|
|
void av_register_hwaccel(AVHWAccel *hwaccel)
|
|
|
|
{
|
|
|
|
AVHWAccel **p = &first_hwaccel;
|
|
|
|
while (*p)
|
|
|
|
p = &(*p)->next;
|
|
|
|
*p = hwaccel;
|
|
|
|
hwaccel->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
|
|
|
|
{
|
|
|
|
return hwaccel ? hwaccel->next : first_hwaccel;
|
|
|
|
}
|
|
|
|
|
|
|
|
int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
|
|
|
|
{
|
|
|
|
if (lockmgr_cb) {
|
|
|
|
// There is no good way to rollback a failure to destroy the
|
|
|
|
// mutex, so we ignore failures.
|
|
|
|
lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY);
|
|
|
|
lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY);
|
|
|
|
lockmgr_cb = NULL;
|
|
|
|
codec_mutex = NULL;
|
|
|
|
avformat_mutex = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cb) {
|
|
|
|
void *new_codec_mutex = NULL;
|
|
|
|
void *new_avformat_mutex = NULL;
|
|
|
|
int err;
|
|
|
|
if (err = cb(&new_codec_mutex, AV_LOCK_CREATE)) {
|
|
|
|
return err > 0 ? AVERROR_UNKNOWN : err;
|
|
|
|
}
|
|
|
|
if (err = cb(&new_avformat_mutex, AV_LOCK_CREATE)) {
|
|
|
|
// Ignore failures to destroy the newly created mutex.
|
|
|
|
cb(&new_codec_mutex, AV_LOCK_DESTROY);
|
|
|
|
return err > 0 ? AVERROR_UNKNOWN : err;
|
|
|
|
}
|
|
|
|
lockmgr_cb = cb;
|
|
|
|
codec_mutex = new_codec_mutex;
|
|
|
|
avformat_mutex = new_avformat_mutex;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int avpriv_lock_avformat(void)
|
|
|
|
{
|
|
|
|
if (lockmgr_cb) {
|
|
|
|
if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int avpriv_unlock_avformat(void)
|
|
|
|
{
|
|
|
|
if (lockmgr_cb) {
|
|
|
|
if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int avpriv_toupper4(unsigned int x)
|
|
|
|
{
|
|
|
|
return av_toupper(x & 0xFF) +
|
|
|
|
(av_toupper((x >> 8) & 0xFF) << 8) +
|
|
|
|
(av_toupper((x >> 16) & 0xFF) << 16) +
|
|
|
|
(av_toupper((x >> 24) & 0xFF) << 24);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
dst->owner = src->owner;
|
|
|
|
|
|
|
|
ret = av_frame_ref(dst->f, src->f);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (src->progress &&
|
|
|
|
!(dst->progress = av_buffer_ref(src->progress))) {
|
|
|
|
ff_thread_release_buffer(dst->owner, dst);
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !HAVE_THREADS
|
|
|
|
|
|
|
|
int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
|
|
|
|
{
|
|
|
|
f->owner = avctx;
|
|
|
|
return ff_get_buffer(avctx, f->f, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f)
|
|
|
|
{
|
|
|
|
if (f->f)
|
|
|
|
av_frame_unref(f->f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ff_thread_finish_setup(AVCodecContext *avctx)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ff_thread_report_progress(ThreadFrame *f, int progress, int field)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void ff_thread_await_progress(ThreadFrame *f, int progress, int field)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int avcodec_is_open(AVCodecContext *s)
|
|
|
|
{
|
|
|
|
return !!s->internal;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t *avpriv_find_start_code(const uint8_t *restrict p,
|
|
|
|
const uint8_t *end,
|
|
|
|
uint32_t * restrict state)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
assert(p <= end);
|
|
|
|
if (p >= end)
|
|
|
|
return end;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
uint32_t tmp = *state << 8;
|
|
|
|
*state = tmp + *(p++);
|
|
|
|
if (tmp == 0x100 || p == end)
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (p < end) {
|
|
|
|
if (p[-1] > 1 ) p += 3;
|
|
|
|
else if (p[-2] ) p += 2;
|
|
|
|
else if (p[-3]|(p[-1]-1)) p++;
|
|
|
|
else {
|
|
|
|
p++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p = FFMIN(p, end) - 4;
|
|
|
|
*state = AV_RB32(p);
|
|
|
|
|
|
|
|
return p + 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVCPBProperties *av_cpb_properties_alloc(size_t *size)
|
|
|
|
{
|
|
|
|
AVCPBProperties *props = av_mallocz(sizeof(AVCPBProperties));
|
|
|
|
if (!props)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (size)
|
|
|
|
*size = sizeof(*props);
|
|
|
|
|
|
|
|
props->vbv_delay = UINT64_MAX;
|
|
|
|
|
|
|
|
return props;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx)
|
|
|
|
{
|
|
|
|
AVPacketSideData *tmp;
|
|
|
|
AVCPBProperties *props;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
props = av_cpb_properties_alloc(&size);
|
|
|
|
if (!props)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
tmp = av_realloc_array(avctx->coded_side_data, avctx->nb_coded_side_data + 1, sizeof(*tmp));
|
|
|
|
if (!tmp) {
|
|
|
|
av_freep(&props);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
avctx->coded_side_data = tmp;
|
|
|
|
avctx->nb_coded_side_data++;
|
|
|
|
|
|
|
|
avctx->coded_side_data[avctx->nb_coded_side_data - 1].type = AV_PKT_DATA_CPB_PROPERTIES;
|
|
|
|
avctx->coded_side_data[avctx->nb_coded_side_data - 1].data = (uint8_t*)props;
|
|
|
|
avctx->coded_side_data[avctx->nb_coded_side_data - 1].size = size;
|
|
|
|
|
|
|
|
return props;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void codec_parameters_reset(AVCodecParameters *par)
|
|
|
|
{
|
|
|
|
av_freep(&par->extradata);
|
|
|
|
|
|
|
|
memset(par, 0, sizeof(*par));
|
|
|
|
|
|
|
|
par->codec_type = AVMEDIA_TYPE_UNKNOWN;
|
|
|
|
par->codec_id = AV_CODEC_ID_NONE;
|
|
|
|
par->format = -1;
|
|
|
|
par->field_order = AV_FIELD_UNKNOWN;
|
|
|
|
par->color_range = AVCOL_RANGE_UNSPECIFIED;
|
|
|
|
par->color_primaries = AVCOL_PRI_UNSPECIFIED;
|
|
|
|
par->color_trc = AVCOL_TRC_UNSPECIFIED;
|
|
|
|
par->color_space = AVCOL_SPC_UNSPECIFIED;
|
|
|
|
par->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
|
|
|
|
par->sample_aspect_ratio = (AVRational){ 0, 1 };
|
|
|
|
}
|
|
|
|
|
|
|
|
AVCodecParameters *avcodec_parameters_alloc(void)
|
|
|
|
{
|
|
|
|
AVCodecParameters *par = av_mallocz(sizeof(*par));
|
|
|
|
|
|
|
|
if (!par)
|
|
|
|
return NULL;
|
|
|
|
codec_parameters_reset(par);
|
|
|
|
return par;
|
|
|
|
}
|
|
|
|
|
|
|
|
void avcodec_parameters_free(AVCodecParameters **ppar)
|
|
|
|
{
|
|
|
|
AVCodecParameters *par = *ppar;
|
|
|
|
|
|
|
|
if (!par)
|
|
|
|
return;
|
|
|
|
codec_parameters_reset(par);
|
|
|
|
|
|
|
|
av_freep(ppar);
|
|
|
|
}
|
|
|
|
|
|
|
|
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
|
|
|
|
{
|
|
|
|
codec_parameters_reset(dst);
|
|
|
|
memcpy(dst, src, sizeof(*dst));
|
|
|
|
|
|
|
|
dst->extradata = NULL;
|
|
|
|
dst->extradata_size = 0;
|
|
|
|
if (src->extradata) {
|
|
|
|
dst->extradata = av_mallocz(src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
if (!dst->extradata)
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
memcpy(dst->extradata, src->extradata, src->extradata_size);
|
|
|
|
dst->extradata_size = src->extradata_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int avcodec_parameters_from_context(AVCodecParameters *par,
|
|
|
|
const AVCodecContext *codec)
|
|
|
|
{
|
|
|
|
codec_parameters_reset(par);
|
|
|
|
|
|
|
|
par->codec_type = codec->codec_type;
|
|
|
|
par->codec_id = codec->codec_id;
|
|
|
|
par->codec_tag = codec->codec_tag;
|
|
|
|
|
|
|
|
par->bit_rate = codec->bit_rate;
|
|
|
|
par->bits_per_coded_sample = codec->bits_per_coded_sample;
|
|
|
|
par->profile = codec->profile;
|
|
|
|
par->level = codec->level;
|
|
|
|
|
|
|
|
switch (par->codec_type) {
|
|
|
|
case AVMEDIA_TYPE_VIDEO:
|
|
|
|
par->format = codec->pix_fmt;
|
|
|
|
par->width = codec->width;
|
|
|
|
par->height = codec->height;
|
|
|
|
par->field_order = codec->field_order;
|
|
|
|
par->color_range = codec->color_range;
|
|
|
|
par->color_primaries = codec->color_primaries;
|
|
|
|
par->color_trc = codec->color_trc;
|
|
|
|
par->color_space = codec->colorspace;
|
|
|
|
par->chroma_location = codec->chroma_sample_location;
|
|
|
|
par->sample_aspect_ratio = codec->sample_aspect_ratio;
|
|
|
|
break;
|
|
|
|
case AVMEDIA_TYPE_AUDIO:
|
|
|
|
par->format = codec->sample_fmt;
|
|
|
|
par->channel_layout = codec->channel_layout;
|
|
|
|
par->channels = codec->channels;
|
|
|
|
par->sample_rate = codec->sample_rate;
|
|
|
|
par->block_align = codec->block_align;
|
|
|
|
par->initial_padding = codec->initial_padding;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (codec->extradata) {
|
|
|
|
par->extradata = av_mallocz(codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
if (!par->extradata)
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
memcpy(par->extradata, codec->extradata, codec->extradata_size);
|
|
|
|
par->extradata_size = codec->extradata_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int avcodec_parameters_to_context(AVCodecContext *codec,
|
|
|
|
const AVCodecParameters *par)
|
|
|
|
{
|
|
|
|
codec->codec_type = par->codec_type;
|
|
|
|
codec->codec_id = par->codec_id;
|
|
|
|
codec->codec_tag = par->codec_tag;
|
|
|
|
|
|
|
|
codec->bit_rate = par->bit_rate;
|
|
|
|
codec->bits_per_coded_sample = par->bits_per_coded_sample;
|
|
|
|
codec->profile = par->profile;
|
|
|
|
codec->level = par->level;
|
|
|
|
|
|
|
|
switch (par->codec_type) {
|
|
|
|
case AVMEDIA_TYPE_VIDEO:
|
|
|
|
codec->pix_fmt = par->format;
|
|
|
|
codec->width = par->width;
|
|
|
|
codec->height = par->height;
|
|
|
|
codec->field_order = par->field_order;
|
|
|
|
codec->color_range = par->color_range;
|
|
|
|
codec->color_primaries = par->color_primaries;
|
|
|
|
codec->color_trc = par->color_trc;
|
|
|
|
codec->colorspace = par->color_space;
|
|
|
|
codec->chroma_sample_location = par->chroma_location;
|
|
|
|
codec->sample_aspect_ratio = par->sample_aspect_ratio;
|
|
|
|
break;
|
|
|
|
case AVMEDIA_TYPE_AUDIO:
|
|
|
|
codec->sample_fmt = par->format;
|
|
|
|
codec->channel_layout = par->channel_layout;
|
|
|
|
codec->channels = par->channels;
|
|
|
|
codec->sample_rate = par->sample_rate;
|
|
|
|
codec->block_align = par->block_align;
|
|
|
|
codec->initial_padding = par->initial_padding;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (par->extradata) {
|
|
|
|
av_freep(&codec->extradata);
|
|
|
|
codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
if (!codec->extradata)
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
memcpy(codec->extradata, par->extradata, par->extradata_size);
|
|
|
|
codec->extradata_size = par->extradata_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|