diff options
Diffstat (limited to 'libavcodec/utvideoenc.c')
-rw-r--r-- | libavcodec/utvideoenc.c | 142 |
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 }, }; |