summaryrefslogtreecommitdiff
path: root/libavcodec/mjpeg.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2003-06-16 13:19:30 +0000
committerMichael Niedermayer <michaelni@gmx.at>2003-06-16 13:19:30 +0000
commit63efe9a7e6467895e2aac21418949247e4cc511d (patch)
tree175d7ae847a6eb473a31e9da1c77a18cdd536493 /libavcodec/mjpeg.c
parent1433e6c4994c59abe7d3cdc4d8d9f7db6682efce (diff)
cleanup
pegasus "pseudo yuv" (=RCT) lossless decoding support bigendian fix? Originally committed as revision 1963 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/mjpeg.c')
-rw-r--r--libavcodec/mjpeg.c161
1 files changed, 102 insertions, 59 deletions
diff --git a/libavcodec/mjpeg.c b/libavcodec/mjpeg.c
index f6f735d371..7c5752522b 100644
--- a/libavcodec/mjpeg.c
+++ b/libavcodec/mjpeg.c
@@ -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;
}
@@ -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],
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 */
@@ -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];
-
- 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);
- }
+ PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
+
+ 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 */
@@ -1374,6 +1389,29 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
len -= 7;
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;