summaryrefslogtreecommitdiff
path: root/libavcodec/utvideoenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/utvideoenc.c')
-rw-r--r--libavcodec/utvideoenc.c77
1 files changed, 49 insertions, 28 deletions
diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c
index ef51ed06dd..840742caf7 100644
--- a/libavcodec/utvideoenc.c
+++ b/libavcodec/utvideoenc.c
@@ -2,20 +2,20 @@
* Ut Video encoder
* Copyright (c) 2012 Jan Ekström
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -33,7 +33,6 @@
#include "bswapdsp.h"
#include "bytestream.h"
#include "put_bits.h"
-#include "huffyuvencdsp.h"
#include "mathops.h"
#include "utvideo.h"
#include "huffman.h"
@@ -77,6 +76,7 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx)
c->planes = 4;
avctx->codec_tag = MKTAG('U', 'L', 'R', 'A');
original_format = UTVIDEO_RGBA;
+ avctx->bits_per_coded_sample = 32;
break;
case AV_PIX_FMT_YUV420P:
if (avctx->width & 1 || avctx->height & 1) {
@@ -104,6 +104,14 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx)
avctx->codec_tag = MKTAG('U', 'L', 'Y', '2');
original_format = UTVIDEO_422;
break;
+ case AV_PIX_FMT_YUV444P:
+ c->planes = 3;
+ if (avctx->colorspace == AVCOL_SPC_BT709)
+ avctx->codec_tag = MKTAG('U', 'L', 'H', '4');
+ else
+ avctx->codec_tag = MKTAG('U', 'L', 'Y', '4');
+ original_format = UTVIDEO_444;
+ break;
default:
av_log(avctx, AV_LOG_ERROR, "Unknown pixel format: %d\n",
avctx->pix_fmt);
@@ -111,7 +119,7 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx)
}
ff_bswapdsp_init(&c->bdsp);
- ff_huffyuvencdsp_init(&c->hdsp);
+ ff_llvidencdsp_init(&c->llvidencdsp);
#if FF_API_PRIVATE_OPT
FF_DISABLE_DEPRECATION_WARNINGS
@@ -285,6 +293,9 @@ static void left_predict(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
}
}
+#undef A
+#undef B
+
/* Write data to a plane with median prediction */
static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst,
ptrdiff_t stride, int width, int height)
@@ -313,7 +324,7 @@ static void median_predict(UtvideoContext *c, uint8_t *src, uint8_t *dst,
/* Rest of the coded part uses median prediction */
for (j = 1; j < height; j++) {
- c->hdsp.sub_hfyu_median_pred(dst, src - stride, src, width, &A, &B);
+ c->llvidencdsp.sub_median_pred(dst, src - stride, src, width, &A, &B);
dst += width;
src += stride;
}
@@ -388,7 +399,7 @@ static int write_huff_codes(uint8_t *src, uint8_t *dst, int dst_size,
}
static int encode_plane(AVCodecContext *avctx, uint8_t *src,
- uint8_t *dst, ptrdiff_t stride,
+ uint8_t *dst, ptrdiff_t stride, int plane_no,
int width, int height, PutByteContext *pb)
{
UtvideoContext *c = avctx->priv_data;
@@ -398,15 +409,17 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src,
HuffEntry he[256];
uint32_t offset = 0, slice_len = 0;
+ const int cmask = ~(!plane_no && avctx->pix_fmt == AV_PIX_FMT_YUV420P);
int i, sstart, send = 0;
int symbol;
+ int ret;
/* Do prediction / make planes */
switch (c->frame_pred) {
case PRED_NONE:
for (i = 0; i < c->slices; i++) {
sstart = send;
- send = height * (i + 1) / c->slices;
+ send = height * (i + 1) / c->slices & cmask;
av_image_copy_plane(dst + sstart * width, width,
src + sstart * stride, stride,
width, send - sstart);
@@ -415,7 +428,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src,
case PRED_LEFT:
for (i = 0; i < c->slices; i++) {
sstart = send;
- send = height * (i + 1) / c->slices;
+ send = height * (i + 1) / c->slices & cmask;
left_predict(src + sstart * stride, dst + sstart * width,
stride, width, send - sstart);
}
@@ -423,7 +436,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src,
case PRED_MEDIAN:
for (i = 0; i < c->slices; i++) {
sstart = send;
- send = height * (i + 1) / c->slices;
+ send = height * (i + 1) / c->slices & cmask;
median_predict(c, src + sstart * stride, dst + sstart * width,
stride, width, send - sstart);
}
@@ -442,7 +455,7 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src,
/* If non-zero count is found, see if it matches width * height */
if (counts[symbol]) {
/* Special case if only one symbol was used */
- if (counts[symbol] == width * height) {
+ if (counts[symbol] == width * (int64_t)height) {
/*
* Write a zero for the single symbol
* used in the plane, else 0xFF.
@@ -466,7 +479,8 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src,
}
/* Calculate huffman lengths */
- ff_huff_gen_len_table(lengths, counts);
+ if ((ret = ff_huff_gen_len_table(lengths, counts, 256, 1)) < 0)
+ return ret;
/*
* Write the plane's header into the output packet:
@@ -486,14 +500,14 @@ static int encode_plane(AVCodecContext *avctx, uint8_t *src,
send = 0;
for (i = 0; i < c->slices; i++) {
sstart = send;
- send = height * (i + 1) / c->slices;
+ send = height * (i + 1) / c->slices & cmask;
/*
* Write the huffman codes to a buffer,
* get the offset in bits and convert to bytes.
*/
offset += write_huff_codes(dst + sstart * width, c->slice_bits,
- width * (send - sstart), width,
+ width * height + 4, width,
send - sstart, he) >> 3;
slice_len = offset - slice_len;
@@ -540,22 +554,17 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
int i, ret = 0;
/* Allocate a new packet if needed, and set it to the pointer dst */
- ret = ff_alloc_packet(pkt, (256 + 4 * c->slices + width * height) *
- c->planes + 4);
+ ret = ff_alloc_packet2(avctx, pkt, (256 + 4 * c->slices + width * height) *
+ c->planes + 4, 0);
- if (ret < 0) {
- av_log(avctx, AV_LOG_ERROR,
- "Error allocating the output packet, or the provided packet "
- "was too small.\n");
+ if (ret < 0)
return ret;
- }
dst = pkt->data;
bytestream2_init_writer(&pb, dst, pkt->size);
- av_fast_malloc(&c->slice_bits, &c->slice_bits_size,
- width * height + AV_INPUT_BUFFER_PADDING_SIZE);
+ av_fast_padded_malloc(&c->slice_bits, &c->slice_bits_size, width * height + 4);
if (!c->slice_bits) {
av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer 2.\n");
@@ -573,7 +582,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
case AV_PIX_FMT_RGBA:
for (i = 0; i < c->planes; i++) {
ret = encode_plane(avctx, c->slice_buffer[i] + 2 * c->slice_stride,
- c->slice_buffer[i], c->slice_stride,
+ c->slice_buffer[i], c->slice_stride, i,
width, height, &pb);
if (ret) {
@@ -582,10 +591,21 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
}
}
break;
+ case AV_PIX_FMT_YUV444P:
+ for (i = 0; i < c->planes; i++) {
+ ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0],
+ pic->linesize[i], i, width, height, &pb);
+
+ if (ret) {
+ av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i);
+ return ret;
+ }
+ }
+ break;
case AV_PIX_FMT_YUV422P:
for (i = 0; i < c->planes; i++) {
ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0],
- pic->linesize[i], width >> !!i, height, &pb);
+ pic->linesize[i], i, width >> !!i, height, &pb);
if (ret) {
av_log(avctx, AV_LOG_ERROR, "Error encoding plane %d.\n", i);
@@ -596,7 +616,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
case AV_PIX_FMT_YUV420P:
for (i = 0; i < c->planes; i++) {
ret = encode_plane(avctx, pic->data[i], c->slice_buffer[0],
- pic->linesize[i], width >> !!i, height >> !!i,
+ pic->linesize[i], i, width >> !!i, height >> !!i,
&pb);
if (ret) {
@@ -668,8 +688,9 @@ AVCodec ff_utvideo_encoder = {
.init = utvideo_encode_init,
.encode2 = utvideo_encode_frame,
.close = utvideo_encode_close,
+ .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_INTRA_ONLY,
.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_YUV422P,
- AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE
},
};