* 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"
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]);
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;
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:
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:
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) {
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 */
/*
* 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;
}
}
-/* 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)
/* 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;
}
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:
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);
* At least currently Ut Video is IDR only.
* Set flags accordingly.
*/
+#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;
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),
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"),
};