avcodec/huffyuv: Support more 8bit YUV formats
Reviewed-by: Paul B Mahol <onemda@gmail.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
67999d3d12
commit
27b1e63f32
@ -67,6 +67,12 @@ typedef struct HYuvContext {
|
|||||||
int version;
|
int version;
|
||||||
int yuy2; //use yuy2 instead of 422P
|
int yuy2; //use yuy2 instead of 422P
|
||||||
int bgr32; //use bgr32 instead of bgr24
|
int bgr32; //use bgr32 instead of bgr24
|
||||||
|
int bps;
|
||||||
|
int alpha;
|
||||||
|
int chroma;
|
||||||
|
int yuv;
|
||||||
|
int chroma_h_shift;
|
||||||
|
int chroma_v_shift;
|
||||||
int width, height;
|
int width, height;
|
||||||
int flags;
|
int flags;
|
||||||
int context;
|
int context;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "get_bits.h"
|
#include "get_bits.h"
|
||||||
#include "huffyuv.h"
|
#include "huffyuv.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
#include "libavutil/pixdesc.h"
|
||||||
|
|
||||||
#define classic_shift_luma_table_size 42
|
#define classic_shift_luma_table_size 42
|
||||||
static const unsigned char classic_shift_luma[classic_shift_luma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = {
|
static const unsigned char classic_shift_luma[classic_shift_luma_table_size + FF_INPUT_BUFFER_PADDING_SIZE] = {
|
||||||
@ -264,12 +265,16 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
|||||||
if ((avctx->bits_per_coded_sample & 7) &&
|
if ((avctx->bits_per_coded_sample & 7) &&
|
||||||
avctx->bits_per_coded_sample != 12)
|
avctx->bits_per_coded_sample != 12)
|
||||||
s->version = 1; // do such files exist at all?
|
s->version = 1; // do such files exist at all?
|
||||||
else
|
else if (avctx->extradata_size > 3 && avctx->extradata[3] == 0)
|
||||||
s->version = 2;
|
s->version = 2;
|
||||||
|
else
|
||||||
|
s->version = 3;
|
||||||
} else
|
} else
|
||||||
s->version = 0;
|
s->version = 0;
|
||||||
|
|
||||||
if (s->version == 2) {
|
s->bps = 8;
|
||||||
|
s->chroma = 1;
|
||||||
|
if (s->version >= 2) {
|
||||||
int method, interlace;
|
int method, interlace;
|
||||||
|
|
||||||
if (avctx->extradata_size < 4)
|
if (avctx->extradata_size < 4)
|
||||||
@ -278,9 +283,18 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
|||||||
method = ((uint8_t*)avctx->extradata)[0];
|
method = ((uint8_t*)avctx->extradata)[0];
|
||||||
s->decorrelate = method & 64 ? 1 : 0;
|
s->decorrelate = method & 64 ? 1 : 0;
|
||||||
s->predictor = method & 63;
|
s->predictor = method & 63;
|
||||||
s->bitstream_bpp = ((uint8_t*)avctx->extradata)[1];
|
if (s->version == 2) {
|
||||||
if (s->bitstream_bpp == 0)
|
s->bitstream_bpp = ((uint8_t*)avctx->extradata)[1];
|
||||||
s->bitstream_bpp = avctx->bits_per_coded_sample & ~7;
|
if (s->bitstream_bpp == 0)
|
||||||
|
s->bitstream_bpp = avctx->bits_per_coded_sample & ~7;
|
||||||
|
} else {
|
||||||
|
s->bps = (avctx->extradata[1] >> 4) + 1;
|
||||||
|
s->chroma_h_shift = avctx->extradata[1] & 3;
|
||||||
|
s->chroma_v_shift = (avctx->extradata[1] >> 2) & 3;
|
||||||
|
s->yuv = !!(((uint8_t*)avctx->extradata)[2] & 1);
|
||||||
|
s->chroma= !!(((uint8_t*)avctx->extradata)[2] & 3);
|
||||||
|
s->alpha = !!(((uint8_t*)avctx->extradata)[2] & 4);
|
||||||
|
}
|
||||||
interlace = (((uint8_t*)avctx->extradata)[2] & 0x30) >> 4;
|
interlace = (((uint8_t*)avctx->extradata)[2] & 0x30) >> 4;
|
||||||
s->interlaced = (interlace == 1) ? 1 : (interlace == 2) ? 0 : s->interlaced;
|
s->interlaced = (interlace == 1) ? 1 : (interlace == 2) ? 0 : s->interlaced;
|
||||||
s->context = ((uint8_t*)avctx->extradata)[2] & 0x40 ? 1 : 0;
|
s->context = ((uint8_t*)avctx->extradata)[2] & 0x40 ? 1 : 0;
|
||||||
@ -318,29 +332,59 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (s->bitstream_bpp) {
|
if (s->version <= 2) {
|
||||||
case 12:
|
switch (s->bitstream_bpp) {
|
||||||
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
case 12:
|
||||||
break;
|
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||||
case 16:
|
s->yuv = 1;
|
||||||
if (s->yuy2) {
|
break;
|
||||||
avctx->pix_fmt = AV_PIX_FMT_YUYV422;
|
case 16:
|
||||||
} else {
|
if (s->yuy2) {
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUYV422;
|
||||||
|
} else {
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUV422P;
|
||||||
|
}
|
||||||
|
s->yuv = 1;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
case 32:
|
||||||
|
if (s->bgr32) {
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_RGB32;
|
||||||
|
s->alpha = 1;
|
||||||
|
} else {
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_BGR24;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt,
|
||||||
|
&s->chroma_h_shift,
|
||||||
|
&s->chroma_v_shift);
|
||||||
|
} else {
|
||||||
|
switch ( (s->chroma<<10) | (s->yuv<<9) | (s->alpha<<8) | ((s->bps-1)<<4) | s->chroma_h_shift | (s->chroma_v_shift<<2)) {
|
||||||
|
case 0x670:
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUV444P;
|
||||||
|
break;
|
||||||
|
case 0x671:
|
||||||
avctx->pix_fmt = AV_PIX_FMT_YUV422P;
|
avctx->pix_fmt = AV_PIX_FMT_YUV422P;
|
||||||
|
break;
|
||||||
|
case 0x672:
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUV411P;
|
||||||
|
break;
|
||||||
|
case 0x674:
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUV440P;
|
||||||
|
break;
|
||||||
|
case 0x675:
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||||
|
break;
|
||||||
|
case 0x67A:
|
||||||
|
avctx->pix_fmt = AV_PIX_FMT_YUV410P;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
case 32:
|
|
||||||
if (s->bgr32) {
|
|
||||||
avctx->pix_fmt = AV_PIX_FMT_RGB32;
|
|
||||||
} else {
|
|
||||||
avctx->pix_fmt = AV_PIX_FMT_BGR24;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return AVERROR_INVALIDDATA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P || avctx->pix_fmt == AV_PIX_FMT_YUV420P) && avctx->width & 1) {
|
if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P || avctx->pix_fmt == AV_PIX_FMT_YUV420P) && avctx->width & 1) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "width must be even for this colorspace\n");
|
av_log(avctx, AV_LOG_ERROR, "width must be even for this colorspace\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
@ -370,7 +414,7 @@ static av_cold int decode_init_thread_copy(AVCodecContext *avctx)
|
|||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
s->vlc[i].table = NULL;
|
s->vlc[i].table = NULL;
|
||||||
|
|
||||||
if (s->version == 2) {
|
if (s->version >= 2) {
|
||||||
if (read_huffman_tables(s, ((uint8_t*)avctx->extradata) + 4,
|
if (read_huffman_tables(s, ((uint8_t*)avctx->extradata) + 4,
|
||||||
avctx->extradata_size) < 0)
|
avctx->extradata_size) < 0)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
@ -417,6 +461,25 @@ static void decode_422_bitstream(HYuvContext *s, int count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void decode_plane_bitstream(HYuvContext *s, int count, int plane)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
count/=2;
|
||||||
|
|
||||||
|
if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
|
||||||
|
for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
|
||||||
|
s->temp[0][2*i ] = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);
|
||||||
|
s->temp[0][2*i + 1] = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(i=0; i<count; i++){
|
||||||
|
s->temp[0][2*i ] = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);
|
||||||
|
s->temp[0][2*i + 1] = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void decode_gray_bitstream(HYuvContext *s, int count)
|
static void decode_gray_bitstream(HYuvContext *s, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -546,7 +609,72 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
|
|||||||
|
|
||||||
s->last_slice_end = 0;
|
s->last_slice_end = 0;
|
||||||
|
|
||||||
if (s->bitstream_bpp < 24) {
|
if (s->version > 2) {
|
||||||
|
int plane;
|
||||||
|
for(plane = 0; plane < 1 + 2*s->chroma + s->alpha; plane++) {
|
||||||
|
int left, lefttop, y;
|
||||||
|
int w = width;
|
||||||
|
int h = height;
|
||||||
|
int fake_stride = fake_ystride;
|
||||||
|
|
||||||
|
if (s->chroma && (plane == 1 || plane == 2)) {
|
||||||
|
w >>= s->chroma_h_shift;
|
||||||
|
h >>= s->chroma_v_shift;
|
||||||
|
fake_stride = plane == 1 ? fake_ustride : fake_vstride;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (s->predictor) {
|
||||||
|
case LEFT:
|
||||||
|
case PLANE:
|
||||||
|
decode_plane_bitstream(s, w, plane);
|
||||||
|
left = s->dsp.add_hfyu_left_prediction(p->data[plane], s->temp[0], w, 0);
|
||||||
|
|
||||||
|
for (y = 1; y < h; y++) {
|
||||||
|
uint8_t *dst = p->data[plane] + p->linesize[plane]*y;
|
||||||
|
|
||||||
|
decode_plane_bitstream(s, w, plane);
|
||||||
|
left = s->dsp.add_hfyu_left_prediction(dst, s->temp[0], w, left);
|
||||||
|
if (s->predictor == PLANE) {
|
||||||
|
if (y > s->interlaced) {
|
||||||
|
s->dsp.add_bytes(dst, dst - fake_stride, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MEDIAN:
|
||||||
|
decode_plane_bitstream(s, w, plane);
|
||||||
|
left= s->dsp.add_hfyu_left_prediction(p->data[plane], s->temp[0], w, 0);
|
||||||
|
|
||||||
|
y = 1;
|
||||||
|
|
||||||
|
/* second line is left predicted for interlaced case */
|
||||||
|
if (s->interlaced) {
|
||||||
|
decode_plane_bitstream(s, w, plane);
|
||||||
|
left = s->dsp.add_hfyu_left_prediction(p->data[plane] + p->linesize[plane], s->temp[0], w, left);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lefttop = p->data[plane][0];
|
||||||
|
decode_plane_bitstream(s, w, plane);
|
||||||
|
s->dsp.add_hfyu_median_prediction(p->data[plane] + fake_stride, p->data[plane], s->temp[0], w, &left, &lefttop);
|
||||||
|
y++;
|
||||||
|
|
||||||
|
for (; y<h; y++) {
|
||||||
|
uint8_t *dst;
|
||||||
|
|
||||||
|
decode_plane_bitstream(s, w, plane);
|
||||||
|
|
||||||
|
dst = p->data[plane] + p->linesize[plane] * y;
|
||||||
|
|
||||||
|
s->dsp.add_hfyu_median_prediction(dst, dst - fake_stride, s->temp[0], w, &left, &lefttop);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_slice(s, p, height);
|
||||||
|
} else if (s->bitstream_bpp < 24) {
|
||||||
int y, cy;
|
int y, cy;
|
||||||
int lefty, leftu, leftv;
|
int lefty, leftu, leftv;
|
||||||
int lefttopy, lefttopu, lefttopv;
|
int lefttopy, lefttopu, lefttopv;
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "huffman.h"
|
#include "huffman.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "put_bits.h"
|
#include "put_bits.h"
|
||||||
|
#include "libavutil/pixdesc.h"
|
||||||
|
|
||||||
static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst,
|
static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst,
|
||||||
const uint8_t *src, int w, int left)
|
const uint8_t *src, int w, int left)
|
||||||
@ -145,6 +146,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
|||||||
{
|
{
|
||||||
HYuvContext *s = avctx->priv_data;
|
HYuvContext *s = avctx->priv_data;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
|
||||||
|
|
||||||
ff_huffyuv_common_init(avctx);
|
ff_huffyuv_common_init(avctx);
|
||||||
|
|
||||||
@ -163,6 +165,14 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
|||||||
avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
|
avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
|
||||||
avctx->coded_frame->key_frame = 1;
|
avctx->coded_frame->key_frame = 1;
|
||||||
|
|
||||||
|
s->bps = 8;
|
||||||
|
s->yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && desc->nb_components >= 2;
|
||||||
|
s->chroma = desc->nb_components > 2;
|
||||||
|
s->alpha = !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA);
|
||||||
|
av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt,
|
||||||
|
&s->chroma_h_shift,
|
||||||
|
&s->chroma_v_shift);
|
||||||
|
|
||||||
switch (avctx->pix_fmt) {
|
switch (avctx->pix_fmt) {
|
||||||
case AV_PIX_FMT_YUV420P:
|
case AV_PIX_FMT_YUV420P:
|
||||||
case AV_PIX_FMT_YUV422P:
|
case AV_PIX_FMT_YUV422P:
|
||||||
@ -172,6 +182,12 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
|||||||
}
|
}
|
||||||
s->bitstream_bpp = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 12 : 16;
|
s->bitstream_bpp = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 12 : 16;
|
||||||
break;
|
break;
|
||||||
|
case AV_PIX_FMT_YUV444P:
|
||||||
|
case AV_PIX_FMT_YUV410P:
|
||||||
|
case AV_PIX_FMT_YUV411P:
|
||||||
|
case AV_PIX_FMT_YUV440P:
|
||||||
|
s->version = 3;
|
||||||
|
break;
|
||||||
case AV_PIX_FMT_RGB32:
|
case AV_PIX_FMT_RGB32:
|
||||||
s->bitstream_bpp = 32;
|
s->bitstream_bpp = 32;
|
||||||
break;
|
break;
|
||||||
@ -182,8 +198,9 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
|||||||
av_log(avctx, AV_LOG_ERROR, "format not supported\n");
|
av_log(avctx, AV_LOG_ERROR, "format not supported\n");
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
avctx->bits_per_coded_sample = s->bitstream_bpp;
|
avctx->bits_per_coded_sample = s->bitstream_bpp;
|
||||||
s->decorrelate = s->bitstream_bpp >= 24;
|
s->decorrelate = s->bitstream_bpp >= 24 && !s->yuv;
|
||||||
s->predictor = avctx->prediction_method;
|
s->predictor = avctx->prediction_method;
|
||||||
s->interlaced = avctx->flags&CODEC_FLAG_INTERLACED_ME ? 1 : 0;
|
s->interlaced = avctx->flags&CODEC_FLAG_INTERLACED_ME ? 1 : 0;
|
||||||
if (avctx->context_model == 1) {
|
if (avctx->context_model == 1) {
|
||||||
@ -209,11 +226,23 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
|||||||
"by huffyuv; use vcodec=ffvhuff\n");
|
"by huffyuv; use vcodec=ffvhuff\n");
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
if (s->version > 2) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
|
"Error: ver>2 is not supported "
|
||||||
|
"by huffyuv; use vcodec=ffvhuff\n");
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
if (s->interlaced != ( s->height > 288 ))
|
if (s->interlaced != ( s->height > 288 ))
|
||||||
av_log(avctx, AV_LOG_INFO,
|
av_log(avctx, AV_LOG_INFO,
|
||||||
"using huffyuv 2.2.0 or newer interlacing flag\n");
|
"using huffyuv 2.2.0 or newer interlacing flag\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->version > 2 && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR, "Ver > 2 is under development, files encoded with it may not be decodable with future versions!!!\n"
|
||||||
|
"Use vstrict=-2 / -strict -2 to use it anyway.\n");
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (s->bitstream_bpp >= 24 && s->predictor == MEDIAN) {
|
if (s->bitstream_bpp >= 24 && s->predictor == MEDIAN) {
|
||||||
av_log(avctx, AV_LOG_ERROR,
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
"Error: RGB is incompatible with median predictor\n");
|
"Error: RGB is incompatible with median predictor\n");
|
||||||
@ -221,11 +250,20 @@ static av_cold int encode_init(AVCodecContext *avctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
((uint8_t*)avctx->extradata)[0] = s->predictor | (s->decorrelate << 6);
|
((uint8_t*)avctx->extradata)[0] = s->predictor | (s->decorrelate << 6);
|
||||||
((uint8_t*)avctx->extradata)[1] = s->bitstream_bpp;
|
|
||||||
((uint8_t*)avctx->extradata)[2] = s->interlaced ? 0x10 : 0x20;
|
((uint8_t*)avctx->extradata)[2] = s->interlaced ? 0x10 : 0x20;
|
||||||
if (s->context)
|
if (s->context)
|
||||||
((uint8_t*)avctx->extradata)[2] |= 0x40;
|
((uint8_t*)avctx->extradata)[2] |= 0x40;
|
||||||
((uint8_t*)avctx->extradata)[3] = 0;
|
if (s->version < 3) {
|
||||||
|
((uint8_t*)avctx->extradata)[1] = s->bitstream_bpp;
|
||||||
|
((uint8_t*)avctx->extradata)[3] = 0;
|
||||||
|
} else {
|
||||||
|
((uint8_t*)avctx->extradata)[1] = ((s->bps-1)<<4) | s->chroma_h_shift | (s->chroma_v_shift<<2);
|
||||||
|
if (s->chroma)
|
||||||
|
((uint8_t*)avctx->extradata)[2] |= s->yuv ? 1 : 2;
|
||||||
|
if (s->alpha)
|
||||||
|
((uint8_t*)avctx->extradata)[2] |= 4;
|
||||||
|
((uint8_t*)avctx->extradata)[3] = 1;
|
||||||
|
}
|
||||||
s->avctx->extradata_size = 4;
|
s->avctx->extradata_size = 4;
|
||||||
|
|
||||||
if (avctx->stats_in) {
|
if (avctx->stats_in) {
|
||||||
@ -345,6 +383,54 @@ static int encode_422_bitstream(HYuvContext *s, int offset, int count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < 4 * count) {
|
||||||
|
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOAD2\
|
||||||
|
int y0 = s->temp[0][2 * i];\
|
||||||
|
int y1 = s->temp[0][2 * i + 1];
|
||||||
|
#define STAT2\
|
||||||
|
s->stats[plane][y0]++;\
|
||||||
|
s->stats[plane][y1]++;
|
||||||
|
#define WRITE2\
|
||||||
|
put_bits(&s->pb, s->len[plane][y0], s->bits[plane][y0]);\
|
||||||
|
put_bits(&s->pb, s->len[plane][y1], s->bits[plane][y1]);
|
||||||
|
|
||||||
|
count /= 2;
|
||||||
|
|
||||||
|
if (s->flags & CODEC_FLAG_PASS1) {
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
LOAD2;
|
||||||
|
STAT2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (s->context) {
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
LOAD2;
|
||||||
|
STAT2;
|
||||||
|
WRITE2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
LOAD2;
|
||||||
|
WRITE2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef LOAD2
|
||||||
|
#undef STAT2
|
||||||
|
#undef WRITE2
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int encode_gray_bitstream(HYuvContext *s, int count)
|
static int encode_gray_bitstream(HYuvContext *s, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -634,6 +720,59 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
|||||||
}
|
}
|
||||||
encode_bgra_bitstream(s, width, 3);
|
encode_bgra_bitstream(s, width, 3);
|
||||||
}
|
}
|
||||||
|
} else if (s->yuv) {
|
||||||
|
int plane;
|
||||||
|
for (plane = 0; plane < 1 + 2*s->chroma + s->alpha; plane++) {
|
||||||
|
int left, y;
|
||||||
|
int w = width;
|
||||||
|
int h = height;
|
||||||
|
int fake_stride = fake_ystride;
|
||||||
|
|
||||||
|
if (s->chroma && (plane == 1 || plane == 2)) {
|
||||||
|
w >>= s->chroma_h_shift;
|
||||||
|
h >>= s->chroma_v_shift;
|
||||||
|
fake_stride = plane == 1 ? fake_ustride : fake_vstride;
|
||||||
|
}
|
||||||
|
|
||||||
|
left = sub_left_prediction(s, s->temp[0], p->data[plane], w , 0);
|
||||||
|
|
||||||
|
encode_plane_bitstream(s, w, plane);
|
||||||
|
|
||||||
|
if (s->predictor==MEDIAN) {
|
||||||
|
int lefttop;
|
||||||
|
y = 1;
|
||||||
|
if (s->interlaced) {
|
||||||
|
left = sub_left_prediction(s, s->temp[0], p->data[plane] + p->linesize[plane], w , left);
|
||||||
|
|
||||||
|
encode_plane_bitstream(s, w, plane);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lefttop = p->data[plane][0];
|
||||||
|
|
||||||
|
for (; y < h; y++) {
|
||||||
|
uint8_t *dst = p->data[plane] + p->linesize[plane] * y;
|
||||||
|
|
||||||
|
s->dsp.sub_hfyu_median_prediction(s->temp[0], dst - fake_stride, dst, w , &left, &lefttop);
|
||||||
|
|
||||||
|
encode_plane_bitstream(s, w, plane);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (y = 1; y < h; y++) {
|
||||||
|
uint8_t *dst = p->data[plane] + p->linesize[plane] * y;
|
||||||
|
|
||||||
|
if (s->predictor == PLANE && s->interlaced < y) {
|
||||||
|
s->dsp.diff_bytes(s->temp[1], dst, dst - fake_stride, w);
|
||||||
|
|
||||||
|
left = sub_left_prediction(s, s->temp[0], s->temp[1], w , left);
|
||||||
|
} else {
|
||||||
|
left = sub_left_prediction(s, s->temp[0], dst, w , left);
|
||||||
|
}
|
||||||
|
|
||||||
|
encode_plane_bitstream(s, w, plane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Format not supported!\n");
|
av_log(avctx, AV_LOG_ERROR, "Format not supported!\n");
|
||||||
}
|
}
|
||||||
@ -715,7 +854,9 @@ AVCodec ff_ffvhuff_encoder = {
|
|||||||
.encode2 = encode_frame,
|
.encode2 = encode_frame,
|
||||||
.close = encode_end,
|
.close = encode_end,
|
||||||
.pix_fmts = (const enum AVPixelFormat[]){
|
.pix_fmts = (const enum AVPixelFormat[]){
|
||||||
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24,
|
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV411P,
|
||||||
|
AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P,
|
||||||
|
AV_PIX_FMT_RGB24,
|
||||||
AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE
|
AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user