summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libmpeg3/video/motion.c
Side-by-side diff
Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/video/motion.c') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmpeg3/video/motion.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmpeg3/video/motion.c b/core/multimedia/opieplayer/libmpeg3/video/motion.c
new file mode 100644
index 0000000..4d2f681
--- a/dev/null
+++ b/core/multimedia/opieplayer/libmpeg3/video/motion.c
@@ -0,0 +1,230 @@
+#include "mpeg3video.h"
+#include "../libmpeg3.h"
+#include "../mpeg3protos.h"
+#include "vlc.h"
+
+#include <stdio.h>
+
+
+/* calculate motion vector component */
+
+static inline void mpeg3video_calc_mv(int *pred, int r_size, int motion_code, int motion_r, int full_pel_vector)
+{
+ int lim = 16 << r_size;
+ int vec = full_pel_vector ? (*pred >> 1) : (*pred);
+
+ if(motion_code > 0)
+ {
+ vec += ((motion_code - 1) << r_size) + motion_r + 1;
+ if(vec >= lim) vec -= lim + lim;
+ }
+ else
+ if(motion_code < 0)
+ {
+ vec -= ((-motion_code - 1) << r_size) + motion_r + 1;
+ if(vec < -lim) vec += lim + lim;
+ }
+ *pred = full_pel_vector ? (vec << 1) : vec;
+}
+
+
+/*
+int *dmvector, * differential motion vector *
+int mvx, int mvy * decoded mv components (always in field format) *
+*/
+void mpeg3video_calc_dmv(mpeg3video_t *video,
+ int DMV[][2],
+ int *dmvector,
+ int mvx,
+ int mvy)
+{
+ if(video->pict_struct == FRAME_PICTURE)
+ {
+ if(video->topfirst)
+ {
+/* vector for prediction of top field from bottom field */
+ DMV[0][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0];
+ DMV[0][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] - 1;
+
+/* vector for prediction of bottom field from top field */
+ DMV[1][0] = ((3 * mvx + (mvx > 0)) >> 1) + dmvector[0];
+ DMV[1][1] = ((3 * mvy + (mvy > 0)) >> 1) + dmvector[1] + 1;
+ }
+ else
+ {
+/* vector for prediction of top field from bottom field */
+ DMV[0][0] = ((3 * mvx + (mvx>0)) >> 1) + dmvector[0];
+ DMV[0][1] = ((3 * mvy + (mvy>0)) >> 1) + dmvector[1] - 1;
+
+/* vector for prediction of bottom field from top field */
+ DMV[1][0] = ((mvx + (mvx>0)) >> 1) + dmvector[0];
+ DMV[1][1] = ((mvy + (mvy>0)) >> 1) + dmvector[1] + 1;
+ }
+ }
+ else
+ {
+/* vector for prediction from field of opposite 'parity' */
+ DMV[0][0] = ((mvx + (mvx > 0)) >> 1) + dmvector[0];
+ DMV[0][1] = ((mvy + (mvy > 0)) >> 1) + dmvector[1];
+
+/* correct for vertical field shift */
+ if(video->pict_struct == TOP_FIELD)
+ DMV[0][1]--;
+ else
+ DMV[0][1]++;
+ }
+}
+
+static inline int mpeg3video_get_mv(mpeg3_slice_t *slice)
+{
+ int code;
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+
+ if(mpeg3slice_getbit(slice_buffer))
+ {
+ return 0;
+ }
+
+ if((code = mpeg3slice_showbits9(slice_buffer)) >= 64)
+ {
+ code >>= 6;
+ mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab0[code].len);
+ return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab0[code].val : mpeg3_MVtab0[code].val;
+ }
+
+ if(code >= 24)
+ {
+ code >>= 3;
+ mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab1[code].len);
+ return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab1[code].val : mpeg3_MVtab1[code].val;
+ }
+
+ if((code -= 12) < 0)
+ {
+/* fprintf(stdout,"mpeg3video_get_mv: invalid motion_vector code\n"); */
+ slice->fault = 1;
+ return 1;
+ }
+
+ mpeg3slice_flushbits(slice_buffer, mpeg3_MVtab2[code].len);
+ return mpeg3slice_getbit(slice_buffer) ? -mpeg3_MVtab2[code].val : mpeg3_MVtab2[code].val;
+}
+
+/* get differential motion vector (for dual prime prediction) */
+
+static inline int mpeg3video_get_dmv(mpeg3_slice_t *slice)
+{
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ if(mpeg3slice_getbit(slice_buffer))
+ {
+ return mpeg3slice_getbit(slice_buffer) ? -1 : 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+
+/* get and decode motion vector and differential motion vector */
+
+void mpeg3video_motion_vector(mpeg3_slice_t *slice,
+ mpeg3video_t *video,
+ int *PMV,
+ int *dmvector,
+ int h_r_size,
+ int v_r_size,
+ int dmv,
+ int mvscale,
+ int full_pel_vector)
+{
+ int motion_r;
+ int motion_code = mpeg3video_get_mv(slice);
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+
+ if(slice->fault) return;
+ motion_r = (h_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, h_r_size) : 0;
+
+ mpeg3video_calc_mv(&PMV[0], h_r_size, motion_code, motion_r, full_pel_vector);
+
+ if(dmv) dmvector[0] = mpeg3video_get_dmv(slice);
+
+ motion_code = mpeg3video_get_mv(slice);
+ if(slice->fault) return;
+ motion_r = (v_r_size != 0 && motion_code != 0) ? mpeg3slice_getbits(slice_buffer, v_r_size) : 0;
+
+/* DIV 2 */
+ if(mvscale) PMV[1] >>= 1;
+
+ mpeg3video_calc_mv(&PMV[1], v_r_size, motion_code, motion_r, full_pel_vector);
+
+ if(mvscale) PMV[1] <<= 1;
+ if(dmv) dmvector[1] = mpeg3video_get_dmv(slice);
+}
+
+int mpeg3video_motion_vectors(mpeg3_slice_t *slice,
+ mpeg3video_t *video,
+ int PMV[2][2][2],
+ int dmvector[2],
+ int mv_field_sel[2][2],
+ int s,
+ int mv_count,
+ int mv_format,
+ int h_r_size,
+ int v_r_size,
+ int dmv,
+ int mvscale)
+{
+ int result = 0;
+ mpeg3_slice_buffer_t *slice_buffer = slice->slice_buffer;
+ if(mv_count == 1)
+ {
+ if(mv_format == MV_FIELD && !dmv)
+ {
+ mv_field_sel[1][s] = mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer);
+ }
+
+ mpeg3video_motion_vector(slice,
+ video,
+ PMV[0][s],
+ dmvector,
+ h_r_size,
+ v_r_size,
+ dmv,
+ mvscale,
+ 0);
+ if(slice->fault) return 1;
+
+/* update other motion vector predictors */
+ PMV[1][s][0] = PMV[0][s][0];
+ PMV[1][s][1] = PMV[0][s][1];
+ }
+ else
+ {
+ mv_field_sel[0][s] = mpeg3slice_getbit(slice_buffer);
+ mpeg3video_motion_vector(slice,
+ video,
+ PMV[0][s],
+ dmvector,
+ h_r_size,
+ v_r_size,
+ dmv,
+ mvscale,
+ 0);
+ if(slice->fault) return 1;
+
+ mv_field_sel[1][s] = mpeg3slice_getbit(slice_buffer);
+ mpeg3video_motion_vector(slice,
+ video,
+ PMV[1][s],
+ dmvector,
+ h_r_size,
+ v_r_size,
+ dmv,
+ mvscale,
+ 0);
+ if(slice->fault) return 1;
+ }
+ return 0;
+}