X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Futils.c;h=d6019d957f7d8b4af0ff2c168c3eac4a0c900169;hb=b0de1c766329dd8c9960ad1722e2f653160abc1b;hp=25914282dc69926747e044cf1ca8ea1a40b0e2a2;hpb=7c45087b8441441fc929a6df363f6fa010ef23b0;p=ffmpeg diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 25914282dc6..d6019d957f7 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -26,11 +26,13 @@ */ #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/internal.h" #include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" @@ -42,47 +44,28 @@ #include "thread.h" #include "internal.h" #include "bytestream.h" +#include "version.h" #include #include #include #include static int volatile entangled_thread_counter = 0; -static int (*ff_lockmgr_cb)(void **mutex, enum AVLockOp op); +static int (*lockmgr_cb)(void **mutex, enum AVLockOp op); 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) { @@ -108,7 +91,7 @@ AVCodec *av_codec_next(const AVCodec *c) return first_avcodec; } -static void avcodec_init(void) +static av_cold void avcodec_init(void) { static int initialized = 0; @@ -116,7 +99,8 @@ static void avcodec_init(void) return; initialized = 1; - ff_dsputil_static_init(); + if (CONFIG_DSPUTIL) + ff_dsputil_static_init(); } int av_codec_is_encoder(const AVCodec *codec) @@ -129,7 +113,7 @@ int av_codec_is_decoder(const AVCodec *codec) return codec && codec->decode; } -void avcodec_register(AVCodec *codec) +av_cold void avcodec_register(AVCodec *codec) { AVCodec **p; avcodec_init(); @@ -143,20 +127,68 @@ void avcodec_register(AVCodec *codec) 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) { - 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; +} + +int ff_set_sar(AVCodecContext *avctx, AVRational sar) +{ + int ret = av_image_check_sar(avctx->width, avctx->height, sar); -#if (ARCH_ARM && HAVE_NEON) || ARCH_PPC || HAVE_MMX + if (ret < 0) { + av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\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_NEON || ARCH_PPC || HAVE_MMX # define STRIDE_ALIGN 16 #else # define STRIDE_ALIGN 8 @@ -172,6 +204,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, 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: @@ -195,10 +228,14 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, 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: @@ -322,11 +359,6 @@ static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); - if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) { - w += EDGE_WIDTH * 2; - h += EDGE_WIDTH * 2; - } - do { // NOTE: do not align linesizes individually, this breaks e.g. assumptions // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 @@ -450,9 +482,6 @@ fail: static int video_get_buffer(AVCodecContext *s, AVFrame *pic) { FramePool *pool = s->internal->pool; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format); - int pixel_size = desc->comp[0].step_minus1 + 1; - int h_chroma_shift, v_chroma_shift; int i; if (pic->data[0] != NULL) { @@ -463,26 +492,14 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic) memset(pic->data, 0, sizeof(pic->data)); pic->extended_data = pic->data; - av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); - for (i = 0; i < 4 && pool->pools[i]; i++) { - const int h_shift = i == 0 ? 0 : h_chroma_shift; - const int v_shift = i == 0 ? 0 : v_chroma_shift; - pic->linesize[i] = pool->linesize[i]; pic->buf[i] = av_buffer_pool_get(pool->pools[i]); if (!pic->buf[i]) goto fail; - // no edge if EDGE EMU or not planar YUV - if ((s->flags & CODEC_FLAG_EMU_EDGE) || !pool->pools[2]) - pic->data[i] = pic->buf[i]->data; - else { - pic->data[i] = pic->buf[i]->data + - FFALIGN((pic->linesize[i] * EDGE_WIDTH >> v_shift) + - (pixel_size * EDGE_WIDTH >> h_shift), pool->stride_align[i]); - } + pic->data[i] = pic->buf[i]->data; } for (; i < AV_NUM_DATA_POINTERS; i++) { pic->data[i] = NULL; @@ -508,7 +525,9 @@ int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags return ret; #if FF_API_GET_BUFFER +FF_DISABLE_DEPRECATION_WARNINGS frame->type = FF_BUFFER_TYPE_INTERNAL; +FF_ENABLE_DEPRECATION_WARNINGS #endif switch (avctx->codec_type) { @@ -522,6 +541,7 @@ int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags } #if FF_API_GET_BUFFER +FF_DISABLE_DEPRECATION_WARNINGS int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame) { return avcodec_default_get_buffer2(avctx, frame, 0); @@ -535,7 +555,8 @@ typedef struct CompatReleaseBufPriv { static void compat_free_buffer(void *opaque, uint8_t *data) { CompatReleaseBufPriv *priv = opaque; - priv->avctx.release_buffer(&priv->avctx, &priv->frame); + if (priv->avctx.release_buffer) + priv->avctx.release_buffer(&priv->avctx, &priv->frame); av_freep(&priv); } @@ -544,23 +565,80 @@ static void compat_release_buffer(void *opaque, uint8_t *data) AVBufferRef *buf = opaque; av_buffer_unref(&buf); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) +{ + AVPacket *pkt = avctx->internal->pkt; + uint8_t *packet_sd; + int size; + AVFrameSideData *frame_sd; + +#if FF_API_AVFRAME_COLORSPACE + frame->color_primaries = avctx->color_primaries; + frame->color_trc = avctx->color_trc; + frame->colorspace = avctx->colorspace; + frame->color_range = avctx->color_range; + frame->chroma_location = avctx->chroma_sample_location; #endif + frame->reordered_opaque = avctx->reordered_opaque; + if (!pkt) { + frame->pkt_pts = AV_NOPTS_VALUE; + return 0; + } + + frame->pkt_pts = pkt->pts; + + /* copy the replaygain data to the output frame */ + packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_REPLAYGAIN, &size); + if (packet_sd) { + frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_REPLAYGAIN, size); + if (!frame_sd) + return AVERROR(ENOMEM); + + memcpy(frame_sd->data, packet_sd, size); + } + /* copy the displaymatrix to the output frame */ + packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, &size); + if (packet_sd) { + frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX, size); + if (!frame_sd) + return AVERROR(ENOMEM); + + memcpy(frame_sd->data, packet_sd, size); + } + + return 0; +} + int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) { + const AVHWAccel *hwaccel = avctx->hwaccel; + int override_dimensions = 1; int ret; switch (avctx->codec_type) { case AVMEDIA_TYPE_VIDEO: - if (!frame->width) - frame->width = avctx->width; - if (!frame->height) - frame->height = avctx->height; + if (frame->width <= 0 || frame->height <= 0) { + frame->width = FFMAX(avctx->width, avctx->coded_width); + frame->height = FFMAX(avctx->height, avctx->coded_height); + override_dimensions = 0; + } if (frame->format < 0) frame->format = avctx->pix_fmt; if (!frame->sample_aspect_ratio.num) frame->sample_aspect_ratio = avctx->sample_aspect_ratio; + if (av_image_check_sar(frame->width, frame->height, + frame->sample_aspect_ratio) < 0) { + av_log(avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n", + frame->sample_aspect_ratio.num, + frame->sample_aspect_ratio.den); + frame->sample_aspect_ratio = (AVRational){ 0, 1 }; + } + if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) return ret; break; @@ -595,10 +673,17 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) default: return AVERROR(EINVAL); } - frame->pkt_pts = avctx->pkt ? avctx->pkt->pts : AV_NOPTS_VALUE; - frame->reordered_opaque = avctx->reordered_opaque; + ret = ff_decode_frame_props(avctx, frame); + if (ret < 0) + return ret; + + if (hwaccel && hwaccel->alloc_frame) { + ret = hwaccel->alloc_frame(avctx, frame); + goto end; + } #if FF_API_GET_BUFFER +FF_DISABLE_DEPRECATION_WARNINGS /* * Wrap an old get_buffer()-allocated buffer in an bunch of AVBuffers. * We wrap each plane in its own AVBuffer. Each of those has a reference to @@ -658,15 +743,19 @@ do { \ if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); - if (!desc) { + planes = av_pix_fmt_count_planes(frame->format); + /* workaround for AVHWAccel plane count of 0, buf[0] is used as + check for allocated buffers: make libavcodec happy */ + if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) + planes = 1; + if (!desc || planes <= 0) { ret = AVERROR(EINVAL); goto fail; } - planes = (desc->flags & PIX_FMT_PLANAR) ? desc->nb_components : 1; for (i = 0; i < planes; i++) { - int h_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; - int plane_size = (frame->width >> h_shift) * frame->linesize[i]; + int v_shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; + int plane_size = (frame->height >> v_shift) * frame->linesize[i]; WRAP_PLANE(frame->buf[i], frame->data[i], plane_size); } @@ -687,7 +776,7 @@ do { \ for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++) WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]); - for (i = 0; i < planes - FF_ARRAY_ELEMS(frame->buf); i++) + for (i = 0; i < frame->nb_extended_buf; i++) WRAP_PLANE(frame->extended_buf[i], frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)], frame->linesize[0]); @@ -695,6 +784,9 @@ do { \ av_buffer_unref(&dummy_buf); + frame->width = avctx->width; + frame->height = avctx->height; + return 0; fail: @@ -703,14 +795,23 @@ fail: av_buffer_unref(&dummy_buf); return ret; } +FF_ENABLE_DEPRECATION_WARNINGS #endif - return avctx->get_buffer2(avctx, frame, flags); + ret = avctx->get_buffer2(avctx, frame, flags); + +end: + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) { + frame->width = avctx->width; + frame->height = avctx->height; + } + + return ret; } int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame) { - AVFrame tmp; + AVFrame *tmp; int ret; av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO); @@ -719,20 +820,22 @@ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame) return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); if (av_frame_is_writable(frame)) - return 0; + return ff_decode_frame_props(avctx, frame); + + tmp = av_frame_alloc(); + if (!tmp) + return AVERROR(ENOMEM); - av_frame_move_ref(&tmp, frame); + av_frame_move_ref(tmp, frame); ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF); if (ret < 0) { - av_frame_unref(&tmp); + av_frame_free(&tmp); return ret; } - av_image_copy(frame->data, frame->linesize, tmp.data, tmp.linesize, - frame->format, frame->width, frame->height); - - av_frame_unref(&tmp); + av_frame_copy(frame, tmp); + av_frame_free(&tmp); return 0; } @@ -746,6 +849,7 @@ void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic) int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic) { av_assert0(0); + return AVERROR_BUG; } #endif @@ -776,7 +880,7 @@ int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - return desc->flags & PIX_FMT_HWACCEL; + return desc->flags & AV_PIX_FMT_FLAG_HWACCEL; } enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt) @@ -786,6 +890,65 @@ enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const en return fmt[0]; } +static AVHWAccel *find_hwaccel(enum AVCodecID codec_id, + enum AVPixelFormat pix_fmt) +{ + AVHWAccel *hwaccel = NULL; + + while ((hwaccel = av_hwaccel_next(hwaccel))) + if (hwaccel->id == codec_id + && hwaccel->pix_fmt == pix_fmt) + return hwaccel; + return NULL; +} + + +int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) +{ + const AVPixFmtDescriptor *desc; + enum AVPixelFormat ret = avctx->get_format(avctx, fmt); + + desc = av_pix_fmt_desc_get(ret); + if (!desc) + return AV_PIX_FMT_NONE; + + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + av_freep(&avctx->internal->hwaccel_priv_data); + avctx->hwaccel = NULL; + + if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) { + AVHWAccel *hwaccel; + int err; + + hwaccel = find_hwaccel(avctx->codec_id, ret); + if (!hwaccel) { + av_log(avctx, AV_LOG_ERROR, + "Could not find an AVHWAccel for the pixel format: %s", + desc->name); + return AV_PIX_FMT_NONE; + } + + if (hwaccel->priv_data_size) { + avctx->internal->hwaccel_priv_data = av_mallocz(hwaccel->priv_data_size); + if (!avctx->internal->hwaccel_priv_data) + return AV_PIX_FMT_NONE; + } + + if (hwaccel->init) { + err = hwaccel->init(avctx); + if (err < 0) { + av_freep(&avctx->internal->hwaccel_priv_data); + return AV_PIX_FMT_NONE; + } + } + avctx->hwaccel = hwaccel; + } + + return ret; +} + +#if FF_API_AVFRAME_LAVC void avcodec_get_frame_defaults(AVFrame *frame) { if (frame->extended_data != frame->data) @@ -807,25 +970,18 @@ AVFrame *avcodec_alloc_frame(void) if (frame == NULL) return NULL; +FF_DISABLE_DEPRECATION_WARNINGS avcodec_get_frame_defaults(frame); +FF_ENABLE_DEPRECATION_WARNINGS return frame; } 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) { @@ -854,8 +1010,8 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code av_dict_copy(&tmp, *options, 0); /* If there is a user-supplied mutex locking routine, call it. */ - if (ff_lockmgr_cb) { - if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) + if (lockmgr_cb) { + if ((*lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN)) return -1; } @@ -878,6 +1034,12 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code 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); @@ -898,16 +1060,28 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code if ((ret = av_opt_set_dict(avctx, &tmp)) < 0) goto free_and_end; - if (avctx->coded_width && avctx->coded_height) - avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height); + 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) - 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 (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, @@ -946,7 +1120,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code avctx->time_base.den = avctx->sample_rate; } - if (HAVE_THREADS && !avctx->thread_opaque) { + if (HAVE_THREADS) { ret = ff_thread_init(avctx); if (ret < 0) { goto free_and_end; @@ -1051,8 +1225,8 @@ end: entangled_thread_counter--; /* Release any user-supplied mutex. */ - if (ff_lockmgr_cb) { - (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); + if (lockmgr_cb) { + (*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); } if (options) { av_dict_free(options); @@ -1063,8 +1237,10 @@ end: free_and_end: av_dict_free(&tmp); av_freep(&avctx->priv_data); - if (avctx->internal) + if (avctx->internal) { + av_frame_free(&avctx->internal->to_free); av_freep(&avctx->internal->pool); + } av_freep(&avctx->internal); avctx->codec = NULL; goto end; @@ -1078,7 +1254,9 @@ int ff_alloc_packet(AVPacket *avpkt, int size) if (avpkt->data) { AVBufferRef *buf = avpkt->buf; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS void *destruct = avpkt->destruct; +FF_ENABLE_DEPRECATION_WARNINGS #endif if (avpkt->size < size) @@ -1086,7 +1264,9 @@ int ff_alloc_packet(AVPacket *avpkt, int size) av_init_packet(avpkt); #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS avpkt->destruct = destruct; +FF_ENABLE_DEPRECATION_WARNINGS #endif avpkt->buf = buf; avpkt->size = size; @@ -1102,26 +1282,22 @@ int ff_alloc_packet(AVPacket *avpkt, int size) static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src) { AVFrame *frame = NULL; - uint8_t *buf = NULL; int ret; - if (!(frame = avcodec_alloc_frame())) + if (!(frame = av_frame_alloc())) return AVERROR(ENOMEM); - *frame = *src; - if ((ret = av_samples_get_buffer_size(&frame->linesize[0], s->channels, - s->frame_size, s->sample_fmt, 0)) < 0) + frame->format = src->format; + frame->channel_layout = src->channel_layout; + frame->nb_samples = s->frame_size; + ret = av_frame_get_buffer(frame, 32); + if (ret < 0) goto fail; - if (!(buf = av_malloc(ret))) { - ret = AVERROR(ENOMEM); + ret = av_frame_copy_props(frame, src); + if (ret < 0) goto fail; - } - frame->nb_samples = s->frame_size; - if ((ret = avcodec_fill_audio_frame(frame, s->channels, s->sample_fmt, - buf, ret, 0)) < 0) - goto fail; if ((ret = av_samples_copy(frame->extended_data, src->extended_data, 0, 0, src->nb_samples, s->channels, s->sample_fmt)) < 0) goto fail; @@ -1135,10 +1311,7 @@ static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src) return 0; fail: - if (frame->extended_data != frame->data) - av_freep(&frame->extended_data); - av_freep(&buf); - av_freep(&frame); + av_frame_free(&frame); return ret; } @@ -1235,133 +1408,11 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, avpkt->flags |= AV_PKT_FLAG_KEY; end: - if (padded_frame) { - av_freep(&padded_frame->data[0]); - if (padded_frame->extended_data != padded_frame->data) - av_freep(&padded_frame->extended_data); - av_freep(&padded_frame); - } + av_frame_free(&padded_frame); return ret; } -#if FF_API_OLD_ENCODE_AUDIO -int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, - uint8_t *buf, int buf_size, - const short *samples) -{ - AVPacket pkt; - AVFrame frame0 = { { 0 } }; - AVFrame *frame; - int ret, samples_size, got_packet; - - av_init_packet(&pkt); - pkt.data = buf; - pkt.size = buf_size; - - if (samples) { - frame = &frame0; - avcodec_get_frame_defaults(frame); - - if (avctx->frame_size) { - frame->nb_samples = avctx->frame_size; - } else { - /* if frame_size is not set, the number of samples must be - * calculated from the buffer size */ - int64_t nb_samples; - if (!av_get_bits_per_sample(avctx->codec_id)) { - av_log(avctx, AV_LOG_ERROR, "avcodec_encode_audio() does not " - "support this codec\n"); - return AVERROR(EINVAL); - } - nb_samples = (int64_t)buf_size * 8 / - (av_get_bits_per_sample(avctx->codec_id) * - avctx->channels); - if (nb_samples >= INT_MAX) - return AVERROR(EINVAL); - frame->nb_samples = nb_samples; - } - - /* it is assumed that the samples buffer is large enough based on the - * relevant parameters */ - samples_size = av_samples_get_buffer_size(NULL, avctx->channels, - frame->nb_samples, - avctx->sample_fmt, 1); - if ((ret = avcodec_fill_audio_frame(frame, avctx->channels, - avctx->sample_fmt, - (const uint8_t *)samples, - samples_size, 1))) - return ret; - - /* fabricate frame pts from sample count. - * this is needed because the avcodec_encode_audio() API does not have - * a way for the user to provide pts */ - frame->pts = ff_samples_to_time_base(avctx, - avctx->internal->sample_count); - avctx->internal->sample_count += frame->nb_samples; - } else { - frame = NULL; - } - - got_packet = 0; - ret = avcodec_encode_audio2(avctx, &pkt, frame, &got_packet); - if (!ret && got_packet && avctx->coded_frame) { - avctx->coded_frame->pts = pkt.pts; - avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); - } - /* free any side data since we cannot return it */ - if (pkt.side_data_elems > 0) { - int i; - for (i = 0; i < pkt.side_data_elems; i++) - av_free(pkt.side_data[i].data); - av_freep(&pkt.side_data); - pkt.side_data_elems = 0; - } - - if (frame && frame->extended_data != frame->data) - av_free(frame->extended_data); - - return ret ? ret : pkt.size; -} - -#endif - -#if FF_API_OLD_ENCODE_VIDEO -int attribute_align_arg avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, - const AVFrame *pict) -{ - AVPacket pkt; - int ret, got_packet = 0; - - if (buf_size < FF_MIN_BUFFER_SIZE) { - av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n"); - return -1; - } - - av_init_packet(&pkt); - pkt.data = buf; - pkt.size = buf_size; - - ret = avcodec_encode_video2(avctx, &pkt, pict, &got_packet); - if (!ret && got_packet && avctx->coded_frame) { - avctx->coded_frame->pts = pkt.pts; - avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); - } - - /* free any side data since we cannot return it */ - if (pkt.side_data_elems > 0) { - int i; - for (i = 0; i < pkt.side_data_elems; i++) - av_free(pkt.side_data[i].data); - av_freep(&pkt.side_data); - pkt.side_data_elems = 0; - } - - return ret ? ret : pkt.size; -} - -#endif - int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, @@ -1422,46 +1473,106 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, 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, @@ -1475,13 +1586,15 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi 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) @@ -1502,99 +1615,47 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi 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; + 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; } -#if FF_API_OLD_DECODE_AUDIO -int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, - int *frame_size_ptr, - AVPacket *avpkt) -{ - AVFrame frame = { { 0 } }; - int ret, got_frame = 0; - - if (avctx->get_buffer != avcodec_default_get_buffer) { - av_log(avctx, AV_LOG_ERROR, "Custom get_buffer() for use with" - "avcodec_decode_audio3() detected. Overriding with avcodec_default_get_buffer\n"); - av_log(avctx, AV_LOG_ERROR, "Please port your application to " - "avcodec_decode_audio4()\n"); - avctx->get_buffer = avcodec_default_get_buffer; - } - - ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt); - - if (ret >= 0 && got_frame) { - int ch, plane_size; - int planar = av_sample_fmt_is_planar(avctx->sample_fmt); - int data_size = av_samples_get_buffer_size(&plane_size, avctx->channels, - frame.nb_samples, - avctx->sample_fmt, 1); - if (*frame_size_ptr < data_size) { - av_log(avctx, AV_LOG_ERROR, "output buffer size is too small for " - "the current frame (%d < %d)\n", *frame_size_ptr, data_size); - return AVERROR(EINVAL); - } - - memcpy(samples, frame.extended_data[0], plane_size); - - if (planar && avctx->channels > 1) { - uint8_t *out = ((uint8_t *)samples) + plane_size; - for (ch = 1; ch < avctx->channels; ch++) { - memcpy(out, frame.extended_data[ch], plane_size); - out += plane_size; - } - } - *frame_size_ptr = data_size; - } else { - *frame_size_ptr = 0; - } - return ret; -} - -#endif - int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, 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); @@ -1605,22 +1666,14 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, frame->format = avctx->sample_fmt; if (!avctx->refcounted_frames) { - avci->to_free = *frame; - avci->to_free.extended_data = avci->to_free.data; + int err = unrefcount_frame(avci, frame); + if (err < 0) + return err; } - } - - if (ret < 0 && 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; } @@ -1631,7 +1684,7 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, { 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) @@ -1660,32 +1713,23 @@ void avsubtitle_free(AVSubtitle *sub) av_cold int avcodec_close(AVCodecContext *avctx) { - /* If there is a user-supplied mutex locking routine, call it. */ - if (ff_lockmgr_cb) { - if ((*ff_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 around avcodec_open/close()\n"); - entangled_thread_counter--; - return -1; - } - 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); + + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + av_freep(&avctx->internal->hwaccel_priv_data); + av_freep(&avctx->internal); } @@ -1697,12 +1741,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) av_freep(&avctx->extradata); avctx->codec = NULL; avctx->active_thread_type = 0; - entangled_thread_counter--; - /* Release any user-supplied mutex. */ - if (ff_lockmgr_cb) { - (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); - } return 0; } @@ -1827,8 +1866,6 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) /* fake mpeg2 transport stream codec (currently not * registered) */ codec_name = "mpeg2ts"; - } else if (enc->codec_name[0] != '\0') { - codec_name = enc->codec_name; } else { /* output avi tags */ char tag_buf[32]; @@ -1957,6 +1994,9 @@ void avcodec_flush_buffers(AVCodecContext *avctx) ff_thread_flush(avctx); else if (avctx->codec->flush) avctx->codec->flush(avctx); + + if (!avctx->refcounted_frames) + av_frame_unref(avctx->internal->to_free); } int av_get_exact_bits_per_sample(enum AVCodecID codec_id) @@ -1984,11 +2024,13 @@ 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: @@ -2196,6 +2238,8 @@ int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b) 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 " @@ -2220,6 +2264,8 @@ void av_log_ask_for_sample(void *avc, const char *msg, ...) va_end(argument_list); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* FF_API_MISSING_SAMPLE */ static AVHWAccel *first_hwaccel = NULL; @@ -2237,32 +2283,21 @@ AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel) return hwaccel ? hwaccel->next : first_hwaccel; } -AVHWAccel *ff_find_hwaccel(enum AVCodecID codec_id, enum AVPixelFormat pix_fmt) -{ - AVHWAccel *hwaccel = NULL; - - while ((hwaccel = av_hwaccel_next(hwaccel))) - if (hwaccel->id == codec_id - && hwaccel->pix_fmt == pix_fmt) - return hwaccel; - return NULL; -} - int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) { - if (ff_lockmgr_cb) { - if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) + if (lockmgr_cb) { + if (lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) return -1; - if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY)) + if (lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY)) return -1; } - ff_lockmgr_cb = cb; + lockmgr_cb = cb; - if (ff_lockmgr_cb) { - if (ff_lockmgr_cb(&codec_mutex, AV_LOCK_CREATE)) + if (lockmgr_cb) { + if (lockmgr_cb(&codec_mutex, AV_LOCK_CREATE)) return -1; - if (ff_lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE)) + if (lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE)) return -1; } return 0; @@ -2270,8 +2305,8 @@ int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op)) int avpriv_lock_avformat(void) { - if (ff_lockmgr_cb) { - if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN)) + if (lockmgr_cb) { + if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_OBTAIN)) return -1; } return 0; @@ -2279,8 +2314,8 @@ int avpriv_lock_avformat(void) int avpriv_unlock_avformat(void) { - if (ff_lockmgr_cb) { - if ((*ff_lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE)) + if (lockmgr_cb) { + if ((*lockmgr_cb)(&avformat_mutex, AV_LOCK_RELEASE)) return -1; } return 0; @@ -2323,7 +2358,8 @@ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) { - av_frame_unref(f->f); + if (f->f) + av_frame_unref(f->f); } void ff_thread_finish_setup(AVCodecContext *avctx) @@ -2358,3 +2394,36 @@ 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; +}