pegasus "pseudo yuv" (=RCT) lossless decoding support
bigendian fix?

Originally committed as revision 1963 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Michael Niedermayer 2003-06-16 13:19:30 +00:00
parent 1433e6c499
commit 63efe9a7e6

View File

@ -281,19 +281,16 @@ void mjpeg_close(MpegEncContext *s)
av_free(s->mjpeg_ctx); av_free(s->mjpeg_ctx);
} }
static inline int predict(uint8_t *ptr, int stride, int predictor, int size){ #define PREDICT(ret, topleft, top, left, predictor)\
switch(predictor){ switch(predictor){\
case 0: return ptr[0]; case 1: ret= left; break;\
case 1: return ptr[-size]; case 2: ret= top; break;\
case 2: return ptr[-stride]; case 3: ret= topleft; break;\
case 3: return ptr[-stride-size]; case 4: ret= left + top - topleft; break;\
case 4: return ptr[-size] + ptr[-stride] - ptr[-stride-size]; case 5: ret= left + ((top - topleft)>>1); break;\
case 5: return ptr[-size] + ((ptr[-stride] - ptr[-stride-size])>>1); case 6: ret= top + ((left - topleft)>>1); break;\
case 6: return ptr[-stride] + ((ptr[-size] - ptr[-stride-size])>>1); case 7: ret= (left + top)>>1; break;\
case 7: return (ptr[-size] + ptr[-stride])>>1;
default: return 0xFFFF;
} }
}
static inline void put_marker(PutBitContext *p, int code) static inline void put_marker(PutBitContext *p, int code)
{ {
@ -671,6 +668,8 @@ typedef struct MJpegDecodeContext {
int bottom_field; /* true if bottom field */ int bottom_field; /* true if bottom field */
int lossless; int lossless;
int rgb; int rgb;
int rct; /* pegasus reversible colorspace transform */
int bits; /* bits per component */
int width, height; int width, height;
int nb_components; int nb_components;
@ -834,7 +833,10 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
/* XXX: verify len field validity */ /* XXX: verify len field validity */
len = get_bits(&s->gb, 16); len = get_bits(&s->gb, 16);
if (get_bits(&s->gb, 8) != 8){ s->bits= get_bits(&s->gb, 8);
if(s->rct) s->bits=9;
if (s->bits != 8 && !s->lossless){
printf("only 8 bits/component accepted\n"); printf("only 8 bits/component accepted\n");
return -1; return -1;
} }
@ -865,6 +867,8 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
dprintf("component %d %d:%d id: %d quant:%d\n", i, s->h_count[i], dprintf("component %d %d:%d id: %d quant:%d\n", i, s->h_count[i],
s->v_count[i], s->component_id[i], s->quant_index[i]); s->v_count[i], s->component_id[i], s->quant_index[i]);
} }
if(s->v_max==1 && s->h_max==1 && s->lossless==1) s->rgb=1;
/* if different size, realloc/alloc picture */ /* if different size, realloc/alloc picture */
/* XXX: also check h_count and v_count */ /* XXX: also check h_count and v_count */
@ -882,7 +886,6 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
s->bottom_field = 0; s->bottom_field = 0;
} }
assert(s->rgb==0 || (s->h_max==1 && s->v_max==1));
if(s->rgb){ if(s->rgb){
int w, h; int w, h;
w = s->width; w = s->width;
@ -1033,6 +1036,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
} }
comp_index[i] = index; comp_index[i] = index;
nb_blocks[i] = s->h_count[index] * s->v_count[index]; nb_blocks[i] = s->h_count[index] * s->v_count[index];
h_count[i] = s->h_count[index]; h_count[i] = s->h_count[index];
v_count[i] = s->v_count[index]; v_count[i] = s->v_count[index];
@ -1060,6 +1064,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
break; break;
} }
} }
predictor= get_bits(&s->gb, 8); /* lossless predictor or start of spectral (Ss) */ predictor= get_bits(&s->gb, 8); /* lossless predictor or start of spectral (Ss) */
skip_bits(&s->gb, 8); /* Se */ skip_bits(&s->gb, 8); /* Se */
skip_bits(&s->gb, 4); /* Ah */ skip_bits(&s->gb, 4); /* Ah */
@ -1082,56 +1087,64 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
v_count[0] = 1; v_count[0] = 1;
} }
if(s->avctx->debug & FF_DEBUG_PICT_INFO)
printf("%s %s p:%d >>:%d\n", s->lossless ? "lossless" : "sequencial DCT", s->rgb ? "RGB" : "", predictor, point_transform);
if(s->lossless){ if(s->lossless){
if(s->rgb){ //FIXME cleanup if(s->rgb){
uint16_t buffer[2048][4];
int left[3], top[3], topleft[3];
const int linesize= s->linesize[0]; const int linesize= s->linesize[0];
const int mask= (1<<s->bits)-1;
for(i=0; i<3; i++){
buffer[0][i]= 1 << (s->bits + point_transform - 1);
}
for(mb_y = 0; mb_y < mb_height; mb_y++) { for(mb_y = 0; mb_y < mb_height; mb_y++) {
const int modified_predictor= mb_y ? 1 : predictor;
uint8_t *ptr = s->current_picture[0] + (linesize * mb_y);
if (s->interlaced && s->bottom_field)
ptr += linesize >> 1;
for(i=0; i<3; i++){
top[i]= left[i]= topleft[i]= buffer[0][i];
}
for(mb_x = 0; mb_x < mb_width; mb_x++) { for(mb_x = 0; mb_x < mb_width; mb_x++) {
if (s->restart_interval && !s->restart_count) if (s->restart_interval && !s->restart_count)
s->restart_count = s->restart_interval; s->restart_count = s->restart_interval;
if(mb_x==0 || mb_y==0 || s->interlaced || 1){ for(i=0;i<3;i++) {
for(i=0;i<3;i++) { int pred;
uint8_t *ptr;
int c, pred;
c = comp_index[i];
ptr = s->current_picture[0] + (linesize * mb_y) + 4*mb_x + c; //FIXME optimize this crap PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
if(mb_y==0){
if(mb_x==0){ topleft[i]= top[i];
pred= 128 << point_transform; top[i]= buffer[mb_x][i];
}else{
pred= ptr[-4]; left[i]=
} buffer[mb_x][i]= mask & (pred + (mjpeg_decode_dc(s, dc_index[i]) << point_transform));
}else{
if(mb_x==0){
pred= ptr[-linesize];
}else{
pred= predict(ptr, linesize, predictor, 4);
}
}
if (s->interlaced && s->bottom_field)
ptr += linesize >> 1;
*ptr= pred + (mjpeg_decode_dc(s, dc_index[i]) << point_transform);
}
}else{
for(i=0;i<3;i++) {
uint8_t *ptr;
int c, pred;
c = comp_index[i];
ptr = s->current_picture[0] + (linesize * mb_y) + 4*mb_x + c; //FIXME optimize this crap
pred= predict(ptr, linesize, predictor, 4);
*ptr= pred + (mjpeg_decode_dc(s, dc_index[i]) << point_transform);
}
} }
/* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */
if (s->restart_interval && (s->restart_interval < 1350) && if (s->restart_interval && !--s->restart_count) {
!--s->restart_count) {
align_get_bits(&s->gb); align_get_bits(&s->gb);
skip_bits(&s->gb, 16); /* skip RSTn */ skip_bits(&s->gb, 16); /* skip RSTn */
} }
} }
if(s->rct){
for(mb_x = 0; mb_x < mb_width; mb_x++) {
ptr[4*mb_x+1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2])>>2);
ptr[4*mb_x+0] = buffer[mb_x][1] + ptr[4*mb_x+1];
ptr[4*mb_x+2] = buffer[mb_x][2] + ptr[4*mb_x+1];
}
}else{
for(mb_x = 0; mb_x < mb_width; mb_x++) {
ptr[4*mb_x+0] = buffer[mb_x][0];
ptr[4*mb_x+1] = buffer[mb_x][1];
ptr[4*mb_x+2] = buffer[mb_x][2];
}
}
} }
}else{ }else{
for(mb_y = 0; mb_y < mb_height; mb_y++) { for(mb_y = 0; mb_y < mb_height; mb_y++) {
@ -1139,7 +1152,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
if (s->restart_interval && !s->restart_count) if (s->restart_interval && !s->restart_count)
s->restart_count = s->restart_interval; s->restart_count = s->restart_interval;
if(mb_x==0 || mb_y==0 || s->interlaced || 1){ if(mb_x==0 || mb_y==0 || s->interlaced){
for(i=0;i<nb_components;i++) { for(i=0;i<nb_components;i++) {
uint8_t *ptr; uint8_t *ptr;
int x, y, c, linesize; int x, y, c, linesize;
@ -1165,7 +1178,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
if(x==0 && mb_x==0){ if(x==0 && mb_x==0){
pred= ptr[-linesize]; pred= ptr[-linesize];
}else{ }else{
pred= predict(ptr, linesize, predictor, 1); PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
} }
} }
@ -1195,7 +1208,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
int pred; int pred;
ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
pred= predict(ptr, linesize, predictor, 1); PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
*ptr= pred + (mjpeg_decode_dc(s, dc_index[i]) << point_transform); *ptr= pred + (mjpeg_decode_dc(s, dc_index[i]) << point_transform);
if (++x == h) { if (++x == h) {
x = 0; x = 0;
@ -1204,9 +1217,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
} }
} }
} }
/* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */ if (s->restart_interval && !--s->restart_count) {
if (s->restart_interval && (s->restart_interval < 1350) &&
!--s->restart_count) {
align_get_bits(&s->gb); align_get_bits(&s->gb);
skip_bits(&s->gb, 16); /* skip RSTn */ skip_bits(&s->gb, 16); /* skip RSTn */
} }
@ -1293,6 +1304,10 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
id = be2me_32(id); id = be2me_32(id);
len -= 6; len -= 6;
if(s->avctx->debug & FF_DEBUG_STARTCODE){
printf("APPx %8X\n", id);
}
/* buggy AVID, it puts EOI only at every 10th frame */ /* buggy AVID, it puts EOI only at every 10th frame */
/* also this fourcc is used by non-avid files too, it holds some /* also this fourcc is used by non-avid files too, it holds some
informations, but it's always present in AVID creates files */ informations, but it's always present in AVID creates files */
@ -1374,6 +1389,29 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
len -= 7; len -= 7;
goto out; goto out;
} }
if (id == ff_get_fourcc("LJIF")){
printf("Pegasus lossless jpeg header found\n");
int i;
skip_bits(&s->gb, 16); /* version ? */
skip_bits(&s->gb, 16); /* unknwon always 0? */
skip_bits(&s->gb, 16); /* unknwon always 0? */
skip_bits(&s->gb, 16); /* unknwon always 0? */
switch( get_bits(&s->gb, 8)){
case 1:
s->rgb= 1;
s->rct=0;
break;
case 2:
s->rgb= 1;
s->rct=1;
break;
default:
printf("unknown colorspace\n");
}
len -= 9;
goto out;
}
/* Apple MJPEG-A */ /* Apple MJPEG-A */
if ((s->start_code == APP1) && (len > (0x28 - 8))) if ((s->start_code == APP1) && (len > (0x28 - 8)))
@ -1563,6 +1601,9 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
init_get_bits(&s->gb, buf_ptr, (buf_end - buf_ptr)*8); init_get_bits(&s->gb, buf_ptr, (buf_end - buf_ptr)*8);
s->start_code = start_code; s->start_code = start_code;
if(s->avctx->debug & FF_DEBUG_STARTCODE){
printf("startcode: %X\n", start_code);
}
/* process markers */ /* process markers */
if (start_code >= 0xd0 && start_code <= 0xd7) { if (start_code >= 0xd0 && start_code <= 0xd7) {
@ -1589,13 +1630,11 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
break; break;
case SOF0: case SOF0:
s->lossless=0; s->lossless=0;
s->rgb=0;
if (mjpeg_decode_sof(s) < 0) if (mjpeg_decode_sof(s) < 0)
return -1; return -1;
break; break;
case SOF3: case SOF3:
s->lossless=1; s->lossless=1;
s->rgb=1; //FIXME
if (mjpeg_decode_sof(s) < 0) if (mjpeg_decode_sof(s) < 0)
return -1; return -1;
break; break;
@ -1622,7 +1661,11 @@ eoi_parser:
switch((s->h_count[0] << 4) | s->v_count[0]) { switch((s->h_count[0] << 4) | s->v_count[0]) {
case 0x11: case 0x11:
if(s->rgb){ if(s->rgb){
#ifdef WORDS_BIGENDIAN
avctx->pix_fmt = PIX_FMT_ABGR32;
#else
avctx->pix_fmt = PIX_FMT_RGBA32; avctx->pix_fmt = PIX_FMT_RGBA32;
#endif
}else }else
avctx->pix_fmt = PIX_FMT_YUV444P; avctx->pix_fmt = PIX_FMT_YUV444P;
break; break;