summaryrefslogtreecommitdiff
path: root/src/libffmpeg/libavcodec/mjpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libffmpeg/libavcodec/mjpeg.c')
-rw-r--r--src/libffmpeg/libavcodec/mjpeg.c873
1 files changed, 524 insertions, 349 deletions
diff --git a/src/libffmpeg/libavcodec/mjpeg.c b/src/libffmpeg/libavcodec/mjpeg.c
index 1b6b15c4a..48f528f88 100644
--- a/src/libffmpeg/libavcodec/mjpeg.c
+++ b/src/libffmpeg/libavcodec/mjpeg.c
@@ -243,6 +243,7 @@ static void build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code,
}
}
+#ifdef CONFIG_ENCODERS
int mjpeg_init(MpegEncContext *s)
{
MJpegContext *m;
@@ -280,6 +281,7 @@ void mjpeg_close(MpegEncContext *s)
{
av_free(s->mjpeg_ctx);
}
+#endif //CONFIG_ENCODERS
#define PREDICT(ret, topleft, top, left, predictor)\
switch(predictor){\
@@ -289,9 +291,11 @@ void mjpeg_close(MpegEncContext *s)
case 4: ret= left + top - topleft; break;\
case 5: ret= left + ((top - topleft)>>1); break;\
case 6: ret= top + ((left - topleft)>>1); break;\
+ default:\
case 7: ret= (left + top)>>1; break;\
}
+#ifdef CONFIG_ENCODERS
static inline void put_marker(PutBitContext *p, int code)
{
put_bits(p, 8, 0xff);
@@ -377,28 +381,8 @@ static void jpeg_put_comments(MpegEncContext *s)
put_string(p, "JFIF"); /* this puts the trailing zero-byte too */
put_bits(p, 16, 0x0201); /* v 1.02 */
put_bits(p, 8, 0); /* units type: 0 - aspect ratio */
- switch(s->aspect_ratio_info)
- {
- case FF_ASPECT_4_3_625:
- case FF_ASPECT_4_3_525:
- put_bits(p, 16, 4);
- put_bits(p, 16, 3);
- break;
- case FF_ASPECT_16_9_625:
- case FF_ASPECT_16_9_525:
- put_bits(p, 16, 16);
- put_bits(p, 16, 9);
- break;
- case FF_ASPECT_EXTENDED:
- put_bits(p, 16, s->aspected_width);
- put_bits(p, 16, s->aspected_height);
- break;
- case FF_ASPECT_SQUARE:
- default:
- put_bits(p, 16, 1); /* aspect: 1:1 */
- put_bits(p, 16, 1);
- break;
- }
+ put_bits(p, 16, s->avctx->sample_aspect_ratio.num);
+ put_bits(p, 16, s->avctx->sample_aspect_ratio.den);
put_bits(p, 8, 0); /* thumbnail width */
put_bits(p, 8, 0); /* thumbnail height */
}
@@ -575,7 +559,7 @@ static inline void mjpeg_encode_dc(MpegEncContext *s, int val,
mant--;
}
- nbits= av_log2(val) + 1;
+ nbits= av_log2_16bit(val) + 1;
put_bits(&s->pb, huff_size[nbits], huff_code[nbits]);
@@ -659,7 +643,7 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
AVFrame * const p= (AVFrame*)&s->current_picture;
const int predictor= avctx->prediction_method+1;
- init_put_bits(&s->pb, buf, buf_size, NULL, NULL);
+ init_put_bits(&s->pb, buf, buf_size);
*p = *pict;
p->pict_type= FF_I_TYPE;
@@ -680,7 +664,7 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
}
for(y = 0; y < height; y++) {
- const int modified_predictor= y ? 1 : predictor;
+ const int modified_predictor= y ? predictor : 1;
uint8_t *ptr = p->data[0] + (linesize * y);
for(i=0; i<3; i++){
@@ -789,6 +773,7 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in
// return (get_bit_count(&f->pb)+7)/8;
}
+#endif //CONFIG_ENCODERS
/******************************************/
/* decoding */
@@ -806,6 +791,7 @@ typedef struct MJpegDecodeContext {
int16_t quant_matrixes[4][64];
VLC vlcs[2][4];
+ int qscale[4]; ///< quantizer scale calculated from quant_matrixes
int org_width, org_height; /* size given at codec init */
int first_picture; /* true if decoding first picture */
@@ -818,15 +804,23 @@ typedef struct MJpegDecodeContext {
int bits; /* bits per component */
int width, height;
+ int mb_width, mb_height;
int nb_components;
int component_id[MAX_COMPONENTS];
int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */
int v_count[MAX_COMPONENTS];
+ int comp_index[MAX_COMPONENTS];
+ int dc_index[MAX_COMPONENTS];
+ int ac_index[MAX_COMPONENTS];
+ int nb_blocks[MAX_COMPONENTS];
+ int h_scount[MAX_COMPONENTS];
+ int v_scount[MAX_COMPONENTS];
int h_max, v_max; /* maximum h and v counts */
int quant_index[4]; /* quant table index for each component */
int last_dc[MAX_COMPONENTS]; /* last DEQUANTIZED dc (XXX: am I right to do that ?) */
- uint8_t *current_picture[MAX_COMPONENTS]; /* picture structure */
- int linesize[MAX_COMPONENTS];
+ AVFrame picture; /* picture structure */
+ int linesize[MAX_COMPONENTS]; ///< linesize << interlaced
+ uint8_t *qscale_table;
DCTELEM block[64] __align8;
ScanTable scantable;
void (*idct_put)(uint8_t *dest/*align 8*/, int line_size, DCTELEM *block/*align 16*/);
@@ -840,7 +834,7 @@ typedef struct MJpegDecodeContext {
static int mjpeg_decode_dht(MJpegDecodeContext *s);
-static void build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_table,
+static int build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_table,
int nb_codes)
{
uint8_t huff_size[256];
@@ -849,7 +843,7 @@ static void build_vlc(VLC *vlc, const uint8_t *bits_table, const uint8_t *val_ta
memset(huff_size, 0, sizeof(huff_size));
build_huffman_codes(huff_size, huff_code, bits_table, val_table);
- init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2);
+ return init_vlc(vlc, 9, nb_codes, huff_size, 1, 1, huff_code, 2, 2);
}
static int mjpeg_decode_init(AVCodecContext *avctx)
@@ -922,6 +916,12 @@ static int mjpeg_decode_dqt(MJpegDecodeContext *s)
j = s->scantable.permutated[i];
s->quant_matrixes[index][j] = get_bits(&s->gb, 8);
}
+
+ //XXX FIXME finetune, and perhaps add dc too
+ s->qscale[index]= FFMAX(
+ s->quant_matrixes[index][s->scantable.permutated[1]],
+ s->quant_matrixes[index][s->scantable.permutated[8]]) >> 1;
+ dprintf("qscale[%d]: %d\n", index, s->qscale[index]);
len -= 65;
}
@@ -968,7 +968,9 @@ static int mjpeg_decode_dht(MJpegDecodeContext *s)
free_vlc(&s->vlcs[class][index]);
dprintf("class=%d index=%d nb_codes=%d\n",
class, index, code_max + 1);
- build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1);
+ if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1) < 0){
+ return -1;
+ }
}
return 0;
}
@@ -1021,8 +1023,8 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
/* if different size, realloc/alloc picture */
/* XXX: also check h_count and v_count */
if (width != s->width || height != s->height) {
- for(i=0;i<MAX_COMPONENTS;i++)
- av_freep(&s->current_picture[i]);
+ av_freep(&s->qscale_table);
+
s->width = width;
s->height = height;
/* test interlaced mode */
@@ -1034,36 +1036,48 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s)
s->bottom_field = 0;
}
- if(s->rgb){
- int w, h;
- w = s->width;
- h = s->height;
- if (s->interlaced)
- w *= 2;
- s->linesize[0] = 4*w;
- s->current_picture[0] = av_mallocz(4*w * h);
- s->current_picture[1] = s->current_picture[2] = NULL;
- }else{
- for(i=0;i<nb_components;i++) {
- int w, h;
- w = (s->width + 8 * s->h_max - 1) / (8 * s->h_max);
- h = (s->height + 8 * s->v_max - 1) / (8 * s->v_max);
- w = w * 8 * s->h_count[i];
- h = h * 8 * s->v_count[i];
- if (s->interlaced)
- w *= 2;
- s->linesize[i] = w;
- s->current_picture[i] = av_mallocz(w * h);
- if (!s->current_picture[i])
- {
- dprintf("error: no picture buffers allocated\n");
- return -1;
- }
- }
- }
+ s->qscale_table= av_mallocz((s->width+15)/16);
+
s->first_picture = 0;
}
+
+ if(s->interlaced && s->bottom_field)
+ return 0;
+
+ /* XXX: not complete test ! */
+ switch((s->h_count[0] << 4) | s->v_count[0]) {
+ case 0x11:
+ if(s->rgb){
+ s->avctx->pix_fmt = PIX_FMT_RGBA32;
+ }else
+ s->avctx->pix_fmt = PIX_FMT_YUV444P;
+ break;
+ case 0x21:
+ s->avctx->pix_fmt = PIX_FMT_YUV422P;
+ break;
+ default:
+ case 0x22:
+ s->avctx->pix_fmt = PIX_FMT_YUV420P;
+ break;
+ }
+ if(s->picture.data[0])
+ s->avctx->release_buffer(s->avctx, &s->picture);
+
+ s->picture.reference= 0;
+ if(s->avctx->get_buffer(s->avctx, &s->picture) < 0){
+ fprintf(stderr, "get_buffer() failed\n");
+ return -1;
+ }
+ s->picture.pict_type= I_TYPE;
+ s->picture.key_frame= 1;
+
+ for(i=0; i<3; i++){
+ s->linesize[i]= s->picture.linesize[i] << s->interlaced;
+ }
+
+// printf("%d %d %d %d %d %d\n", s->width, s->height, s->linesize[0], s->linesize[1], s->interlaced, s->avctx->height);
+
if (len != (8+(3*nb_components)))
{
dprintf("decode_sof0: error, len(%d) mismatch\n", len);
@@ -1139,16 +1153,211 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
return 0;
}
+static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){
+ int i, mb_x, mb_y;
+ 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 < s->mb_height; mb_y++) {
+ const int modified_predictor= mb_y ? predictor : 1;
+ uint8_t *ptr = s->picture.data[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 < s->mb_width; mb_x++) {
+ if (s->restart_interval && !s->restart_count)
+ s->restart_count = s->restart_interval;
+
+ for(i=0;i<3;i++) {
+ int pred;
+
+ topleft[i]= top[i];
+ top[i]= buffer[mb_x][i];
+
+ PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
+
+ left[i]=
+ buffer[mb_x][i]= mask & (pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform));
+ }
+
+ 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 < s->mb_width; mb_x++) {
+ ptr[4*mb_x+1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200)>>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 if(s->pegasus_rct){
+ for(mb_x = 0; mb_x < s->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 < s->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];
+ }
+ }
+ }
+ return 0;
+}
+
+static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, int point_transform){
+ int i, mb_x, mb_y;
+ const int nb_components=3;
+
+ for(mb_y = 0; mb_y < s->mb_height; mb_y++) {
+ for(mb_x = 0; mb_x < s->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){
+ for(i=0;i<nb_components;i++) {
+ uint8_t *ptr;
+ int n, h, v, x, y, c, j, linesize;
+ n = s->nb_blocks[i];
+ c = s->comp_index[i];
+ h = s->h_scount[i];
+ v = s->v_scount[i];
+ x = 0;
+ y = 0;
+ linesize= s->linesize[c];
+
+ for(j=0; j<n; j++) {
+ int pred;
+
+ ptr = s->picture.data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
+ if(y==0 && mb_y==0){
+ if(x==0 && mb_x==0){
+ pred= 128 << point_transform;
+ }else{
+ pred= ptr[-1];
+ }
+ }else{
+ if(x==0 && mb_x==0){
+ pred= ptr[-linesize];
+ }else{
+ PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
+ }
+ }
+
+ if (s->interlaced && s->bottom_field)
+ ptr += linesize >> 1;
+ *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform);
+
+ if (++x == h) {
+ x = 0;
+ y++;
+ }
+ }
+ }
+ }else{
+ for(i=0;i<nb_components;i++) {
+ uint8_t *ptr;
+ int n, h, v, x, y, c, j, linesize;
+ n = s->nb_blocks[i];
+ c = s->comp_index[i];
+ h = s->h_scount[i];
+ v = s->v_scount[i];
+ x = 0;
+ y = 0;
+ linesize= s->linesize[c];
+
+ for(j=0; j<n; j++) {
+ int pred;
+
+ ptr = s->picture.data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
+ PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
+ *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform);
+ if (++x == h) {
+ x = 0;
+ y++;
+ }
+ }
+ }
+ }
+ if (s->restart_interval && !--s->restart_count) {
+ align_get_bits(&s->gb);
+ skip_bits(&s->gb, 16); /* skip RSTn */
+ }
+ }
+ }
+ return 0;
+}
+
+static int mjpeg_decode_scan(MJpegDecodeContext *s){
+ int i, mb_x, mb_y;
+ const int nb_components=3;
+
+ for(mb_y = 0; mb_y < s->mb_height; mb_y++) {
+ for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
+ if (s->restart_interval && !s->restart_count)
+ s->restart_count = s->restart_interval;
+
+ for(i=0;i<nb_components;i++) {
+ uint8_t *ptr;
+ int n, h, v, x, y, c, j;
+ n = s->nb_blocks[i];
+ c = s->comp_index[i];
+ h = s->h_scount[i];
+ v = s->v_scount[i];
+ x = 0;
+ y = 0;
+ for(j=0;j<n;j++) {
+ memset(s->block, 0, sizeof(s->block));
+ if (decode_block(s, s->block, i,
+ s->dc_index[i], s->ac_index[i],
+ s->quant_index[c]) < 0) {
+ dprintf("error y=%d x=%d\n", mb_y, mb_x);
+ return -1;
+ }
+// dprintf("mb: %d %d processed\n", mb_y, mb_x);
+ ptr = s->picture.data[c] +
+ (s->linesize[c] * (v * mb_y + y) * 8) +
+ (h * mb_x + x) * 8;
+ if (s->interlaced && s->bottom_field)
+ ptr += s->linesize[c] >> 1;
+//printf("%d %d %d %d %d %d %d %d \n", mb_x, mb_y, x, y, c, s->bottom_field, (v * mb_y + y) * 8, (h * mb_x + x) * 8);
+ s->idct_put(ptr, s->linesize[c], s->block);
+ if (++x == h) {
+ x = 0;
+ y++;
+ }
+ }
+ }
+ /* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */
+ if (s->restart_interval && (s->restart_interval < 1350) &&
+ !--s->restart_count) {
+ align_get_bits(&s->gb);
+ skip_bits(&s->gb, 16); /* skip RSTn */
+ for (i=0; i<nb_components; i++) /* reset dc */
+ s->last_dc[i] = 1024;
+ }
+ }
+ }
+ return 0;
+}
+
static int mjpeg_decode_sos(MJpegDecodeContext *s)
{
- int len, nb_components, i, j, n, h, v, ret, point_transform, predictor;
- int mb_width, mb_height, mb_x, mb_y, vmax, hmax, index, id;
- int comp_index[4];
- int dc_index[4];
- int ac_index[4];
- int nb_blocks[4];
- int h_count[4];
- int v_count[4];
+ int len, nb_components, i, h, v, predictor, point_transform;
+ int vmax, hmax, index, id;
const int block_size= s->lossless ? 1 : 8;
/* XXX: verify len field validity */
@@ -1180,18 +1389,19 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
return -1;
}
- comp_index[i] = index;
+ 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];
+ s->nb_blocks[i] = s->h_count[index] * s->v_count[index];
+ s->h_scount[i] = s->h_count[index];
+ s->v_scount[i] = s->v_count[index];
- dc_index[i] = get_bits(&s->gb, 4);
- ac_index[i] = get_bits(&s->gb, 4);
+ s->dc_index[i] = get_bits(&s->gb, 4);
+ s->ac_index[i] = get_bits(&s->gb, 4);
- if (dc_index[i] < 0 || ac_index[i] < 0 ||
- dc_index[i] >= 4 || ac_index[i] >= 4)
+ if (s->dc_index[i] < 0 || s->ac_index[i] < 0 ||
+ s->dc_index[i] >= 4 || s->ac_index[i] >= 4)
goto out_of_range;
+#if 0 //buggy
switch(s->start_code)
{
case SOF0:
@@ -1208,6 +1418,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
goto out_of_range;
break;
}
+#endif
}
predictor= get_bits(&s->gb, 8); /* lossless predictor or start of spectral (Ss) */
@@ -1220,213 +1431,35 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
if (nb_components > 1) {
/* interleaved stream */
- mb_width = (s->width + s->h_max * block_size - 1) / (s->h_max * block_size);
- mb_height = (s->height + s->v_max * block_size - 1) / (s->v_max * block_size);
+ s->mb_width = (s->width + s->h_max * block_size - 1) / (s->h_max * block_size);
+ s->mb_height = (s->height + s->v_max * block_size - 1) / (s->v_max * block_size);
} else {
- h = s->h_max / s->h_count[comp_index[0]];
- v = s->v_max / s->v_count[comp_index[0]];
- mb_width = (s->width + h * block_size - 1) / (h * block_size);
- mb_height = (s->height + v * block_size - 1) / (v * block_size);
- nb_blocks[0] = 1;
- h_count[0] = 1;
- v_count[0] = 1;
+ h = s->h_max / s->h_scount[s->comp_index[0]];
+ v = s->v_max / s->v_scount[s->comp_index[0]];
+ s->mb_width = (s->width + h * block_size - 1) / (h * block_size);
+ s->mb_height = (s->height + v * block_size - 1) / (v * block_size);
+ s->nb_blocks[0] = 1;
+ s->h_scount[0] = 1;
+ s->v_scount[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){
- 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;
-
- for(i=0;i<3;i++) {
- int pred;
-
- topleft[i]= top[i];
- top[i]= buffer[mb_x][i];
-
- PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
-
- left[i]=
- buffer[mb_x][i]= mask & (pred + (mjpeg_decode_dc(s, dc_index[i]) << point_transform));
- }
-
- 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] - 0x200)>>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 if(s->pegasus_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++) {
- 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){
- for(i=0;i<nb_components;i++) {
- uint8_t *ptr;
- int x, y, c, linesize;
- n = nb_blocks[i];
- c = comp_index[i];
- h = h_count[i];
- v = v_count[i];
- x = 0;
- y = 0;
- linesize= s->linesize[c];
-
- for(j=0; j<n; j++) {
- int pred;
-
- ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
- if(y==0 && mb_y==0){
- if(x==0 && mb_x==0){
- pred= 128 << point_transform;
- }else{
- pred= ptr[-1];
- }
- }else{
- if(x==0 && mb_x==0){
- pred= ptr[-linesize];
- }else{
- PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
- }
- }
-
- if (s->interlaced && s->bottom_field)
- ptr += linesize >> 1;
- *ptr= pred + (mjpeg_decode_dc(s, dc_index[i]) << point_transform);
-
- if (++x == h) {
- x = 0;
- y++;
- }
- }
- }
- }else{
- for(i=0;i<nb_components;i++) {
- uint8_t *ptr;
- int x, y, c, linesize;
- n = nb_blocks[i];
- c = comp_index[i];
- h = h_count[i];
- v = v_count[i];
- x = 0;
- y = 0;
- linesize= s->linesize[c];
-
- for(j=0; j<n; j++) {
- int pred;
-
- ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
- 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;
- y++;
- }
- }
- }
- }
- if (s->restart_interval && !--s->restart_count) {
- align_get_bits(&s->gb);
- skip_bits(&s->gb, 16); /* skip RSTn */
- }
- }
+ if(s->rgb){
+ if(ljpeg_decode_rgb_scan(s, predictor, point_transform) < 0)
+ return -1;
+ }else{
+ if(ljpeg_decode_yuv_scan(s, predictor, point_transform) < 0)
+ return -1;
}
- }
}else{
- for(mb_y = 0; mb_y < mb_height; mb_y++) {
- for(mb_x = 0; mb_x < mb_width; mb_x++) {
- if (s->restart_interval && !s->restart_count)
- s->restart_count = s->restart_interval;
-
- for(i=0;i<nb_components;i++) {
- uint8_t *ptr;
- int x, y, c;
- n = nb_blocks[i];
- c = comp_index[i];
- h = h_count[i];
- v = v_count[i];
- x = 0;
- y = 0;
- for(j=0;j<n;j++) {
- memset(s->block, 0, sizeof(s->block));
- if (decode_block(s, s->block, i,
- dc_index[i], ac_index[i],
- s->quant_index[c]) < 0) {
- dprintf("error y=%d x=%d\n", mb_y, mb_x);
- ret = -1;
- goto the_end;
- }
-// dprintf("mb: %d %d processed\n", mb_y, mb_x);
- ptr = s->current_picture[c] +
- (s->linesize[c] * (v * mb_y + y) * 8) +
- (h * mb_x + x) * 8;
- if (s->interlaced && s->bottom_field)
- ptr += s->linesize[c] >> 1;
- s->idct_put(ptr, s->linesize[c], s->block);
- if (++x == h) {
- x = 0;
- y++;
- }
- }
- }
- /* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */
- if (s->restart_interval && (s->restart_interval < 1350) &&
- !--s->restart_count) {
- align_get_bits(&s->gb);
- skip_bits(&s->gb, 16); /* skip RSTn */
- for (j=0; j<nb_components; j++) /* reset dc */
- s->last_dc[j] = 1024;
- }
- }
+ if(mjpeg_decode_scan(s) < 0)
+ return -1;
}
- }
- ret = 0;
- the_end:
emms_c();
- return ret;
+ return 0;
out_of_range:
dprintf("decode_sos: ac/dc index out of range\n");
return -1;
@@ -1494,29 +1527,10 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
skip_bits(&s->gb, 8); /* the trailing zero-byte */
printf("mjpeg: JFIF header found (version: %x.%x)\n",
get_bits(&s->gb, 8), get_bits(&s->gb, 8));
- if (get_bits(&s->gb, 8) == 0)
- {
- int x_density, y_density;
- x_density = get_bits(&s->gb, 16);
- y_density = get_bits(&s->gb, 16);
+ skip_bits(&s->gb, 8);
- dprintf("x/y density: %d (%f), %d (%f)\n", x_density,
- (float)x_density, y_density, (float)y_density);
-#if 0
- //MN: needs to be checked
- if(x_density)
-// s->avctx->aspect_ratio= s->width*y_density/((float)s->height*x_density);
- s->avctx->aspect_ratio = (float)x_density/y_density;
- /* it's better, but every JFIF I have seen stores 1:1 */
- else
- s->avctx->aspect_ratio= 0.0;
-#endif
- }
- else
- {
- skip_bits(&s->gb, 16);
- skip_bits(&s->gb, 16);
- }
+ s->avctx->sample_aspect_ratio.num= get_bits(&s->gb, 16);
+ s->avctx->sample_aspect_ratio.den= get_bits(&s->gb, 16);
t_w = get_bits(&s->gb, 8);
t_h = get_bits(&s->gb, 8);
@@ -1599,7 +1613,7 @@ out:
static int mjpeg_decode_com(MJpegDecodeContext *s)
{
/* XXX: verify len field validity */
- unsigned int len = get_bits(&s->gb, 16);
+ int len = get_bits(&s->gb, 16);
if (len >= 2 && len < 32768) {
/* XXX: any better upper bound */
uint8_t *cbuf = av_malloc(len - 1);
@@ -1667,7 +1681,7 @@ static int find_marker(uint8_t **pbuf_ptr, uint8_t *buf_end)
while (buf_ptr < buf_end) {
v = *buf_ptr++;
v2 = *buf_ptr;
- if ((buf_ptr < buf_end) && (v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe)) {
+ if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe)) {
val = *buf_ptr++;
goto found;
}
@@ -1690,8 +1704,8 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
{
MJpegDecodeContext *s = avctx->priv_data;
uint8_t *buf_end, *buf_ptr;
- int i, start_code;
- AVPicture *picture = data;
+ int start_code;
+ AVFrame *picture = data;
*data_size = 0;
@@ -1776,7 +1790,10 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
mjpeg_decode_dqt(s);
break;
case DHT:
- mjpeg_decode_dht(s);
+ if(mjpeg_decode_dht(s) < 0){
+ fprintf(stderr, "huffman table decode error\n");
+ return -1;
+ }
break;
case SOF0:
s->lossless=0;
@@ -1789,6 +1806,8 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
return -1;
break;
case EOI:
+ if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
+ break;
eoi_parser:
{
if (s->interlaced) {
@@ -1797,35 +1816,23 @@ eoi_parser:
if (s->bottom_field)
goto not_the_end;
}
- for(i=0;i<3;i++) {
- picture->data[i] = s->current_picture[i];
- picture->linesize[i] = (s->interlaced) ?
- s->linesize[i] >> 1 : s->linesize[i];
- }
- *data_size = sizeof(AVPicture);
+ *picture = s->picture;
+ *data_size = sizeof(AVFrame);
avctx->height = s->height;
if (s->interlaced)
avctx->height *= 2;
avctx->width = s->width;
- /* XXX: not complete test ! */
- switch((s->h_count[0] << 4) | s->v_count[0]) {
- case 0x11:
- if(s->rgb){
- avctx->pix_fmt = PIX_FMT_RGBA32;
- }else
- avctx->pix_fmt = PIX_FMT_YUV444P;
- break;
- case 0x21:
- avctx->pix_fmt = PIX_FMT_YUV422P;
- break;
- default:
- case 0x22:
- avctx->pix_fmt = PIX_FMT_YUV420P;
- break;
+
+ if(!s->lossless){
+ picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]);
+ picture->qstride= 0;
+ picture->qscale_table= s->qscale_table;
+ memset(picture->qscale_table, picture->quality, (s->width+15)/16);
+ if(avctx->debug & FF_DEBUG_QP)
+ printf("QP: %d\n", picture->quality);
+ picture->quality*= FF_QP2LAMBDA;
}
- /* dummy quality */
- /* XXX: infer it with matrix */
-// avctx->quality = 3;
+
goto the_end;
}
break;
@@ -1878,8 +1885,7 @@ static int mjpegb_decode_frame(AVCodecContext *avctx,
{
MJpegDecodeContext *s = avctx->priv_data;
uint8_t *buf_end, *buf_ptr;
- int i;
- AVPicture *picture = data;
+ AVFrame *picture = data;
GetBitContext hgb; /* for the header */
uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs;
uint32_t field_size;
@@ -1966,36 +1972,189 @@ read_header:
}
}
- for(i=0;i<3;i++) {
- picture->data[i] = s->current_picture[i];
- picture->linesize[i] = (s->interlaced) ?
- s->linesize[i] >> 1 : s->linesize[i];
- }
- *data_size = sizeof(AVPicture);
+ //XXX FIXME factorize, this looks very similar to the EOI code
+
+ *picture= s->picture;
+ *data_size = sizeof(AVFrame);
avctx->height = s->height;
if (s->interlaced)
avctx->height *= 2;
avctx->width = s->width;
- /* XXX: not complete test ! */
- switch((s->h_count[0] << 4) | s->v_count[0]) {
- case 0x11:
- avctx->pix_fmt = PIX_FMT_YUV444P;
- break;
- case 0x21:
- avctx->pix_fmt = PIX_FMT_YUV422P;
- break;
- default:
- case 0x22:
- avctx->pix_fmt = PIX_FMT_YUV420P;
- break;
+
+ if(!s->lossless){
+ picture->quality= FFMAX(FFMAX(s->qscale[0], s->qscale[1]), s->qscale[2]);
+ picture->qstride= 0;
+ picture->qscale_table= s->qscale_table;
+ memset(picture->qscale_table, picture->quality, (s->width+15)/16);
+ if(avctx->debug & FF_DEBUG_QP)
+ printf("QP: %d\n", picture->quality);
+ picture->quality*= FF_QP2LAMBDA;
}
- /* dummy quality */
- /* XXX: infer it with matrix */
-// avctx->quality = 3;
return buf_ptr - buf;
}
+#include "sp5x.h"
+
+static int sp5x_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ uint8_t *buf, int buf_size)
+{
+#if 0
+ MJpegDecodeContext *s = avctx->priv_data;
+#endif
+ const int qscale = 5;
+ uint8_t *buf_ptr, *buf_end, *recoded;
+ int i = 0, j = 0;
+
+ *data_size = 0;
+
+ /* no supplementary picture */
+ if (buf_size == 0)
+ return 0;
+
+ if (!avctx->width || !avctx->height)
+ return -1;
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+
+#if 1
+ recoded = av_mallocz(buf_size + 1024);
+ if (!recoded)
+ return -1;
+
+ /* SOI */
+ recoded[j++] = 0xFF;
+ recoded[j++] = 0xD8;
+
+ memcpy(recoded+j, &sp5x_data_dqt[0], sizeof(sp5x_data_dqt));
+ memcpy(recoded+j+5, &sp5x_quant_table[qscale * 2], 64);
+ memcpy(recoded+j+70, &sp5x_quant_table[(qscale * 2) + 1], 64);
+ j += sizeof(sp5x_data_dqt);
+
+ memcpy(recoded+j, &sp5x_data_dht[0], sizeof(sp5x_data_dht));
+ j += sizeof(sp5x_data_dht);
+
+ memcpy(recoded+j, &sp5x_data_sof[0], sizeof(sp5x_data_sof));
+ recoded[j+5] = (avctx->height >> 8) & 0xFF;
+ recoded[j+6] = avctx->height & 0xFF;
+ recoded[j+7] = (avctx->width >> 8) & 0xFF;
+ recoded[j+8] = avctx->width & 0xFF;
+ j += sizeof(sp5x_data_sof);
+
+ memcpy(recoded+j, &sp5x_data_sos[0], sizeof(sp5x_data_sos));
+ j += sizeof(sp5x_data_sos);
+
+ for (i = 14; i < buf_size && j < buf_size+1024-2; i++)
+ {
+ recoded[j++] = buf[i];
+ if (buf[i] == 0xff)
+ recoded[j++] = 0;
+ }
+
+ /* EOI */
+ recoded[j++] = 0xFF;
+ recoded[j++] = 0xD9;
+
+ i = mjpeg_decode_frame(avctx, data, data_size, recoded, j);
+
+ av_free(recoded);
+
+#else
+ /* SOF */
+ s->bits = 8;
+ s->width = avctx->width;
+ s->height = avctx->height;
+ s->nb_components = 3;
+ s->component_id[0] = 0;
+ s->h_count[0] = 2;
+ s->v_count[0] = 2;
+ s->quant_index[0] = 0;
+ s->component_id[1] = 1;
+ s->h_count[1] = 1;
+ s->v_count[1] = 1;
+ s->quant_index[1] = 1;
+ s->component_id[2] = 2;
+ s->h_count[2] = 1;
+ s->v_count[2] = 1;
+ s->quant_index[2] = 1;
+ s->h_max = 2;
+ s->v_max = 2;
+
+ s->qscale_table = av_mallocz((s->width+15)/16);
+ avctx->pix_fmt = PIX_FMT_YUV420P;
+ s->interlaced = 0;
+
+ s->picture.reference = 0;
+ if (avctx->get_buffer(avctx, &s->picture) < 0)
+ {
+ fprintf(stderr, "get_buffer() failed\n");
+ return -1;
+ }
+
+ s->picture.pict_type = I_TYPE;
+ s->picture.key_frame = 1;
+
+ for (i = 0; i < 3; i++)
+ s->linesize[i] = s->picture.linesize[i] << s->interlaced;
+
+ /* DQT */
+ for (i = 0; i < 64; i++)
+ {
+ j = s->scantable.permutated[i];
+ s->quant_matrixes[0][j] = sp5x_quant_table[(qscale * 2) + i];
+ }
+ s->qscale[0] = FFMAX(
+ s->quant_matrixes[0][s->scantable.permutated[1]],
+ s->quant_matrixes[0][s->scantable.permutated[8]]) >> 1;
+
+ for (i = 0; i < 64; i++)
+ {
+ j = s->scantable.permutated[i];
+ s->quant_matrixes[1][j] = sp5x_quant_table[(qscale * 2) + 1 + i];
+ }
+ s->qscale[1] = FFMAX(
+ s->quant_matrixes[1][s->scantable.permutated[1]],
+ s->quant_matrixes[1][s->scantable.permutated[8]]) >> 1;
+
+ /* DHT */
+
+ /* SOS */
+ s->comp_index[0] = 0;
+ s->nb_blocks[0] = s->h_count[0] * s->v_count[0];
+ s->h_scount[0] = s->h_count[0];
+ s->v_scount[0] = s->v_count[0];
+ s->dc_index[0] = 0;
+ s->ac_index[0] = 0;
+
+ s->comp_index[1] = 1;
+ s->nb_blocks[1] = s->h_count[1] * s->v_count[1];
+ s->h_scount[1] = s->h_count[1];
+ s->v_scount[1] = s->v_count[1];
+ s->dc_index[1] = 1;
+ s->ac_index[1] = 1;
+
+ s->comp_index[2] = 2;
+ s->nb_blocks[2] = s->h_count[2] * s->v_count[2];
+ s->h_scount[2] = s->h_count[2];
+ s->v_scount[2] = s->v_count[2];
+ s->dc_index[2] = 1;
+ s->ac_index[2] = 1;
+
+ for (i = 0; i < 3; i++)
+ s->last_dc[i] = 1024;
+
+ s->mb_width = (s->width * s->h_max * 8 -1) / (s->h_max * 8);
+ s->mb_height = (s->height * s->v_max * 8 -1) / (s->v_max * 8);
+
+ init_get_bits(&s->gb, buf, buf_size*8);
+
+ return mjpeg_decode_scan(s);
+#endif
+
+ return i;
+}
static int mjpeg_decode_end(AVCodecContext *avctx)
{
@@ -2003,8 +2162,9 @@ static int mjpeg_decode_end(AVCodecContext *avctx)
int i, j;
av_free(s->buffer);
- for(i=0;i<MAX_COMPONENTS;i++)
- av_free(s->current_picture[i]);
+ av_free(s->qscale_table);
+ avcodec_default_free_buffers(avctx);
+
for(i=0;i<2;i++) {
for(j=0;j<4;j++)
free_vlc(&s->vlcs[i][j]);
@@ -2021,7 +2181,7 @@ AVCodec mjpeg_decoder = {
NULL,
mjpeg_decode_end,
mjpeg_decode_frame,
- 0,
+ CODEC_CAP_DR1,
NULL
};
@@ -2034,10 +2194,24 @@ AVCodec mjpegb_decoder = {
NULL,
mjpeg_decode_end,
mjpegb_decode_frame,
- 0,
+ CODEC_CAP_DR1,
NULL
};
+AVCodec sp5x_decoder = {
+ "sp5x",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_SP5X,
+ sizeof(MJpegDecodeContext),
+ mjpeg_decode_init,
+ NULL,
+ mjpeg_decode_end,
+ sp5x_decode_frame,
+ CODEC_CAP_DR1,
+ NULL
+};
+
+#ifdef CONFIG_ENCODERS
AVCodec ljpeg_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them
"ljpeg",
CODEC_TYPE_VIDEO,
@@ -2047,3 +2221,4 @@ AVCodec ljpeg_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them
encode_picture_lossless,
MPV_encode_end,
};
+#endif