static void *codec_mutex;
static void *avformat_mutex;
-void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
+#if FF_API_FAST_MALLOC && CONFIG_SHARED && HAVE_SYMVER
+FF_SYMVER(void*, av_fast_realloc, (void *ptr, unsigned int *size, size_t min_size), "LIBAVCODEC_55")
{
- if (min_size < *size)
- return ptr;
-
- min_size = FFMAX(17 * min_size / 16 + 32, min_size);
-
- ptr = av_realloc(ptr, min_size);
- /* we could set this to the unmodified min_size but this is safer
- * if the user lost the ptr and uses NULL now
- */
- if (!ptr)
- min_size = 0;
-
- *size = min_size;
-
- return ptr;
+ return av_fast_realloc(ptr, size, min_size);
}
-void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
+FF_SYMVER(void, av_fast_malloc, (void *ptr, unsigned int *size, size_t min_size), "LIBAVCODEC_55")
{
- void **p = ptr;
- if (min_size < *size)
- return;
- min_size = FFMAX(17 * min_size / 16 + 32, min_size);
- av_free(*p);
- *p = av_malloc(min_size);
- if (!*p)
- min_size = 0;
- *size = min_size;
+ av_fast_malloc(ptr, size, min_size);
}
+#endif
void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size)
{
return EDGE_WIDTH;
}
+#if FF_API_SET_DIMENSIONS
void avcodec_set_dimensions(AVCodecContext *s, int width, int height)
{
- s->coded_width = width;
- s->coded_height = height;
- s->width = width;
- s->height = 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;
}
#if HAVE_NEON || ARCH_PPC || HAVE_MMX
default: return AVERROR(EINVAL);
}
- frame->pkt_pts = avctx->pkt ? avctx->pkt->pts : AV_NOPTS_VALUE;
+ frame->pkt_pts = avctx->internal->pkt ? avctx->internal->pkt->pts : AV_NOPTS_VALUE;
frame->reordered_opaque = avctx->reordered_opaque;
#if FF_API_GET_BUFFER
frame->extended_data = frame->data;
}
+#if FF_API_AVFRAME_LAVC
AVFrame *avcodec_alloc_frame(void)
{
AVFrame *frame = av_mallocz(sizeof(AVFrame));
void avcodec_free_frame(AVFrame **frame)
{
- AVFrame *f;
-
- if (!frame || !*frame)
- return;
-
- f = *frame;
-
- if (f->extended_data != f->data)
- av_freep(&f->extended_data);
-
- av_freep(frame);
+ av_frame_free(frame);
}
+#endif
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
{
goto free_and_end;
}
+ avctx->internal->to_free = av_frame_alloc();
+ if (!avctx->internal->to_free) {
+ 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);
goto free_and_end;
if (avctx->coded_width && avctx->coded_height && !avctx->width && !avctx->height)
- avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
+ ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
else if (avctx->width && avctx->height)
- avcodec_set_dimensions(avctx, 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");
- avcodec_set_dimensions(avctx, 0, 0);
+ ff_set_dimensions(avctx, 0, 0);
}
/* if the decoder init function was already called previously,
AVFrame *frame = NULL;
int ret;
- if (!(frame = avcodec_alloc_frame()))
+ if (!(frame = av_frame_alloc()))
return AVERROR(ENOMEM);
frame->format = src->format;
return ret;
}
-static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
+static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
{
- int size = 0;
+ int size = 0, ret;
const uint8_t *data;
uint32_t flags;
- if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE))
- return;
-
data = av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, &size);
- if (!data || size < 4)
- return;
+ if (!data)
+ return 0;
+
+ if (!(avctx->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) {
+ av_log(avctx, AV_LOG_ERROR, "This decoder does not support parameter "
+ "changes, but PARAM_CHANGE side data was sent to it.\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (size < 4)
+ goto fail;
+
flags = bytestream_get_le32(&data);
size -= 4;
- if (size < 4) /* Required for any of the changes */
- return;
+
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
+ if (size < 4)
+ goto fail;
avctx->channels = bytestream_get_le32(&data);
size -= 4;
}
if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
if (size < 8)
- return;
+ goto fail;
avctx->channel_layout = bytestream_get_le64(&data);
size -= 8;
}
- if (size < 4)
- return;
if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
+ if (size < 4)
+ goto fail;
avctx->sample_rate = bytestream_get_le32(&data);
size -= 4;
}
if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
if (size < 8)
- return;
+ goto fail;
avctx->width = bytestream_get_le32(&data);
avctx->height = bytestream_get_le32(&data);
- avcodec_set_dimensions(avctx, avctx->width, avctx->height);
size -= 8;
+ ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
+ if (ret < 0)
+ return ret;
}
+
+ return 0;
+fail:
+ av_log(avctx, AV_LOG_ERROR, "PARAM_CHANGE side data too small.\n");
+ return AVERROR_INVALIDDATA;
+}
+
+static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
+{
+ int ret;
+
+ /* move the original frame to our backup */
+ av_frame_unref(avci->to_free);
+ av_frame_move_ref(avci->to_free, frame);
+
+ /* now copy everything except the AVBufferRefs back
+ * note that we make a COPY of the side data, so calling av_frame_free() on
+ * the caller's frame will work properly */
+ ret = av_frame_copy_props(frame, avci->to_free);
+ if (ret < 0)
+ return ret;
+
+ memcpy(frame->data, avci->to_free->data, sizeof(frame->data));
+ memcpy(frame->linesize, avci->to_free->linesize, sizeof(frame->linesize));
+ if (avci->to_free->extended_data != avci->to_free->data) {
+ int planes = av_get_channel_layout_nb_channels(avci->to_free->channel_layout);
+ int size = planes * sizeof(*frame->extended_data);
+
+ if (!size) {
+ av_frame_unref(frame);
+ return AVERROR_BUG;
+ }
+
+ frame->extended_data = av_malloc(size);
+ if (!frame->extended_data) {
+ av_frame_unref(frame);
+ return AVERROR(ENOMEM);
+ }
+ memcpy(frame->extended_data, avci->to_free->extended_data,
+ size);
+ } else
+ frame->extended_data = frame->data;
+
+ frame->format = avci->to_free->format;
+ frame->width = avci->to_free->width;
+ frame->height = avci->to_free->height;
+ frame->channel_layout = avci->to_free->channel_layout;
+ frame->nb_samples = avci->to_free->nb_samples;
+
+ return 0;
}
int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
if ((avctx->coded_width || avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
return -1;
- avctx->pkt = avpkt;
- apply_param_change(avctx, avpkt);
-
- avcodec_get_frame_defaults(picture);
+ avctx->internal->pkt = avpkt;
+ ret = apply_param_change(avctx, avpkt);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ return ret;
+ }
- if (!avctx->refcounted_frames)
- av_frame_unref(&avci->to_free);
+ av_frame_unref(picture);
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) {
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
emms_c(); //needed to avoid an emms_c() call before every return;
- if (ret < 0 && picture->data[0])
- av_frame_unref(picture);
-
if (*got_picture_ptr) {
if (!avctx->refcounted_frames) {
- avci->to_free = *picture;
- avci->to_free.extended_data = avci->to_free.data;
- memset(picture->buf, 0, sizeof(picture->buf));
+ int err = unrefcount_frame(avci, picture);
+ if (err < 0)
+ return err;
}
avctx->frame_number++;
- }
+ } else
+ av_frame_unref(picture);
} else
ret = 0;
- /* many decoders assign whole AVFrames, thus overwriting extended_data;
- * make sure it's set correctly */
- picture->extended_data = picture->data;
-
return ret;
}
AVPacket *avpkt)
{
AVCodecInternal *avci = avctx->internal;
- int planar, channels;
int ret = 0;
*got_frame_ptr = 0;
- avctx->pkt = avpkt;
+ avctx->internal->pkt = avpkt;
if (!avpkt->data && avpkt->size) {
av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
return AVERROR(EINVAL);
}
- apply_param_change(avctx, avpkt);
-
- avcodec_get_frame_defaults(frame);
+ ret = apply_param_change(avctx, avpkt);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ return ret;
+ }
- if (!avctx->refcounted_frames)
- av_frame_unref(&avci->to_free);
+ av_frame_unref(frame);
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
frame->format = avctx->sample_fmt;
if (!avctx->refcounted_frames) {
- avci->to_free = *frame;
- avci->to_free.extended_data = avci->to_free.data;
- memset(frame->buf, 0, sizeof(frame->buf));
- frame->extended_buf = NULL;
- frame->nb_extended_buf = 0;
+ int err = unrefcount_frame(avci, frame);
+ if (err < 0)
+ return err;
}
- } else if (frame->data[0])
+ } else
av_frame_unref(frame);
}
- /* many decoders assign whole AVFrames, thus overwriting extended_data;
- * make sure it's set correctly; assume decoders that actually use
- * extended_data are doing it correctly */
- planar = av_sample_fmt_is_planar(frame->format);
- channels = av_get_channel_layout_nb_channels(frame->channel_layout);
- if (!(planar && channels > AV_NUM_DATA_POINTERS))
- frame->extended_data = frame->data;
return ret;
}
{
int ret;
- avctx->pkt = avpkt;
+ avctx->internal->pkt = avpkt;
*got_sub_ptr = 0;
ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt);
if (*got_sub_ptr)
if (avcodec_is_open(avctx)) {
FramePool *pool = avctx->internal->pool;
int i;
- if (HAVE_THREADS && avctx->thread_opaque)
+ if (HAVE_THREADS && avctx->internal->thread_ctx)
ff_thread_free(avctx);
if (avctx->codec && avctx->codec->close)
avctx->codec->close(avctx);
avctx->coded_frame = NULL;
- if (!avctx->refcounted_frames)
- av_frame_unref(&avctx->internal->to_free);
+ av_frame_free(&avctx->internal->to_free);
for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
av_buffer_pool_uninit(&pool->pools[i]);
av_freep(&avctx->internal->pool);
avctx->codec->flush(avctx);
if (!avctx->refcounted_frames)
- av_frame_unref(&avctx->internal->to_free);
+ av_frame_unref(avctx->internal->to_free);
}
int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
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:
return hwaccel ? hwaccel->next : first_hwaccel;
}
-AVHWAccel *ff_find_hwaccel(enum AVCodecID codec_id, enum AVPixelFormat pix_fmt)
+AVHWAccel *ff_find_hwaccel(AVCodecContext *avctx)
{
+ enum AVCodecID codec_id = avctx->codec->id;
+ enum AVPixelFormat pix_fmt = avctx->pix_fmt;
+
AVHWAccel *hwaccel = NULL;
while ((hwaccel = av_hwaccel_next(hwaccel)))