X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Futvideoenc.c;h=9af0f66a71371819921f5f76562ee5c755831289;hb=bb198c4997d5036f3bf91de51e44f807115677d0;hp=085c415caa5b558975b205f7fd0726bf51ee44fe;hpb=716d413c13981da15323c7a3821860536eefdbbb;p=ffmpeg diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index 085c415caa5..9af0f66a713 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -24,12 +24,14 @@ * Ut Video encoder */ +#include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "internal.h" +#include "bswapdsp.h" #include "bytestream.h" #include "put_bits.h" -#include "dsputil.h" +#include "huffyuvencdsp.h" #include "mathops.h" #include "utvideo.h" #include "huffman.h" @@ -46,7 +48,6 @@ static av_cold int utvideo_encode_close(AVCodecContext *avctx) UtvideoContext *c = avctx->priv_data; int i; - av_freep(&avctx->coded_frame); av_freep(&c->slice_bits); for (i = 0; i < 4; i++) av_freep(&c->slice_buffer[i]); @@ -57,7 +58,7 @@ static av_cold int utvideo_encode_close(AVCodecContext *avctx) static av_cold int utvideo_encode_init(AVCodecContext *avctx) { UtvideoContext *c = avctx->priv_data; - int i; + int i, subsampled_height; uint32_t original_format; c->avctx = avctx; @@ -82,7 +83,10 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } c->planes = 3; - avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); + if (avctx->colorspace == AVCOL_SPC_BT709) + avctx->codec_tag = MKTAG('U', 'L', 'H', '0'); + else + avctx->codec_tag = MKTAG('U', 'L', 'Y', '0'); original_format = UTVIDEO_420; break; case AV_PIX_FMT_YUV422P: @@ -92,7 +96,10 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } c->planes = 3; - avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); + if (avctx->colorspace == AVCOL_SPC_BT709) + avctx->codec_tag = MKTAG('U', 'L', 'H', '2'); + else + avctx->codec_tag = MKTAG('U', 'L', 'Y', '2'); original_format = UTVIDEO_422; break; default: @@ -101,7 +108,8 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - ff_dsputil_init(&c->dsp, avctx); + ff_bswapdsp_init(&c->bdsp); + ff_huffyuvencdsp_init(&c->hdsp); /* Check the prediction method, and error out if unsupported */ if (avctx->prediction_method < 0 || avctx->prediction_method > 4) { @@ -125,19 +133,31 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) return AVERROR_OPTION_NOT_FOUND; } - avctx->coded_frame = avcodec_alloc_frame(); + /* + * Check the asked slice count for obviously invalid + * values (> 256 or negative). + */ + if (avctx->slices > 256 || avctx->slices < 0) { + av_log(avctx, AV_LOG_ERROR, + "Slice count %d is not supported in Ut Video (theoretical range is 0-256).\n", + avctx->slices); + return AVERROR(EINVAL); + } - if (!avctx->coded_frame) { - av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n"); - utvideo_encode_close(avctx); - return AVERROR(ENOMEM); + /* Check that the slice count is not larger than the subsampled height */ + subsampled_height = avctx->height >> av_pix_fmt_desc_get(avctx->pix_fmt)->log2_chroma_h; + if (avctx->slices > subsampled_height) { + av_log(avctx, AV_LOG_ERROR, + "Slice count %d is larger than the subsampling-applied height %d.\n", + avctx->slices, subsampled_height); + return AVERROR(EINVAL); } /* extradata size is 4 * 32bit */ avctx->extradata_size = 16; avctx->extradata = av_mallocz(avctx->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata.\n"); @@ -147,7 +167,7 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) for (i = 0; i < c->planes; i++) { c->slice_buffer[i] = av_malloc(c->slice_stride * (avctx->height + 2) + - FF_INPUT_BUFFER_PADDING_SIZE); + AV_INPUT_BUFFER_PADDING_SIZE); if (!c->slice_buffer[i]) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 1.\n"); utvideo_encode_close(avctx); @@ -174,9 +194,19 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx) /* * Set how many slices are going to be used. - * Set one slice for now. + * By default uses multiple slices depending on the subsampled height. + * This enables multithreading in the official decoder. */ - c->slices = 1; + if (!avctx->slices) { + c->slices = subsampled_height / 120; + + if (!c->slices) + c->slices = 1; + else if (c->slices > 256) + c->slices = 256; + } else { + c->slices = avctx->slices; + } /* Set compression mode */ c->compression = COMP_HUFF; @@ -230,20 +260,6 @@ static void mangle_rgb_planes(uint8_t *dst[4], int dst_stride, uint8_t *src, } } -/* Write data to a plane, no prediction applied */ -static void write_plane(uint8_t *src, uint8_t *dst, int stride, - int width, int height) -{ - int i, j; - - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) - *dst++ = src[i]; - - src += stride; - } -} - /* Write data to a plane with left prediction */ static void left_predict(uint8_t *src, uint8_t *dst, int stride, int width, int height) @@ -289,7 +305,7 @@ static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst, int st /* Rest of the coded part uses median prediction */ for (j = 1; j < height; j++) { - c->dsp.sub_hfyu_median_prediction(dst, src - stride, src, width, &A, &B); + c->hdsp.sub_hfyu_median_pred(dst, src - stride, src, width, &A, &B); dst += width; src += stride; } @@ -383,8 +399,9 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, for (i = 0; i < c->slices; i++) { sstart = send; send = height * (i + 1) / c->slices; - write_plane(src + sstart * stride, dst + sstart * width, - stride, width, send - sstart); + av_image_copy_plane(dst + sstart * width, width, + src + sstart * stride, stride, + width, send - sstart); } break; case PRED_LEFT: @@ -474,9 +491,9 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src, slice_len = offset - slice_len; /* Byteswap the written huffman codes */ - c->dsp.bswap_buf((uint32_t *) c->slice_bits, - (uint32_t *) c->slice_bits, - slice_len >> 2); + c->bdsp.bswap_buf((uint32_t *) c->slice_bits, + (uint32_t *) c->slice_bits, + slice_len >> 2); /* Write the offset to the stream */ bytestream2_put_le32(pb, offset); @@ -530,7 +547,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, bytestream2_init_writer(&pb, dst, pkt->size); av_fast_malloc(&c->slice_bits, &c->slice_bits_size, - width * height + FF_INPUT_BUFFER_PADDING_SIZE); + width * height + AV_INPUT_BUFFER_PADDING_SIZE); if (!c->slice_bits) { av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 2.\n"); @@ -598,9 +615,12 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, * At least currently Ut Video is IDR only. * Set flags accordingly. */ - avctx->coded_frame->reference = 0; +#if FF_API_CODED_FRAME +FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = 1; avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; +FF_ENABLE_DEPRECATION_WARNINGS +#endif pkt->size = bytestream2_tell_p(&pb); pkt->flags |= AV_PKT_FLAG_KEY; @@ -613,6 +633,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt, AVCodec ff_utvideo_encoder = { .name = "utvideo", + .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_UTVIDEO, .priv_data_size = sizeof(UtvideoContext), @@ -623,5 +644,4 @@ AVCodec ff_utvideo_encoder = { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), };