summaryrefslogtreecommitdiff
path: root/libavcodec/h263dec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/h263dec.c')
-rw-r--r--libavcodec/h263dec.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
new file mode 100644
index 0000000000..2af76199ab
--- /dev/null
+++ b/libavcodec/h263dec.c
@@ -0,0 +1,205 @@
+/*
+ * H263 decoder
+ * Copyright (c) 2001 Gerard Lantau.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "dsputil.h"
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+//#define DEBUG
+
+static int h263_decode_init(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ s->out_format = FMT_H263;
+
+ s->width = avctx->width;
+ s->height = avctx->height;
+
+ /* select sub codec */
+ switch(avctx->codec->id) {
+ case CODEC_ID_H263:
+ break;
+ case CODEC_ID_OPENDIVX:
+ s->time_increment_bits = 4; /* default value for broken headers */
+ s->h263_pred = 1;
+ break;
+ case CODEC_ID_MSMPEG4:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ break;
+ case CODEC_ID_H263I:
+ s->h263_intel = 1;
+ break;
+ default:
+ return -1;
+ }
+
+ /* for h263, we allocate the images after having read the header */
+ if (MPV_common_init(s) < 0)
+ return -1;
+
+ if (s->h263_msmpeg4)
+ msmpeg4_decode_init_vlc(s);
+ else
+ h263_decode_init_vlc(s);
+
+ return 0;
+}
+
+static int h263_decode_end(AVCodecContext *avctx)
+{
+ MpegEncContext *s = avctx->priv_data;
+
+ MPV_common_end(s);
+ return 0;
+}
+
+static int h263_decode_frame(AVCodecContext *avctx,
+ void *data, int *data_size,
+ UINT8 *buf, int buf_size)
+{
+ MpegEncContext *s = avctx->priv_data;
+ int ret;
+ DCTELEM block[6][64];
+ AVPicture *pict = data;
+
+#ifdef DEBUG
+ printf("*****frame %d size=%d\n", avctx->frame_number, buf_size);
+ printf("bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
+#endif
+
+ /* no supplementary picture */
+ if (buf_size == 0) {
+ *data_size = 0;
+ return 0;
+ }
+
+ init_get_bits(&s->gb, buf, buf_size);
+
+ /* let's go :-) */
+ if (s->h263_msmpeg4) {
+ ret = msmpeg4_decode_picture_header(s);
+ } else if (s->h263_pred) {
+ ret = mpeg4_decode_picture_header(s);
+ } else if (s->h263_intel) {
+ ret = intel_h263_decode_picture_header(s);
+ } else {
+ ret = h263_decode_picture_header(s);
+ }
+ if (ret < 0)
+ return -1;
+
+ MPV_frame_start(s);
+
+#ifdef DEBUG
+ printf("qscale=%d\n", s->qscale);
+#endif
+
+ /* decode each macroblock */
+ for(s->mb_y=0; s->mb_y < s->mb_height; s->mb_y++) {
+ for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) {
+#ifdef DEBUG
+ printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
+#endif
+ /* DCT & quantize */
+ if (s->h263_msmpeg4) {
+ msmpeg4_dc_scale(s);
+ } else if (s->h263_pred) {
+ h263_dc_scale(s);
+ } else {
+ /* default quantization values */
+ s->y_dc_scale = 8;
+ s->c_dc_scale = 8;
+ }
+
+ memset(block, 0, sizeof(block));
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ if (s->h263_msmpeg4) {
+ if (msmpeg4_decode_mb(s, block) < 0)
+ return -1;
+ } else {
+ if (h263_decode_mb(s, block) < 0)
+ return -1;
+ }
+ MPV_decode_mb(s, block);
+ }
+ }
+
+ MPV_frame_end(s);
+
+ pict->data[0] = s->current_picture[0];
+ pict->data[1] = s->current_picture[1];
+ pict->data[2] = s->current_picture[2];
+ pict->linesize[0] = s->linesize;
+ pict->linesize[1] = s->linesize / 2;
+ pict->linesize[2] = s->linesize / 2;
+
+ avctx->quality = s->qscale;
+ *data_size = sizeof(AVPicture);
+ return buf_size;
+}
+
+AVCodec opendivx_decoder = {
+ "opendivx",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_OPENDIVX,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+
+AVCodec h263_decoder = {
+ "h263",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+
+AVCodec msmpeg4_decoder = {
+ "msmpeg4",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_MSMPEG4,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+
+AVCodec h263i_decoder = {
+ "h263i",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_H263I,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+};
+