|
|
|
@ -281,19 +281,16 @@ void mjpeg_close(MpegEncContext *s) |
|
|
|
|
av_free(s->mjpeg_ctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline int predict(uint8_t *ptr, int stride, int predictor, int size){ |
|
|
|
|
switch(predictor){ |
|
|
|
|
case 0: return ptr[0]; |
|
|
|
|
case 1: return ptr[-size]; |
|
|
|
|
case 2: return ptr[-stride]; |
|
|
|
|
case 3: return ptr[-stride-size]; |
|
|
|
|
case 4: return ptr[-size] + ptr[-stride] - ptr[-stride-size]; |
|
|
|
|
case 5: return ptr[-size] + ((ptr[-stride] - ptr[-stride-size])>>1); |
|
|
|
|
case 6: return ptr[-stride] + ((ptr[-size] - ptr[-stride-size])>>1); |
|
|
|
|
case 7: return (ptr[-size] + ptr[-stride])>>1; |
|
|
|
|
default: return 0xFFFF; |
|
|
|
|
#define PREDICT(ret, topleft, top, left, predictor)\ |
|
|
|
|
switch(predictor){\
|
|
|
|
|
case 1: ret= left; break;\
|
|
|
|
|
case 2: ret= top; break;\
|
|
|
|
|
case 3: ret= topleft; break;\
|
|
|
|
|
case 4: ret= left + top - topleft; break;\
|
|
|
|
|
case 5: ret= left + ((top - topleft)>>1); break;\
|
|
|
|
|
case 6: ret= top + ((left - topleft)>>1); break;\
|
|
|
|
|
case 7: ret= (left + top)>>1; break;\
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static inline void put_marker(PutBitContext *p, int code) |
|
|
|
|
{ |
|
|
|
@ -671,6 +668,8 @@ typedef struct MJpegDecodeContext { |
|
|
|
|
int bottom_field; /* true if bottom field */ |
|
|
|
|
int lossless; |
|
|
|
|
int rgb; |
|
|
|
|
int rct; /* pegasus reversible colorspace transform */
|
|
|
|
|
int bits; /* bits per component */ |
|
|
|
|
|
|
|
|
|
int width, height; |
|
|
|
|
int nb_components; |
|
|
|
@ -834,7 +833,10 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) |
|
|
|
|
|
|
|
|
|
/* XXX: verify len field validity */ |
|
|
|
|
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"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
@ -866,6 +868,8 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) |
|
|
|
|
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 */ |
|
|
|
|
/* XXX: also check h_count and v_count */ |
|
|
|
|
if (width != s->width || height != s->height) { |
|
|
|
@ -882,7 +886,6 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) |
|
|
|
|
s->bottom_field = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
assert(s->rgb==0 || (s->h_max==1 && s->v_max==1)); |
|
|
|
|
if(s->rgb){ |
|
|
|
|
int w, h; |
|
|
|
|
w = s->width; |
|
|
|
@ -1033,6 +1036,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
comp_index[i] = index; |
|
|
|
|
|
|
|
|
|
nb_blocks[i] = s->h_count[index] * s->v_count[index]; |
|
|
|
|
h_count[i] = s->h_count[index]; |
|
|
|
|
v_count[i] = s->v_count[index]; |
|
|
|
@ -1060,6 +1064,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) |
|
|
|
|
break;
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
predictor= get_bits(&s->gb, 8); /* lossless predictor or start of spectral (Ss) */ |
|
|
|
|
skip_bits(&s->gb, 8); /* Se */ |
|
|
|
|
skip_bits(&s->gb, 4); /* Ah */ |
|
|
|
@ -1082,56 +1087,64 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) |
|
|
|
|
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->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 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++) { |
|
|
|
|
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++) { |
|
|
|
|
if (s->restart_interval && !s->restart_count) |
|
|
|
|
s->restart_count = s->restart_interval; |
|
|
|
|
|
|
|
|
|
if(mb_x==0 || mb_y==0 || s->interlaced || 1){ |
|
|
|
|
for(i=0;i<3;i++) { |
|
|
|
|
uint8_t *ptr; |
|
|
|
|
int c, pred; |
|
|
|
|
c = comp_index[i]; |
|
|
|
|
for(i=0;i<3;i++) { |
|
|
|
|
int pred; |
|
|
|
|
|
|
|
|
|
ptr = s->current_picture[0] + (linesize * mb_y) + 4*mb_x + c; //FIXME optimize this crap
|
|
|
|
|
if(mb_y==0){ |
|
|
|
|
if(mb_x==0){ |
|
|
|
|
pred= 128 << point_transform; |
|
|
|
|
}else{ |
|
|
|
|
pred= ptr[-4]; |
|
|
|
|
} |
|
|
|
|
}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]; |
|
|
|
|
PREDICT(pred, topleft[i], top[i], left[i], modified_predictor); |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
topleft[i]= top[i]; |
|
|
|
|
top[i]= buffer[mb_x][i]; |
|
|
|
|
|
|
|
|
|
left[i]=
|
|
|
|
|
buffer[mb_x][i]= mask & (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) && |
|
|
|
|
!--s->restart_count) { |
|
|
|
|
|
|
|
|
|
if (s->restart_interval && !--s->restart_count) { |
|
|
|
|
align_get_bits(&s->gb); |
|
|
|
|
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{ |
|
|
|
|
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) |
|
|
|
|
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++) { |
|
|
|
|
uint8_t *ptr; |
|
|
|
|
int x, y, c, linesize; |
|
|
|
@ -1165,7 +1178,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s) |
|
|
|
|
if(x==0 && mb_x==0){ |
|
|
|
|
pred= ptr[-linesize]; |
|
|
|
|
}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; |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
if (++x == h) { |
|
|
|
|
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_interval < 1350) && |
|
|
|
|
!--s->restart_count) { |
|
|
|
|
if (s->restart_interval && !--s->restart_count) { |
|
|
|
|
align_get_bits(&s->gb); |
|
|
|
|
skip_bits(&s->gb, 16); /* skip RSTn */ |
|
|
|
|
} |
|
|
|
@ -1293,6 +1304,10 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) |
|
|
|
|
id = be2me_32(id); |
|
|
|
|
len -= 6; |
|
|
|
|
|
|
|
|
|
if(s->avctx->debug & FF_DEBUG_STARTCODE){ |
|
|
|
|
printf("APPx %8X\n", id);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* buggy AVID, it puts EOI only at every 10th frame */ |
|
|
|
|
/* also this fourcc is used by non-avid files too, it holds some
|
|
|
|
|
informations, but it's always present in AVID creates files */ |
|
|
|
@ -1375,6 +1390,29 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) |
|
|
|
|
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 */ |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
s->start_code = start_code; |
|
|
|
|
if(s->avctx->debug & FF_DEBUG_STARTCODE){ |
|
|
|
|
printf("startcode: %X\n", start_code); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* process markers */ |
|
|
|
|
if (start_code >= 0xd0 && start_code <= 0xd7) { |
|
|
|
@ -1589,13 +1630,11 @@ static int mjpeg_decode_frame(AVCodecContext *avctx, |
|
|
|
|
break; |
|
|
|
|
case SOF0: |
|
|
|
|
s->lossless=0; |
|
|
|
|
s->rgb=0; |
|
|
|
|
if (mjpeg_decode_sof(s) < 0)
|
|
|
|
|
return -1; |
|
|
|
|
break; |
|
|
|
|
case SOF3: |
|
|
|
|
s->lossless=1; |
|
|
|
|
s->rgb=1; //FIXME
|
|
|
|
|
if (mjpeg_decode_sof(s) < 0)
|
|
|
|
|
return -1; |
|
|
|
|
break; |
|
|
|
@ -1622,7 +1661,11 @@ eoi_parser: |
|
|
|
|
switch((s->h_count[0] << 4) | s->v_count[0]) { |
|
|
|
|
case 0x11: |
|
|
|
|
if(s->rgb){ |
|
|
|
|
#ifdef WORDS_BIGENDIAN |
|
|
|
|
avctx->pix_fmt = PIX_FMT_ABGR32; |
|
|
|
|
#else |
|
|
|
|
avctx->pix_fmt = PIX_FMT_RGBA32; |
|
|
|
|
#endif |
|
|
|
|
}else |
|
|
|
|
avctx->pix_fmt = PIX_FMT_YUV444P; |
|
|
|
|
break; |
|
|
|
|