📄 huffyuv.c
字号:
for(i=0; i<count; i++){
READ_2PIX(s->temp[0][2*i ], s->temp[1][i], 1);
READ_2PIX(s->temp[0][2*i+1], s->temp[2][i], 2);
}
}
static void decode_gray_bitstream(HYuvContext *s, int count){
int i;
count/=2;
for(i=0; i<count; i++){
READ_2PIX(s->temp[0][2*i ], s->temp[0][2*i+1], 0);
}
}
#ifdef CONFIG_ENCODERS
static int encode_422_bitstream(HYuvContext *s, int count){
int i;
if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 2*4*count){
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return -1;
}
#define LOAD4\
int y0 = s->temp[0][2*i];\
int y1 = s->temp[0][2*i+1];\
int u0 = s->temp[1][i];\
int v0 = s->temp[2][i];
count/=2;
if(s->flags&CODEC_FLAG_PASS1){
for(i=0; i<count; i++){
LOAD4;
s->stats[0][y0]++;
s->stats[1][u0]++;
s->stats[0][y1]++;
s->stats[2][v0]++;
}
}
if(s->avctx->flags2&CODEC_FLAG2_NO_OUTPUT)
return 0;
if(s->context){
for(i=0; i<count; i++){
LOAD4;
s->stats[0][y0]++;
put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);
s->stats[1][u0]++;
put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]);
s->stats[0][y1]++;
put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
s->stats[2][v0]++;
put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]);
}
}else{
for(i=0; i<count; i++){
LOAD4;
put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);
put_bits(&s->pb, s->len[1][u0], s->bits[1][u0]);
put_bits(&s->pb, s->len[0][y1], s->bits[0][y1]);
put_bits(&s->pb, s->len[2][v0], s->bits[2][v0]);
}
}
return 0;
}
static int encode_gray_bitstream(HYuvContext *s, int count){
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[0][y0]++;\
s->stats[0][y1]++;
#define WRITE2\
put_bits(&s->pb, s->len[0][y0], s->bits[0][y0]);\
put_bits(&s->pb, s->len[0][y1], s->bits[0][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;
}
}
return 0;
}
#endif /* CONFIG_ENCODERS */
static av_always_inline void decode_bgr_1(HYuvContext *s, int count, int decorrelate, int alpha){
int i;
for(i=0; i<count; i++){
int code = get_vlc2(&s->gb, s->vlc[3].table, VLC_BITS, 1);
if(code != -1){
*(uint32_t*)&s->temp[0][4*i] = s->pix_bgr_map[code];
}else if(decorrelate){
s->temp[0][4*i+G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3);
s->temp[0][4*i+B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3) + s->temp[0][4*i+G];
s->temp[0][4*i+R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3) + s->temp[0][4*i+G];
}else{
s->temp[0][4*i+B] = get_vlc2(&s->gb, s->vlc[0].table, VLC_BITS, 3);
s->temp[0][4*i+G] = get_vlc2(&s->gb, s->vlc[1].table, VLC_BITS, 3);
s->temp[0][4*i+R] = get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3);
}
if(alpha)
get_vlc2(&s->gb, s->vlc[2].table, VLC_BITS, 3); //?!
}
}
static void decode_bgr_bitstream(HYuvContext *s, int count){
if(s->decorrelate){
if(s->bitstream_bpp==24)
decode_bgr_1(s, count, 1, 0);
else
decode_bgr_1(s, count, 1, 1);
}else{
if(s->bitstream_bpp==24)
decode_bgr_1(s, count, 0, 0);
else
decode_bgr_1(s, count, 0, 1);
}
}
static int encode_bgr_bitstream(HYuvContext *s, int count){
int i;
if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 3*4*count){
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return -1;
}
#define LOAD3\
int g= s->temp[0][4*i+G];\
int b= (s->temp[0][4*i+B] - g) & 0xff;\
int r= (s->temp[0][4*i+R] - g) & 0xff;
#define STAT3\
s->stats[0][b]++;\
s->stats[1][g]++;\
s->stats[2][r]++;
#define WRITE3\
put_bits(&s->pb, s->len[1][g], s->bits[1][g]);\
put_bits(&s->pb, s->len[0][b], s->bits[0][b]);\
put_bits(&s->pb, s->len[2][r], s->bits[2][r]);
if((s->flags&CODEC_FLAG_PASS1) && (s->avctx->flags2&CODEC_FLAG2_NO_OUTPUT)){
for(i=0; i<count; i++){
LOAD3;
STAT3;
}
}else if(s->context || (s->flags&CODEC_FLAG_PASS1)){
for(i=0; i<count; i++){
LOAD3;
STAT3;
WRITE3;
}
}else{
for(i=0; i<count; i++){
LOAD3;
WRITE3;
}
}
return 0;
}
#ifdef CONFIG_DECODERS
static void draw_slice(HYuvContext *s, int y){
int h, cy;
int offset[4];
if(s->avctx->draw_horiz_band==NULL)
return;
h= y - s->last_slice_end;
y -= h;
if(s->bitstream_bpp==12){
cy= y>>1;
}else{
cy= y;
}
offset[0] = s->picture.linesize[0]*y;
offset[1] = s->picture.linesize[1]*cy;
offset[2] = s->picture.linesize[2]*cy;
offset[3] = 0;
emms_c();
s->avctx->draw_horiz_band(s->avctx, &s->picture, offset, y, 3, h);
s->last_slice_end= y + h;
}
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size){
HYuvContext *s = avctx->priv_data;
const int width= s->width;
const int width2= s->width>>1;
const int height= s->height;
int fake_ystride, fake_ustride, fake_vstride;
AVFrame * const p= &s->picture;
int table_size= 0;
AVFrame *picture = data;
s->bitstream_buffer= av_fast_realloc(s->bitstream_buffer, &s->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer, (uint32_t*)buf, buf_size/4);
if(p->data[0])
avctx->release_buffer(avctx, p);
p->reference= 0;
if(avctx->get_buffer(avctx, p) < 0){
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
if(s->context){
table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size);
if(table_size < 0)
return -1;
}
if((unsigned)(buf_size-table_size) >= INT_MAX/8)
return -1;
init_get_bits(&s->gb, s->bitstream_buffer+table_size, (buf_size-table_size)*8);
fake_ystride= s->interlaced ? p->linesize[0]*2 : p->linesize[0];
fake_ustride= s->interlaced ? p->linesize[1]*2 : p->linesize[1];
fake_vstride= s->interlaced ? p->linesize[2]*2 : p->linesize[2];
s->last_slice_end= 0;
if(s->bitstream_bpp<24){
int y, cy;
int lefty, leftu, leftv;
int lefttopy, lefttopu, lefttopv;
if(s->yuy2){
p->data[0][3]= get_bits(&s->gb, 8);
p->data[0][2]= get_bits(&s->gb, 8);
p->data[0][1]= get_bits(&s->gb, 8);
p->data[0][0]= get_bits(&s->gb, 8);
av_log(avctx, AV_LOG_ERROR, "YUY2 output is not implemented yet\n");
return -1;
}else{
leftv= p->data[2][0]= get_bits(&s->gb, 8);
lefty= p->data[0][1]= get_bits(&s->gb, 8);
leftu= p->data[1][0]= get_bits(&s->gb, 8);
p->data[0][0]= get_bits(&s->gb, 8);
switch(s->predictor){
case LEFT:
case PLANE:
decode_422_bitstream(s, width-2);
lefty= add_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty);
if(!(s->flags&CODEC_FLAG_GRAY)){
leftu= add_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu);
leftv= add_left_prediction(p->data[2] + 1, s->temp[2], width2-1, leftv);
}
for(cy=y=1; y<s->height; y++,cy++){
uint8_t *ydst, *udst, *vdst;
if(s->bitstream_bpp==12){
decode_gray_bitstream(s, width);
ydst= p->data[0] + p->linesize[0]*y;
lefty= add_left_prediction(ydst, s->temp[0], width, lefty);
if(s->predictor == PLANE){
if(y>s->interlaced)
s->dsp.add_bytes(ydst, ydst - fake_ystride, width);
}
y++;
if(y>=s->height) break;
}
draw_slice(s, y);
ydst= p->data[0] + p->linesize[0]*y;
udst= p->data[1] + p->linesize[1]*cy;
vdst= p->data[2] + p->linesize[2]*cy;
decode_422_bitstream(s, width);
lefty= add_left_prediction(ydst, s->temp[0], width, lefty);
if(!(s->flags&CODEC_FLAG_GRAY)){
leftu= add_left_prediction(udst, s->temp[1], width2, leftu);
leftv= add_left_prediction(vdst, s->temp[2], width2, leftv);
}
if(s->predictor == PLANE){
if(cy>s->interlaced){
s->dsp.add_bytes(ydst, ydst - fake_ystride, width);
if(!(s->flags&CODEC_FLAG_GRAY)){
s->dsp.add_bytes(udst, udst - fake_ustride, width2);
s->dsp.add_bytes(vdst, vdst - fake_vstride, width2);
}
}
}
}
draw_slice(s, height);
break;
case MEDIAN:
/* first line except first 2 pixels is left predicted */
decode_422_bitstream(s, width-2);
lefty= add_left_prediction(p->data[0] + 2, s->temp[0], width-2, lefty);
if(!(s->flags&CODEC_FLAG_GRAY)){
leftu= add_left_prediction(p->data[1] + 1, s->temp[1], width2-1, leftu);
leftv= add_left_prediction(p->data[2] + 1, s->temp[2], width2-1, leftv);
}
cy=y=1;
/* second line is left predicted for interlaced case */
if(s->interlaced){
decode_422_bitstream(s, width);
lefty= add_left_prediction(p->data[0] + p->linesize[0], s->temp[0], width, lefty);
if(!(s->flags&CODEC_FLAG_GRAY)){
leftu= add_left_prediction(p->data[1] + p->linesize[2], s->temp[1], width2, leftu);
leftv= add_left_prediction(p->data[2] + p->linesize[1], s->temp[2], width2, leftv);
}
y++; cy++;
}
/* next 4 pixels are left predicted too */
decode_422_bitstream(s, 4);
lefty= add_left_prediction(p->data[0] + fake_ystride, s->temp[0], 4, lefty);
if(!(s->flags&CODEC_FLAG_GRAY)){
leftu= add_left_prediction(p->data[1] + fake_ustride, s->temp[1], 2, leftu);
leftv= add_left_prediction(p->data[2] + fake_vstride, s->temp[2], 2, leftv);
}
/* next line except the first 4 pixels is median predicted */
lefttopy= p->data[0][3];
decode_422_bitstream(s, width-4);
add_median_prediction(p->data[0] + fake_ystride+4, p->data[0]+4, s->temp[0], width-4, &lefty, &lefttopy);
if(!(s->flags&CODEC_FLAG_GRAY)){
lefttopu= p->data[1][1];
lefttopv= p->data[2][1];
add_median_prediction(p->data[1] + fake_ustride+2, p->data[1]+2, s->temp[1], width2-2, &leftu, &lefttopu);
add_median_prediction(p->data[2] + fake_vstride+2, p->data[2]+2, s->temp[2], width2-2, &leftv, &lefttopv);
}
y++; cy++;
for(; y<height; y++,cy++){
uint8_t *ydst, *udst, *vdst;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -