summaryrefslogtreecommitdiff
path: root/libavcodec/mjpeg.c
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2002-11-20 15:18:11 +0000
committerAlex Beregszaszi <alex@rtfs.hu>2002-11-20 15:18:11 +0000
commitb135d9fb96141e4f596ad3596d63231e6e208268 (patch)
tree42c1c67ac550e15ab008db1b4da1aa04cf88df3e /libavcodec/mjpeg.c
parent829ac53d9806682d975262105ce7ba257c2a3a6f (diff)
mjpegb support (need more samples)
Originally committed as revision 1258 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/mjpeg.c')
-rw-r--r--libavcodec/mjpeg.c150
1 files changed, 141 insertions, 9 deletions
diff --git a/libavcodec/mjpeg.c b/libavcodec/mjpeg.c
index 8b167a1578..899aa06e51 100644
--- a/libavcodec/mjpeg.c
+++ b/libavcodec/mjpeg.c
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Support for external huffman table, various fixes (AVID workaround),
- * aspecting and new decode_frame mechanism
+ * aspecting, new decode_frame mechanism and apple mjpeg-b support
* by Alex Beregszaszi <alex@naxine.org>
*/
//#define DEBUG
@@ -1061,7 +1061,7 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
h_count[0] = 1;
v_count[0] = 1;
}
-
+
for(mb_y = 0; mb_y < mb_height; mb_y++) {
for(mb_x = 0; mb_x < mb_width; mb_x++) {
for(i=0;i<nb_components;i++) {
@@ -1098,8 +1098,8 @@ static int mjpeg_decode_sos(MJpegDecodeContext *s)
}
}
/* (< 1350) buggy workaround for Spectralfan.mov, should be fixed */
-
- if ((s->restart_interval < 1350) && !--s->restart_count) {
+ 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 */
@@ -1373,10 +1373,6 @@ static int mjpeg_decode_frame(AVCodecContext *avctx,
{
UINT8 x = *(src++);
-#if 0
- if (x == 0xff && *src == 0xff)
- break;
-#endif
*(dst++) = x;
if (x == 0xff)
{
@@ -1510,12 +1506,135 @@ not_the_end:
}
}
the_end:
-
dprintf("mjpeg decode frame unused %d bytes\n", buf_end - buf_ptr);
// return buf_end - buf_ptr;
return buf_ptr - buf;
}
+static int mjpegb_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ UINT8 *buf, int buf_size)
+{
+ MJpegDecodeContext *s = avctx->priv_data;
+ UINT8 *buf_end, *buf_ptr;
+ int i;
+ AVPicture *picture = data;
+ GetBitContext hgb; /* for the header */
+ uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs;
+ uint32_t field_size;
+
+ *data_size = 0;
+
+ /* no supplementary picture */
+ if (buf_size == 0)
+ return 0;
+
+ buf_ptr = buf;
+ buf_end = buf + buf_size;
+
+read_header:
+ /* reset on every SOI */
+ s->restart_interval = 0;
+
+ init_get_bits(&hgb, buf_ptr, /*buf_size*/buf_end - buf_ptr);
+
+ skip_bits(&hgb, 32); /* reserved zeros */
+
+ if (get_bits(&hgb, 32) != be2me_32(ff_get_fourcc("mjpg")))
+ {
+ dprintf("not mjpeg-b (bad fourcc)\n");
+ return 0;
+ }
+
+ field_size = get_bits(&hgb, 32); /* field size */
+ dprintf("field size: 0x%x\n", field_size);
+ skip_bits(&hgb, 32); /* padded field size */
+ second_field_offs = get_bits(&hgb, 32);
+ dprintf("second field offs: 0x%x\n", second_field_offs);
+ if (second_field_offs)
+ s->interlaced = 1;
+
+ dqt_offs = get_bits(&hgb, 32);
+ dprintf("dqt offs: 0x%x\n", dqt_offs);
+ if (dqt_offs)
+ {
+ init_get_bits(&s->gb, buf+dqt_offs, buf_end - (buf+dqt_offs));
+ s->start_code = DQT;
+ mjpeg_decode_dqt(s);
+ }
+
+ dht_offs = get_bits(&hgb, 32);
+ dprintf("dht offs: 0x%x\n", dht_offs);
+ if (dht_offs)
+ {
+ init_get_bits(&s->gb, buf+dht_offs, buf_end - (buf+dht_offs));
+ s->start_code = DHT;
+ mjpeg_decode_dht(s);
+ }
+
+ sof_offs = get_bits(&hgb, 32);
+ dprintf("sof offs: 0x%x\n", sof_offs);
+ if (sof_offs)
+ {
+ init_get_bits(&s->gb, buf+sof_offs, buf_end - (buf+sof_offs));
+ s->start_code = SOF0;
+ mjpeg_decode_sof0(s);
+ }
+
+ sos_offs = get_bits(&hgb, 32);
+ dprintf("sos offs: 0x%x\n", sos_offs);
+ if (sos_offs)
+ {
+// init_get_bits(&s->gb, buf+sos_offs, buf_end - (buf+sos_offs));
+ init_get_bits(&s->gb, buf+sos_offs, field_size);
+ s->start_code = SOS;
+ mjpeg_decode_sos(s);
+ }
+
+ skip_bits(&hgb, 32); /* start of data offset */
+
+ if (s->interlaced) {
+ s->bottom_field ^= 1;
+ /* if not bottom field, do not output image yet */
+ if (s->bottom_field && second_field_offs)
+ {
+ buf_ptr = buf + second_field_offs;
+ second_field_offs = 0;
+ goto 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);
+ 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;
+ }
+ /* dummy quality */
+ /* XXX: infer it with matrix */
+ avctx->quality = 3;
+
+ return buf_ptr - buf;
+}
+
+
static int mjpeg_decode_end(AVCodecContext *avctx)
{
MJpegDecodeContext *s = avctx->priv_data;
@@ -1543,3 +1662,16 @@ AVCodec mjpeg_decoder = {
0,
NULL
};
+
+AVCodec mjpegb_decoder = {
+ "mjpegb",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MJPEGB,
+ sizeof(MJpegDecodeContext),
+ mjpeg_decode_init,
+ NULL,
+ mjpeg_decode_end,
+ mjpegb_decode_frame,
+ 0,
+ NULL
+};