summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c
Side-by-side diff
Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/video/macroblocks.c') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmpeg3/video/macroblocks.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c b/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c
new file mode 100644
index 0000000..11e17c1
--- a/dev/null
+++ b/core/multimedia/opieplayer/libmpeg3/video/macroblocks.c
@@ -0,0 +1,338 @@
+#include "../libmpeg3.h"
+#include "../mpeg3protos.h"
+#include "mpeg3video.h"
+#include "slice.h"
+#include "vlc.h"
+
+#include <stdio.h>
+
+int mpeg3video_get_macroblock_address(mpeg3_slice_t *slice)
+{
+ int code, val = 0;
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+
+ while((code = mpeg3slice_showbits(slice_buffer, 11)) < 24)
+ {
+/* Is not macroblock_stuffing */
+ if(code != 15)
+ {
+/* Is macroblock_escape */
+ if(code == 8)
+ {
+ val += 33;
+ }
+ else
+ {
+/* fprintf(stderr, "mpeg3video_get_macroblock_address: invalid macroblock_address_increment code\n"); */
+ slice->fault = 1;
+ return 1;
+ }
+ }
+
+ mpeg3slice_flushbits(slice_buffer, 11);
+ }
+
+ if(code >= 1024)
+ {
+ mpeg3slice_flushbit(slice_buffer);
+ return val + 1;
+ }
+
+ if(code >= 128)
+ {
+ code >>= 6;
+ mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab1[code].len);
+ return val + mpeg3_MBAtab1[code].val;
+ }
+
+ code -= 24;
+ mpeg3slice_flushbits(slice_buffer, mpeg3_MBAtab2[code].len);
+
+ return val + mpeg3_MBAtab2[code].val;
+}
+
+/* macroblock_type for pictures with spatial scalability */
+
+static inline int mpeg3video_getsp_imb_type(mpeg3_slice_t *slice)
+{
+// ### This looks wrong.
+// slice_buffer is used without being initialised and slice is not used
+// mpeg3_slice_buffer_t *slice_buffer = slice_buffer;
+// I think this would make more sense and might be what is intended
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ unsigned int code = mpeg3slice_showbits(slice_buffer, 4);
+ if(!code)
+ {
+/* fprintf(stderr,"mpeg3video_getsp_imb_type: invalid macroblock_type code\n"); */
+ slice->fault = 1;
+ return 0;
+ }
+
+ mpeg3slice_flushbits(slice_buffer, mpeg3_spIMBtab[code].len);
+ return mpeg3_spIMBtab[code].val;
+}
+
+static inline int mpeg3video_getsp_pmb_type(mpeg3_slice_t *slice)
+{
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ int code = mpeg3slice_showbits(slice_buffer, 7);
+ if(code < 2)
+ {
+/* fprintf(stderr,"mpeg3video_getsp_pmb_type: invalid macroblock_type code\n"); */
+ slice->fault = 1;
+ return 0;
+ }
+
+ if(code >= 16)
+ {
+ code >>= 3;
+ mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab0[code].len);
+
+ return mpeg3_spPMBtab0[code].val;
+ }
+
+ mpeg3slice_flushbits(slice_buffer, mpeg3_spPMBtab1[code].len);
+ return mpeg3_spPMBtab1[code].val;
+}
+
+static inline int mpeg3video_getsp_bmb_type(mpeg3_slice_t *slice)
+{
+ mpeg3_VLCtab_t *p;
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ int code = mpeg3slice_showbits9(slice_buffer);
+
+ if(code >= 64)
+ p = &mpeg3_spBMBtab0[(code >> 5) - 2];
+ else
+ if(code >= 16)
+ p = &mpeg3_spBMBtab1[(code >> 2) - 4];
+ else
+ if(code >= 8)
+ p = &mpeg3_spBMBtab2[code - 8];
+ else
+ {
+/* fprintf(stderr,"mpeg3video_getsp_bmb_type: invalid macroblock_type code\n"); */
+ slice->fault = 1;
+ return 0;
+ }
+
+ mpeg3slice_flushbits(slice_buffer, p->len);
+ return p->val;
+}
+
+static inline int mpeg3video_get_imb_type(mpeg3_slice_t *slice)
+{
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ if(mpeg3slice_getbit(slice_buffer))
+ {
+ return 1;
+ }
+
+ if(!mpeg3slice_getbit(slice_buffer))
+ {
+/* fprintf(stderr,"mpeg3video_get_imb_type: invalid macroblock_type code\n"); */
+ slice->fault = 1;
+ }
+
+ return 17;
+}
+
+static inline int mpeg3video_get_pmb_type(mpeg3_slice_t *slice)
+{
+ int code;
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+
+ if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8)
+ {
+ code >>= 3;
+ mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab0[code].len);
+ return mpeg3_PMBtab0[code].val;
+ }
+
+ if(code == 0)
+ {
+/* fprintf(stderr,"mpeg3video_get_pmb_type: invalid macroblock_type code\n"); */
+ slice->fault = 1;
+ return 0;
+ }
+
+ mpeg3slice_flushbits(slice_buffer, mpeg3_PMBtab1[code].len);
+ return mpeg3_PMBtab1[code].val;
+}
+
+static inline int mpeg3video_get_bmb_type(mpeg3_slice_t *slice)
+{
+ int code;
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+
+ if((code = mpeg3slice_showbits(slice_buffer, 6)) >= 8)
+ {
+ code >>= 2;
+ mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab0[code].len);
+ return mpeg3_BMBtab0[code].val;
+ }
+
+ if(code == 0)
+ {
+/* fprintf(stderr,"mpeg3video_get_bmb_type: invalid macroblock_type code\n"); */
+ slice->fault = 1;
+ return 0;
+ }
+
+ mpeg3slice_flushbits(slice_buffer, mpeg3_BMBtab1[code].len);
+
+ return mpeg3_BMBtab1[code].val;
+}
+
+static inline int mpeg3video_get_dmb_type(mpeg3_slice_t *slice)
+{
+ if(!mpeg3slice_getbit(slice->slice_buffer))
+ {
+/* fprintf(stderr,"mpeg3video_get_dmb_type: invalid macroblock_type code\n"); */
+ slice->fault=1;
+ }
+
+ return 1;
+}
+
+
+static inline int mpeg3video_get_snrmb_type(mpeg3_slice_t *slice)
+{
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ int code = mpeg3slice_showbits(slice_buffer, 3);
+
+ if(code == 0)
+ {
+/* fprintf(stderr,"mpeg3video_get_snrmb_type: invalid macroblock_type code\n"); */
+ slice->fault = 1;
+ return 0;
+ }
+
+ mpeg3slice_flushbits(slice_buffer, mpeg3_SNRMBtab[code].len);
+ return mpeg3_SNRMBtab[code].val;
+}
+
+int mpeg3video_get_mb_type(mpeg3_slice_t *slice, mpeg3video_t *video)
+{
+ if(video->scalable_mode == SC_SNR)
+ {
+ return mpeg3video_get_snrmb_type(slice);
+ }
+ else
+ {
+ switch(video->pict_type)
+ {
+ case I_TYPE: return video->pict_scal ? mpeg3video_getsp_imb_type(slice) : mpeg3video_get_imb_type(slice);
+ case P_TYPE: return video->pict_scal ? mpeg3video_getsp_pmb_type(slice) : mpeg3video_get_pmb_type(slice);
+ case B_TYPE: return video->pict_scal ? mpeg3video_getsp_bmb_type(slice) : mpeg3video_get_bmb_type(slice);
+ case D_TYPE: return mpeg3video_get_dmb_type(slice);
+ default:
+ /*fprintf(stderr, "mpeg3video_getmbtype: unknown coding type\n"); */
+ break;
+/* MPEG-1 only, not implemented */
+ }
+ }
+
+ return 0;
+}
+
+int mpeg3video_macroblock_modes(mpeg3_slice_t *slice,
+ mpeg3video_t *video,
+ int *pmb_type,
+ int *pstwtype,
+ int *pstwclass,
+ int *pmotion_type,
+ int *pmv_count,
+ int *pmv_format,
+ int *pdmv,
+ int *pmvscale,
+ int *pdct_type)
+{
+ int mb_type;
+ int stwtype, stwcode, stwclass;
+ int motion_type = 0, mv_count, mv_format, dmv, mvscale;
+ int dct_type;
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ static unsigned char stwc_table[3][4]
+ = { {6,3,7,4}, {2,1,5,4}, {2,5,7,4} };
+ static unsigned char stwclass_table[9]
+ = {0, 1, 2, 1, 1, 2, 3, 3, 4};
+
+/* get macroblock_type */
+ mb_type = mpeg3video_get_mb_type(slice, video);
+
+ if(slice->fault) return 1;
+
+/* get spatial_temporal_weight_code */
+ if(mb_type & MB_WEIGHT)
+ {
+ if(video->stwc_table_index == 0)
+ stwtype = 4;
+ else
+ {
+ stwcode = mpeg3slice_getbits2(slice_buffer);
+ stwtype = stwc_table[video->stwc_table_index - 1][stwcode];
+ }
+ }
+ else
+ stwtype = (mb_type & MB_CLASS4) ? 8 : 0;
+
+/* derive spatial_temporal_weight_class (Table 7-18) */
+ stwclass = stwclass_table[stwtype];
+
+/* get frame/field motion type */
+ if(mb_type & (MB_FORWARD | MB_BACKWARD))
+ {
+ if(video->pict_struct == FRAME_PICTURE)
+ {
+/* frame_motion_type */
+ motion_type = video->frame_pred_dct ? MC_FRAME : mpeg3slice_getbits2(slice_buffer);
+ }
+ else
+ {
+/* field_motion_type */
+ motion_type = mpeg3slice_getbits2(slice_buffer);
+ }
+ }
+ else
+ if((mb_type & MB_INTRA) && video->conceal_mv)
+ {
+/* concealment motion vectors */
+ motion_type = (video->pict_struct == FRAME_PICTURE) ? MC_FRAME : MC_FIELD;
+ }
+
+/* derive mv_count, mv_format and dmv, (table 6-17, 6-18) */
+ if(video->pict_struct == FRAME_PICTURE)
+ {
+ mv_count = (motion_type == MC_FIELD && stwclass < 2) ? 2 : 1;
+ mv_format = (motion_type == MC_FRAME) ? MV_FRAME : MV_FIELD;
+ }
+ else
+ {
+ mv_count = (motion_type == MC_16X8) ? 2 : 1;
+ mv_format = MV_FIELD;
+ }
+
+ dmv = (motion_type == MC_DMV); /* dual prime */
+
+/* field mv predictions in frame pictures have to be scaled */
+ mvscale = ((mv_format == MV_FIELD) && (video->pict_struct == FRAME_PICTURE));
+
+/* get dct_type (frame DCT / field DCT) */
+ dct_type = (video->pict_struct == FRAME_PICTURE) &&
+ (!video->frame_pred_dct) &&
+ (mb_type & (MB_PATTERN | MB_INTRA)) ?
+ mpeg3slice_getbit(slice_buffer) : 0;
+
+/* return values */
+ *pmb_type = mb_type;
+ *pstwtype = stwtype;
+ *pstwclass = stwclass;
+ *pmotion_type = motion_type;
+ *pmv_count = mv_count;
+ *pmv_format = mv_format;
+ *pdmv = dmv;
+ *pmvscale = mvscale;
+ *pdct_type = dct_type;
+ return 0;
+}