summaryrefslogtreecommitdiffstats
path: root/libavcodec/utvideoenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/utvideoenc.c')
-rw-r--r--libavcodec/utvideoenc.c142
1 files changed, 76 insertions, 66 deletions
diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c
index ef51ed0..db00e1e 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"
@@ -68,15 +67,16 @@ static av_cold int utvideo_encode_init(AVCodecContext *avctx)
c->slice_stride = FFALIGN(avctx->width, 32);
switch (avctx->pix_fmt) {
- case AV_PIX_FMT_RGB24:
+ case AV_PIX_FMT_GBRP:
c->planes = 3;
avctx->codec_tag = MKTAG('U', 'L', 'R', 'G');
original_format = UTVIDEO_RGB;
break;
- case AV_PIX_FMT_RGBA:
+ case AV_PIX_FMT_GBRAP:
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
@@ -235,55 +243,48 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
static void mangle_rgb_planes(uint8_t *dst[4], ptrdiff_t dst_stride,
- uint8_t *src, int step, ptrdiff_t stride,
+ uint8_t *const src[4], int planes, const int stride[4],
int width, int height)
{
int i, j;
int k = 2 * dst_stride;
+ const uint8_t *sg = src[0];
+ const uint8_t *sb = src[1];
+ const uint8_t *sr = src[2];
+ const uint8_t *sa = src[3];
unsigned int g;
for (j = 0; j < height; j++) {
- if (step == 3) {
- for (i = 0; i < width * step; i += step) {
- g = src[i + 1];
+ if (planes == 3) {
+ for (i = 0; i < width; i++) {
+ g = sg[i];
dst[0][k] = g;
g += 0x80;
- dst[1][k] = src[i + 2] - g;
- dst[2][k] = src[i + 0] - g;
+ dst[1][k] = sb[i] - g;
+ dst[2][k] = sr[i] - g;
k++;
}
} else {
- for (i = 0; i < width * step; i += step) {
- g = src[i + 1];
+ for (i = 0; i < width; i++) {
+ g = sg[i];
dst[0][k] = g;
g += 0x80;
- dst[1][k] = src[i + 2] - g;
- dst[2][k] = src[i + 0] - g;
- dst[3][k] = src[i + 3];
+ dst[1][k] = sb[i] - g;
+ dst[2][k] = sr[i] - g;
+ dst[3][k] = sa[i];
k++;
}
+ sa += stride[3];
}
k += dst_stride - width;
- src += stride;
+ sg += stride[0];
+ sb += stride[1];
+ sr += stride[2];
}
}
-/* Write data to a plane with left prediction */
-static void left_predict(uint8_t *src, uint8_t *dst, ptrdiff_t stride,
- int width, int height)
-{
- int i, j;
- uint8_t prev;
-
- prev = 0x80; /* Set the initial value */
- for (j = 0; j < height; j++) {
- for (i = 0; i < width; i++) {
- *dst++ = src[i] - prev;
- prev = src[i];
- }
- src += 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,
@@ -313,7 +314,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 +389,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 +399,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,15 +418,14 @@ 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;
- left_predict(src + sstart * stride, dst + sstart * width,
- stride, width, send - sstart);
+ send = height * (i + 1) / c->slices & cmask;
+ c->llvidencdsp.sub_left_predict(dst + sstart * width, src + sstart * stride, stride, width, send - sstart);
}
break;
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 +444,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 +468,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 +489,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 +543,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");
@@ -563,17 +561,17 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
}
/* In case of RGB, mangle the planes to Ut Video's format */
- if (avctx->pix_fmt == AV_PIX_FMT_RGBA || avctx->pix_fmt == AV_PIX_FMT_RGB24)
- mangle_rgb_planes(c->slice_buffer, c->slice_stride, pic->data[0],
- c->planes, pic->linesize[0], width, height);
+ if (avctx->pix_fmt == AV_PIX_FMT_GBRAP || avctx->pix_fmt == AV_PIX_FMT_GBRP)
+ mangle_rgb_planes(c->slice_buffer, c->slice_stride, pic->data,
+ c->planes, pic->linesize, width, height);
/* Deal with the planes */
switch (avctx->pix_fmt) {
- case AV_PIX_FMT_RGB24:
- case AV_PIX_FMT_RGBA:
+ case AV_PIX_FMT_GBRP:
+ case AV_PIX_FMT_GBRAP:
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 +580,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 +605,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 +677,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_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P,
+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE
},
};
OpenPOWER on IntegriCloud