X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Futils.c;h=a1443920e394dcf4a0349e7d31c2f67437f093cd;hb=e61f39849c2e2b7f492c17b42058242ed2fa4d57;hp=e078a11408399ebe4a3d099c55942de2e67f74fd;hpb=95a8a5aca60ce37d3abdf121a0285c2e317cf521;p=ffmpeg diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e078a114083..a1443920e39 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -39,8 +39,9 @@ #include "libavutil/samplefmt.h" #include "libavutil/dict.h" #include "avcodec.h" -#include "dsputil.h" #include "libavutil/opt.h" +#include "me_cmp.h" +#include "mpegvideo.h" #include "thread.h" #include "internal.h" #include "bytestream.h" @@ -55,18 +56,6 @@ static int (*lockmgr_cb)(void **mutex, enum AVLockOp op); static void *codec_mutex; static void *avformat_mutex; -#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") -{ - return av_fast_realloc(ptr, size, min_size); -} - -FF_SYMVER(void, av_fast_malloc, (void *ptr, unsigned int *size, size_t min_size), "LIBAVCODEC_55") -{ - av_fast_malloc(ptr, size, min_size); -} -#endif - void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) { void **p = ptr; @@ -99,8 +88,8 @@ static av_cold void avcodec_init(void) return; initialized = 1; - if (CONFIG_DSPUTIL) - ff_dsputil_static_init(); + if (CONFIG_ME_CMP) + ff_me_cmp_init_static(); } int av_codec_is_encoder(const AVCodec *codec) @@ -118,7 +107,7 @@ av_cold void avcodec_register(AVCodec *codec) AVCodec **p; avcodec_init(); p = &first_avcodec; - while (*p != NULL) + while (*p) p = &(*p)->next; *p = codec; codec->next = NULL; @@ -127,10 +116,12 @@ av_cold 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) @@ -151,7 +142,42 @@ int ff_set_dimensions(AVCodecContext *s, int width, int height) return ret; } -#if HAVE_NEON || ARCH_PPC || HAVE_MMX +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_16 # define STRIDE_ALIGN 16 #else # define STRIDE_ALIGN 8 @@ -167,11 +193,13 @@ 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: 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: @@ -190,10 +218,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: @@ -317,11 +349,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 @@ -445,12 +472,9 @@ 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) { + if (pic->data[0]) { av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n"); return -1; } @@ -458,26 +482,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; @@ -546,19 +558,77 @@ static void compat_release_buffer(void *opaque, uint8_t *data) FF_ENABLE_DEPRECATION_WARNINGS #endif +int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) +{ + AVPacket *pkt = avctx->internal->pkt; + int i; + struct { + enum AVPacketSideDataType packet; + enum AVFrameSideDataType frame; + } sd[] = { + { AV_PKT_DATA_REPLAYGAIN , AV_FRAME_DATA_REPLAYGAIN }, + { AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX }, + { AV_PKT_DATA_STEREO3D, AV_FRAME_DATA_STEREO3D }, + { AV_PKT_DATA_AUDIO_SERVICE_TYPE, AV_FRAME_DATA_AUDIO_SERVICE_TYPE }, + }; + + 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; + + frame->reordered_opaque = avctx->reordered_opaque; + if (!pkt) { + frame->pkt_pts = AV_NOPTS_VALUE; + return 0; + } + + frame->pkt_pts = pkt->pts; + + for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) { + int size; + uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size); + if (packet_sd) { + AVFrameSideData *frame_sd = av_frame_new_side_data(frame, + sd[i].frame, + 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: - frame->width = FFMAX(avctx->width, avctx->coded_width); - frame->height = FFMAX(avctx->height, avctx->coded_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; @@ -593,8 +663,17 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) default: return AVERROR(EINVAL); } - frame->pkt_pts = avctx->internal->pkt ? avctx->internal->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) { + if (hwaccel->alloc_frame) { + ret = hwaccel->alloc_frame(avctx, frame); + goto end; + } + } else + avctx->sw_pix_fmt = avctx->pix_fmt; #if FF_API_GET_BUFFER FF_DISABLE_DEPRECATION_WARNINGS @@ -648,6 +727,7 @@ do { \ ref_out = av_buffer_create(data, data_size, compat_release_buffer, \ dummy_ref, 0); \ if (!ref_out) { \ + av_buffer_unref(&dummy_ref); \ av_frame_unref(frame); \ ret = AVERROR(ENOMEM); \ goto fail; \ @@ -714,7 +794,8 @@ FF_ENABLE_DEPRECATION_WARNINGS ret = avctx->get_buffer2(avctx, frame, flags); - if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { +end: + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) { frame->width = avctx->width; frame->height = avctx->height; } @@ -724,7 +805,7 @@ FF_ENABLE_DEPRECATION_WARNINGS int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame) { - AVFrame tmp; + AVFrame *tmp; int ret; av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO); @@ -733,20 +814,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; } @@ -801,6 +884,105 @@ 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; +} + +static int setup_hwaccel(AVCodecContext *avctx, + const enum AVPixelFormat fmt, + const char *name) +{ + AVHWAccel *hwa = find_hwaccel(avctx->codec_id, fmt); + int ret = 0; + + if (!hwa) { + av_log(avctx, AV_LOG_ERROR, + "Could not find an AVHWAccel for the pixel format: %s", + name); + return AVERROR(ENOENT); + } + + if (hwa->priv_data_size) { + avctx->internal->hwaccel_priv_data = av_mallocz(hwa->priv_data_size); + if (!avctx->internal->hwaccel_priv_data) + return AVERROR(ENOMEM); + } + + if (hwa->init) { + ret = hwa->init(avctx); + if (ret < 0) { + av_freep(&avctx->internal->hwaccel_priv_data); + return ret; + } + } + + avctx->hwaccel = hwa; + + return 0; +} + +int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) +{ + const AVPixFmtDescriptor *desc; + enum AVPixelFormat *choices; + enum AVPixelFormat ret; + unsigned n = 0; + + while (fmt[n] != AV_PIX_FMT_NONE) + ++n; + + av_assert0(n >= 1); + avctx->sw_pix_fmt = fmt[n - 1]; + av_assert2(!is_hwaccel_pix_fmt(avctx->sw_pix_fmt)); + + choices = av_malloc_array(n + 1, sizeof(*choices)); + if (!choices) + return AV_PIX_FMT_NONE; + + memcpy(choices, fmt, (n + 1) * sizeof(*choices)); + + for (;;) { + if (avctx->hwaccel && avctx->hwaccel->uninit) + avctx->hwaccel->uninit(avctx); + av_freep(&avctx->internal->hwaccel_priv_data); + avctx->hwaccel = NULL; + + ret = avctx->get_format(avctx, choices); + + desc = av_pix_fmt_desc_get(ret); + if (!desc) { + ret = AV_PIX_FMT_NONE; + break; + } + + if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) + break; + + if (!setup_hwaccel(avctx, ret, desc->name)) + break; + + /* Remove failed hwaccel from choices */ + for (n = 0; choices[n] != ret; n++) + av_assert0(choices[n] != AV_PIX_FMT_NONE); + + do + choices[n] = choices[n + 1]; + while (choices[n++] != AV_PIX_FMT_NONE); + } + + av_freep(&choices); + return ret; +} + +#if FF_API_AVFRAME_LAVC void avcodec_get_frame_defaults(AVFrame *frame) { if (frame->extended_data != frame->data) @@ -815,15 +997,16 @@ void avcodec_get_frame_defaults(AVFrame *frame) frame->extended_data = frame->data; } -#if FF_API_AVFRAME_LAVC AVFrame *avcodec_alloc_frame(void) { AVFrame *frame = av_mallocz(sizeof(AVFrame)); - if (frame == NULL) + if (!frame) return NULL; +FF_DISABLE_DEPRECATION_WARNINGS avcodec_get_frame_defaults(frame); +FF_ENABLE_DEPRECATION_WARNINGS return frame; } @@ -867,8 +1050,12 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code } entangled_thread_counter++; - if (entangled_thread_counter != 1) { - av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n"); + if (entangled_thread_counter != 1 && + !(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE)) { + 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; } @@ -925,6 +1112,16 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code 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)) @@ -998,6 +1195,11 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code 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++) @@ -1044,6 +1246,11 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code } } +#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) { @@ -1061,6 +1268,11 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code 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: entangled_thread_counter--; @@ -1076,10 +1288,20 @@ end: 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); + 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; @@ -1188,6 +1410,13 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, frame = &tmp; } + /* extract audio service type metadata */ + if (frame) { + AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_AUDIO_SERVICE_TYPE); + if (sd && sd->size >= sizeof(enum AVAudioServiceType)) + avctx->audio_service_type = *(enum AVAudioServiceType*)sd->data; + } + /* check for valid frame size */ if (frame) { if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { @@ -1249,6 +1478,10 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, end: av_frame_free(&padded_frame); +#if FF_API_AUDIOENC_DELAY + avctx->delay = avctx->initial_padding; +#endif + return ret; } @@ -1467,6 +1700,11 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi } else ret = 0; +#if FF_API_AVCTX_TIMEBASE + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) + avctx->time_base = av_inv_q(avctx->framerate); +#endif + return ret; } @@ -1552,19 +1790,6 @@ void avsubtitle_free(AVSubtitle *sub) av_cold int avcodec_close(AVCodecContext *avctx) { - /* If there is a user-supplied mutex locking routine, call it. */ - 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 around avcodec_open/close()\n"); - entangled_thread_counter--; - return -1; - } - if (avcodec_is_open(avctx)) { FramePool *pool = avctx->internal->pool; int i; @@ -1577,6 +1802,11 @@ av_cold int avcodec_close(AVCodecContext *avctx) 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); } @@ -1588,12 +1818,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 (lockmgr_cb) { - (*lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE); - } return 0; } @@ -1702,6 +1927,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) const AVCodec *p; char buf1[32]; int bitrate; + int new_line = 0; AVRational display_aspect_ratio; if (enc->codec) @@ -1718,8 +1944,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]; @@ -1736,15 +1960,48 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) if (profile) snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile); - if (enc->pix_fmt != AV_PIX_FMT_NONE) { + 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", + " [%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", + "%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, @@ -1774,11 +2031,18 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) 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); + "%d Hz, ", enc->sample_rate); } - av_strlcat(buf, ", ", buf_size); 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), @@ -1870,6 +2134,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id) 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: @@ -2132,42 +2397,40 @@ void av_register_hwaccel(AVHWAccel *hwaccel) hwaccel->next = NULL; } -AVHWAccel *av_hwaccel_next(AVHWAccel *hwaccel) +AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel) { return hwaccel ? hwaccel->next : first_hwaccel; } -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))) - 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 (lockmgr_cb) { - if (lockmgr_cb(&codec_mutex, AV_LOCK_DESTROY)) - return -1; - if (lockmgr_cb(&avformat_mutex, AV_LOCK_DESTROY)) - return -1; + // 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; } - lockmgr_cb = cb; - - if (lockmgr_cb) { - if (lockmgr_cb(&codec_mutex, AV_LOCK_CREATE)) - return -1; - if (lockmgr_cb(&avformat_mutex, AV_LOCK_CREATE)) - return -1; - } return 0; } @@ -2226,7 +2489,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)