summaryrefslogtreecommitdiff
Diffstat
-rw-r--r--drivers/amvdec_ports/Makefile13
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c22
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h3
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c534
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.h39
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c57
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h11
-rw-r--r--drivers/amvdec_ports/aml_vcodec_util.c18
-rw-r--r--drivers/amvdec_ports/aml_vcodec_util.h8
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.c9
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.h6
-rw-r--r--drivers/amvdec_ports/decoder/aml_h264_parser.c662
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_h264_parser.h226
-rw-r--r--drivers/amvdec_ports/decoder/aml_hevc_parser.c1274
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_hevc_parser.h137
-rw-r--r--drivers/amvdec_ports/decoder/aml_mjpeg_parser.c397
-rw-r--r--drivers/amvdec_ports/decoder/aml_mjpeg_parser.h163
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg12_parser.c198
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg12_parser.h74
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg4_parser.c1233
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg4_parser.h250
-rw-r--r--drivers/amvdec_ports/decoder/aml_vp9_parser.c299
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_vp9_parser.h279
-rw-r--r--drivers/amvdec_ports/decoder/h264_parse.c389
-rw-r--r--drivers/amvdec_ports/decoder/h264_parse.h141
-rw-r--r--drivers/amvdec_ports/decoder/h264_stream.c111
-rw-r--r--drivers/amvdec_ports/decoder/h264_stream.h39
-rw-r--r--drivers/amvdec_ports/decoder/vdec_h264_if.c357
-rw-r--r--drivers/amvdec_ports/decoder/vdec_hevc_if.c477
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mjpeg_if.c498
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg12_if.c490
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg4_if.c499
-rw-r--r--drivers/amvdec_ports/decoder/vdec_vp9_if.c461
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/vdec_vp9_trigger.h0
-rw-r--r--drivers/amvdec_ports/test/vcodec_m2m_test.c18
-rw-r--r--drivers/amvdec_ports/utils/common.c221
-rw-r--r--drivers/amvdec_ports/utils/common.h72
-rw-r--r--drivers/amvdec_ports/utils/get_bits.h590
-rw-r--r--drivers/amvdec_ports/utils/golomb.c147
-rw-r--r--drivers/amvdec_ports/utils/golomb.h500
-rw-r--r--drivers/amvdec_ports/utils/pixfmt.h470
-rw-r--r--drivers/amvdec_ports/utils/put_bits.h323
-rw-r--r--drivers/amvdec_ports/vdec_drv_base.h11
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.c45
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.h10
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c219
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c308
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c334
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c233
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c317
-rw-r--r--drivers/frame_provider/decoder/utils/Makefile1
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_input.c19
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c131
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h22
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c388
55 files changed, 11471 insertions, 2282 deletions
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
new file mode 100644
index 0000000..b16c2d1
--- a/dev/null
+++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
@@ -0,0 +1,1233 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "aml_mpeg4_parser.h"
+#include "../utils/get_bits.h"
+#include "../utils/put_bits.h"
+#include "../utils/golomb.h"
+#include "../utils/common.h"
+#include "utils.h"
+
+const u8 ff_mpeg4_dc_threshold[8]={
+ 99, 13, 15, 17, 19, 21, 23, 0
+};
+
+/* these matrixes will be permuted for the idct */
+const int16_t ff_mpeg4_default_intra_matrix[64] = {
+ 8, 17, 18, 19, 21, 23, 25, 27,
+ 17, 18, 19, 21, 23, 25, 27, 28,
+ 20, 21, 22, 23, 24, 26, 28, 30,
+ 21, 22, 23, 24, 26, 28, 30, 32,
+ 22, 23, 24, 26, 28, 30, 32, 35,
+ 23, 24, 26, 28, 30, 32, 35, 38,
+ 25, 26, 28, 30, 32, 35, 38, 41,
+ 27, 28, 30, 32, 35, 38, 41, 45,
+};
+
+const int16_t ff_mpeg4_default_non_intra_matrix[64] = {
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 18, 19, 20, 21, 22, 23, 24, 25,
+ 19, 20, 21, 22, 23, 24, 26, 27,
+ 20, 21, 22, 23, 25, 26, 27, 28,
+ 21, 22, 23, 24, 26, 27, 28, 30,
+ 22, 23, 24, 26, 27, 28, 30, 31,
+ 23, 24, 25, 27, 28, 30, 31, 33,
+};
+
+const struct AVRational ff_h263_pixel_aspect[16] = {
+ { 0, 1 },
+ { 1, 1 },
+ { 12, 11 },
+ { 10, 11 },
+ { 16, 11 },
+ { 40, 33 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+};
+
+/* As per spec, studio start code search isn't the same as the old type of start code */
+static void next_start_code_studio(struct get_bits_context *gb)
+{
+ align_get_bits(gb);
+
+ while (get_bits_left(gb) >= 24 && show_bits_long(gb, 24) != 0x1) {
+ get_bits(gb, 8);
+ }
+}
+
+static int read_quant_matrix_ext(struct MpegEncContext *s, struct get_bits_context *gb)
+{
+ int i, /*j,*/ v;
+
+ if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return -1;
+ /* intra_quantiser_matrix */
+ for (i = 0; i < 64; i++) {
+ v = get_bits(gb, 8);
+ //j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ //s->intra_matrix[j] = v;
+ //s->chroma_intra_matrix[j] = v;
+ }
+ }
+
+ if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return -1;
+ /* non_intra_quantiser_matrix */
+ for (i = 0; i < 64; i++) {
+ get_bits(gb, 8);
+ }
+ }
+
+ if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return -1;
+ /* chroma_intra_quantiser_matrix */
+ for (i = 0; i < 64; i++) {
+ v = get_bits(gb, 8);
+ //j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ //s->chroma_intra_matrix[j] = v;
+ }
+ }
+
+ if (get_bits1(gb)) {
+ if (get_bits_left(gb) < 64*8)
+ return -1;
+ /* chroma_non_intra_quantiser_matrix */
+ for (i = 0; i < 64; i++) {
+ get_bits(gb, 8);
+ }
+ }
+
+ next_start_code_studio(gb);
+ return 0;
+}
+
+static void extension_and_user_data(struct MpegEncContext *s, struct get_bits_context *gb, int id)
+{
+ u32 startcode;
+ u8 extension_type;
+
+ startcode = show_bits_long(gb, 32);
+ if (startcode == USER_DATA_STARTCODE || startcode == EXT_STARTCODE) {
+ if ((id == 2 || id == 4) && startcode == EXT_STARTCODE) {
+ skip_bits_long(gb, 32);
+ extension_type = get_bits(gb, 4);
+ if (extension_type == QUANT_MATRIX_EXT_ID)
+ read_quant_matrix_ext(s, gb);
+ }
+ }
+}
+
+
+static int decode_studio_vol_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ struct MpegEncContext *s = &ctx->m;
+ int width, height;
+ int bits_per_raw_sample;
+
+ // random_accessible_vol and video_object_type_indication have already
+ // been read by the caller decode_vol_header()
+ skip_bits(gb, 4); /* video_object_layer_verid */
+ ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */
+ skip_bits(gb, 4); /* video_object_layer_shape_extension */
+ skip_bits1(gb); /* progressive_sequence */
+ if (ctx->shape != BIN_ONLY_SHAPE) {
+ ctx->rgb = get_bits1(gb); /* rgb_components */
+ s->chroma_format = get_bits(gb, 2); /* chroma_format */
+ if (!s->chroma_format) {
+ pr_err("illegal chroma format\n");
+ return -1;
+ }
+
+ bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */
+ if (bits_per_raw_sample == 10) {
+ if (ctx->rgb) {
+ ctx->pix_fmt = AV_PIX_FMT_GBRP10;
+ } else {
+ ctx->pix_fmt = s->chroma_format == CHROMA_422 ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV444P10;
+ }
+ }
+ else {
+ pr_err("MPEG-4 Studio profile bit-depth %u", bits_per_raw_sample);
+ return -1;
+ }
+ ctx->bits_per_raw_sample = bits_per_raw_sample;
+ }
+ if (ctx->shape == RECT_SHAPE) {
+ check_marker(gb, "before video_object_layer_width");
+ width = get_bits(gb, 14); /* video_object_layer_width */
+ check_marker(gb, "before video_object_layer_height");
+ height = get_bits(gb, 14); /* video_object_layer_height */
+ check_marker(gb, "after video_object_layer_height");
+
+ /* Do the same check as non-studio profile */
+ if (width && height) {
+ if (s->width && s->height &&
+ (s->width != width || s->height != height))
+ s->context_reinit = 1;
+ s->width = width;
+ s->height = height;
+ }
+ }
+ s->aspect_ratio_info = get_bits(gb, 4);
+ if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) {
+ ctx->sample_aspect_ratio.num = get_bits(gb, 8); // par_width
+ ctx->sample_aspect_ratio.den = get_bits(gb, 8); // par_height
+ } else {
+ ctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info];
+ }
+ skip_bits(gb, 4); /* frame_rate_code */
+ skip_bits(gb, 15); /* first_half_bit_rate */
+ check_marker(gb, "after first_half_bit_rate");
+ skip_bits(gb, 15); /* latter_half_bit_rate */
+ check_marker(gb, "after latter_half_bit_rate");
+ skip_bits(gb, 15); /* first_half_vbv_buffer_size */
+ check_marker(gb, "after first_half_vbv_buffer_size");
+ skip_bits(gb, 3); /* latter_half_vbv_buffer_size */
+ skip_bits(gb, 11); /* first_half_vbv_buffer_size */
+ check_marker(gb, "after first_half_vbv_buffer_size");
+ skip_bits(gb, 15); /* latter_half_vbv_occupancy */
+ check_marker(gb, "after latter_half_vbv_occupancy");
+ s->low_delay = get_bits1(gb);
+ s->mpeg_quant = get_bits1(gb); /* mpeg2_stream */
+
+ next_start_code_studio(gb);
+ extension_and_user_data(s, gb, 2);
+
+ return 0;
+}
+
+static int decode_vol_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ struct MpegEncContext *s = &ctx->m;
+ int width, height, vo_ver_id;
+
+ /* vol header */
+ skip_bits(gb, 1); /* random access */
+ s->vo_type = get_bits(gb, 8);
+
+ /* If we are in studio profile (per vo_type), check if its all consistent
+ * and if so continue pass control to decode_studio_vol_header().
+ * elIf something is inconsistent, error out
+ * else continue with (non studio) vol header decpoding.
+ */
+ if (s->vo_type == CORE_STUDIO_VO_TYPE ||
+ s->vo_type == SIMPLE_STUDIO_VO_TYPE) {
+ if (ctx->profile != FF_PROFILE_UNKNOWN && ctx->profile != FF_PROFILE_MPEG4_SIMPLE_STUDIO)
+ return -1;
+ s->studio_profile = 1;
+ ctx->profile = FF_PROFILE_MPEG4_SIMPLE_STUDIO;
+ return decode_studio_vol_header(ctx, gb);
+ } else if (s->studio_profile) {
+ return -1;
+ }
+
+ if (get_bits1(gb) != 0) { /* is_ol_id */
+ vo_ver_id = get_bits(gb, 4); /* vo_ver_id */
+ skip_bits(gb, 3); /* vo_priority */
+ } else {
+ vo_ver_id = 1;
+ }
+ s->aspect_ratio_info = get_bits(gb, 4);
+ if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) {
+ ctx->sample_aspect_ratio.num = get_bits(gb, 8); // par_width
+ ctx->sample_aspect_ratio.den = get_bits(gb, 8); // par_height
+ } else {
+ ctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info];
+ }
+
+ if ((ctx->vol_control_parameters = get_bits1(gb))) { /* vol control parameter */
+ int chroma_format = get_bits(gb, 2);
+ if (chroma_format != CHROMA_420)
+ pr_err("illegal chroma format\n");
+
+ s->low_delay = get_bits1(gb);
+ if (get_bits1(gb)) { /* vbv parameters */
+ get_bits(gb, 15); /* first_half_bitrate */
+ check_marker(gb, "after first_half_bitrate");
+ get_bits(gb, 15); /* latter_half_bitrate */
+ check_marker(gb, "after latter_half_bitrate");
+ get_bits(gb, 15); /* first_half_vbv_buffer_size */
+ check_marker(gb, "after first_half_vbv_buffer_size");
+ get_bits(gb, 3); /* latter_half_vbv_buffer_size */
+ get_bits(gb, 11); /* first_half_vbv_occupancy */
+ check_marker(gb, "after first_half_vbv_occupancy");
+ get_bits(gb, 15); /* latter_half_vbv_occupancy */
+ check_marker(gb, "after latter_half_vbv_occupancy");
+ }
+ } else {
+ /* is setting low delay flag only once the smartest thing to do?
+ * low delay detection will not be overridden. */
+ if (s->picture_number == 0) {
+ switch (s->vo_type) {
+ case SIMPLE_VO_TYPE:
+ case ADV_SIMPLE_VO_TYPE:
+ s->low_delay = 1;
+ break;
+ default:
+ s->low_delay = 0;
+ }
+ }
+ }
+
+ ctx->shape = get_bits(gb, 2); /* vol shape */
+ if (ctx->shape != RECT_SHAPE)
+ pr_err("only rectangular vol supported\n");
+ if (ctx->shape == GRAY_SHAPE && vo_ver_id != 1) {
+ pr_err("Gray shape not supported\n");
+ skip_bits(gb, 4); /* video_object_layer_shape_extension */
+ }
+
+ check_marker(gb, "before time_increment_resolution");
+
+ ctx->framerate.num = get_bits(gb, 16);
+ if (!ctx->framerate.num) {
+ pr_err("framerate==0\n");
+ return -1;
+ }
+
+ ctx->time_increment_bits = av_log2(ctx->framerate.num - 1) + 1;
+ if (ctx->time_increment_bits < 1)
+ ctx->time_increment_bits = 1;
+
+ check_marker(gb, "before fixed_vop_rate");
+
+ if (get_bits1(gb) != 0) /* fixed_vop_rate */
+ ctx->framerate.den = get_bits(gb, ctx->time_increment_bits);
+ else
+ ctx->framerate.den = 1;
+
+ //ctx->time_base = av_inv_q(av_mul_q(ctx->framerate, (AVRational){ctx->ticks_per_frame, 1}));
+
+ ctx->t_frame = 0;
+
+ if (ctx->shape != BIN_ONLY_SHAPE) {
+ if (ctx->shape == RECT_SHAPE) {
+ check_marker(gb, "before width");
+ width = get_bits(gb, 13);
+ check_marker(gb, "before height");
+ height = get_bits(gb, 13);
+ check_marker(gb, "after height");
+ if (width && height && /* they should be non zero but who knows */
+ !(s->width && s->codec_tag == AV_RL32("MP4S"))) {
+ if (s->width && s->height &&
+ (s->width != width || s->height != height))
+ s->context_reinit = 1;
+ s->width = width;
+ s->height = height;
+ }
+ }
+
+ s->progressive_sequence =
+ s->progressive_frame = get_bits1(gb) ^ 1;
+ s->interlaced_dct = 0;
+ if (!get_bits1(gb)) /* OBMC Disable */
+ pr_info("MPEG-4 OBMC not supported (very likely buggy encoder)\n");
+ if (vo_ver_id == 1)
+ ctx->vol_sprite_usage = get_bits1(gb); /* vol_sprite_usage */
+ else
+ ctx->vol_sprite_usage = get_bits(gb, 2); /* vol_sprite_usage */
+
+ if (ctx->vol_sprite_usage == STATIC_SPRITE)
+ pr_err("Static Sprites not supported\n");
+ if (ctx->vol_sprite_usage == STATIC_SPRITE ||
+ ctx->vol_sprite_usage == GMC_SPRITE) {
+ if (ctx->vol_sprite_usage == STATIC_SPRITE) {
+ skip_bits(gb, 13); // sprite_width
+ check_marker(gb, "after sprite_width");
+ skip_bits(gb, 13); // sprite_height
+ check_marker(gb, "after sprite_height");
+ skip_bits(gb, 13); // sprite_left
+ check_marker(gb, "after sprite_left");
+ skip_bits(gb, 13); // sprite_top
+ check_marker(gb, "after sprite_top");
+ }
+ ctx->num_sprite_warping_points = get_bits(gb, 6);
+ if (ctx->num_sprite_warping_points > 3) {
+ pr_err("%d sprite_warping_points\n",
+ ctx->num_sprite_warping_points);
+ ctx->num_sprite_warping_points = 0;
+ return -1;
+ }
+ s->sprite_warping_accuracy = get_bits(gb, 2);
+ ctx->sprite_brightness_change = get_bits1(gb);
+ if (ctx->vol_sprite_usage == STATIC_SPRITE)
+ skip_bits1(gb); // low_latency_sprite
+ }
+ // FIXME sadct disable bit if verid!=1 && shape not rect
+
+ if (get_bits1(gb) == 1) { /* not_8_bit */
+ s->quant_precision = get_bits(gb, 4); /* quant_precision */
+ if (get_bits(gb, 4) != 8) /* bits_per_pixel */
+ pr_err("N-bit not supported\n");
+ if (s->quant_precision != 5)
+ pr_err("quant precision %d\n", s->quant_precision);
+ if (s->quant_precision<3 || s->quant_precision>9) {
+ s->quant_precision = 5;
+ }
+ } else {
+ s->quant_precision = 5;
+ }
+
+ // FIXME a bunch of grayscale shape things
+
+ if ((s->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */
+ int i, v;
+
+ //mpeg4_load_default_matrices(s);
+
+ /* load custom intra matrix */
+ if (get_bits1(gb)) {
+ int last = 0;
+ for (i = 0; i < 64; i++) {
+ //int j;
+ if (get_bits_left(gb) < 8) {
+ pr_err("insufficient data for custom matrix\n");
+ return -1;
+ }
+ v = get_bits(gb, 8);
+ if (v == 0)
+ break;
+
+ last = v;
+ //j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ //s->intra_matrix[j] = last;
+ //s->chroma_intra_matrix[j] = last;
+ }
+
+ /* replicate last value */
+ //for (; i < 64; i++) {
+ //int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ //s->intra_matrix[j] = last;
+ //s->chroma_intra_matrix[j] = last;
+ //}
+ }
+
+ /* load custom non intra matrix */
+ if (get_bits1(gb)) {
+ int last = 0;
+ for (i = 0; i < 64; i++) {
+ //int j;
+ if (get_bits_left(gb) < 8) {
+ pr_err("insufficient data for custom matrix\n");
+ return -1;
+ }
+ v = get_bits(gb, 8);
+ if (v == 0)
+ break;
+
+ last = v;
+ //j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ //s->inter_matrix[j] = v;
+ //s->chroma_inter_matrix[j] = v;
+ }
+
+ /* replicate last value */
+ //for (; i < 64; i++) {
+ //int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ //s->inter_matrix[j] = last;
+ //s->chroma_inter_matrix[j] = last;
+ //}
+ }
+
+ // FIXME a bunch of grayscale shape things
+ }
+
+ if (vo_ver_id != 1)
+ s->quarter_sample = get_bits1(gb);
+ else
+ s->quarter_sample = 0;
+
+ if (get_bits_left(gb) < 4) {
+ pr_err("VOL Header truncated\n");
+ return -1;
+ }
+
+ if (!get_bits1(gb)) {
+ int pos = get_bits_count(gb);
+ int estimation_method = get_bits(gb, 2);
+ if (estimation_method < 2) {
+ if (!get_bits1(gb)) {
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* opaque */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* transparent */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* intra_cae */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* inter_cae */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* no_update */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* upsampling */
+ }
+ if (!get_bits1(gb)) {
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* intra_blocks */
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* inter_blocks */
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* inter4v_blocks */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* not coded blocks */
+ }
+ if (!check_marker(gb, "in complexity estimation part 1")) {
+ skip_bits_long(gb, pos - get_bits_count(gb));
+ goto no_cplx_est;
+ }
+ if (!get_bits1(gb)) {
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* dct_coeffs */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* dct_lines */
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* vlc_syms */
+ ctx->cplx_estimation_trash_i += 4 * get_bits1(gb); /* vlc_bits */
+ }
+ if (!get_bits1(gb)) {
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* apm */
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* npm */
+ ctx->cplx_estimation_trash_b += 8 * get_bits1(gb); /* interpolate_mc_q */
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* forwback_mc_q */
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* halfpel2 */
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* halfpel4 */
+ }
+ if (!check_marker(gb, "in complexity estimation part 2")) {
+ skip_bits_long(gb, pos - get_bits_count(gb));
+ goto no_cplx_est;
+ }
+ if (estimation_method == 1) {
+ ctx->cplx_estimation_trash_i += 8 * get_bits1(gb); /* sadct */
+ ctx->cplx_estimation_trash_p += 8 * get_bits1(gb); /* qpel */
+ }
+ } else
+ pr_err("Invalid Complexity estimation method %d\n",
+ estimation_method);
+ } else {
+
+no_cplx_est:
+ ctx->cplx_estimation_trash_i =
+ ctx->cplx_estimation_trash_p =
+ ctx->cplx_estimation_trash_b = 0;
+ }
+
+ ctx->resync_marker = !get_bits1(gb); /* resync_marker_disabled */
+
+ s->data_partitioning = get_bits1(gb);
+ if (s->data_partitioning)
+ ctx->rvlc = get_bits1(gb);
+
+ if (vo_ver_id != 1) {
+ ctx->new_pred = get_bits1(gb);
+ if (ctx->new_pred) {
+ pr_err("new pred not supported\n");
+ skip_bits(gb, 2); /* requested upstream message type */
+ skip_bits1(gb); /* newpred segment type */
+ }
+ if (get_bits1(gb)) // reduced_res_vop
+ pr_err("reduced resolution VOP not supported\n");
+ } else {
+ ctx->new_pred = 0;
+ }
+
+ ctx->scalability = get_bits1(gb);
+
+ if (ctx->scalability) {
+ struct get_bits_context bak = *gb;
+ int h_sampling_factor_n;
+ int h_sampling_factor_m;
+ int v_sampling_factor_n;
+ int v_sampling_factor_m;
+
+ skip_bits1(gb); // hierarchy_type
+ skip_bits(gb, 4); /* ref_layer_id */
+ skip_bits1(gb); /* ref_layer_sampling_dir */
+ h_sampling_factor_n = get_bits(gb, 5);
+ h_sampling_factor_m = get_bits(gb, 5);
+ v_sampling_factor_n = get_bits(gb, 5);
+ v_sampling_factor_m = get_bits(gb, 5);
+ ctx->enhancement_type = get_bits1(gb);
+
+ if (h_sampling_factor_n == 0 || h_sampling_factor_m == 0 ||
+ v_sampling_factor_n == 0 || v_sampling_factor_m == 0) {
+ /* illegal scalability header (VERY broken encoder),
+ * trying to workaround */
+ ctx->scalability = 0;
+ *gb = bak;
+ } else
+ pr_err("scalability not supported\n");
+
+ // bin shape stuff FIXME
+ }
+ }
+
+ if (1) {
+ pr_info("tb %d/%d, tincrbits:%d, qp_prec:%d, ps:%d, low_delay:%d %s%s%s%s\n",
+ ctx->framerate.den, ctx->framerate.num,
+ ctx->time_increment_bits,
+ s->quant_precision,
+ s->progressive_sequence,
+ s->low_delay,
+ ctx->scalability ? "scalability " :"" , s->quarter_sample ? "qpel " : "",
+ s->data_partitioning ? "partition " : "", ctx->rvlc ? "rvlc " : ""
+ );
+ }
+
+ return 0;
+}
+
+
+/**
+ * Decode the user data stuff in the header.
+ * Also initializes divx/xvid/lavc_version/build.
+ */
+static int decode_user_data(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ struct MpegEncContext *s = &ctx->m;
+ char buf[256];
+ int i;
+ int e;
+ int ver = 0, build = 0, ver2 = 0, ver3 = 0;
+ char last;
+
+ for (i = 0; i < 255 && get_bits_count(gb) < gb->size_in_bits; i++) {
+ if (show_bits(gb, 23) == 0)
+ break;
+ buf[i] = get_bits(gb, 8);
+ }
+ buf[i] = 0;
+
+ /* divx detection */
+ e = sscanf(buf, "DivX%dBuild%d%c", &ver, &build, &last);
+ if (e < 2)
+ e = sscanf(buf, "DivX%db%d%c", &ver, &build, &last);
+ if (e >= 2) {
+ ctx->divx_version = ver;
+ ctx->divx_build = build;
+ s->divx_packed = e == 3 && last == 'p';
+ }
+
+ /* libavcodec detection */
+ e = sscanf(buf, "FFmpe%*[^b]b%d", &build) + 3;
+ if (e != 4)
+ e = sscanf(buf, "FFmpeg v%d.%d.%d / libavcodec build: %d", &ver, &ver2, &ver3, &build);
+ if (e != 4) {
+ e = sscanf(buf, "Lavc%d.%d.%d", &ver, &ver2, &ver3) + 1;
+ if (e > 1) {
+ if (ver > 0xFFU || ver2 > 0xFFU || ver3 > 0xFFU) {
+ pr_info("Unknown Lavc version string encountered, %d.%d.%d; "
+ "clamping sub-version values to 8-bits.\n",
+ ver, ver2, ver3);
+ }
+ build = ((ver & 0xFF) << 16) + ((ver2 & 0xFF) << 8) + (ver3 & 0xFF);
+ }
+ }
+ if (e != 4) {
+ if (strcmp(buf, "ffmpeg") == 0)
+ ctx->lavc_build = 4600;
+ }
+ if (e == 4)
+ ctx->lavc_build = build;
+
+ /* Xvid detection */
+ e = sscanf(buf, "XviD%d", &build);
+ if (e == 1)
+ ctx->xvid_build = build;
+
+ return 0;
+}
+
+
+static int mpeg4_decode_gop_header(struct MpegEncContext *s, struct get_bits_context *gb)
+{
+ int hours, minutes, seconds;
+
+ if (!show_bits(gb, 23)) {
+ pr_err("GOP header invalid\n");
+ return -1;
+ }
+
+ hours = get_bits(gb, 5);
+ minutes = get_bits(gb, 6);
+ check_marker(gb, "in gop_header");
+ seconds = get_bits(gb, 6);
+
+ s->time_base = seconds + 60*(minutes + 60*hours);
+
+ skip_bits1(gb);
+ skip_bits1(gb);
+
+ return 0;
+}
+
+
+static int mpeg4_decode_profile_level(struct MpegEncContext *s, struct get_bits_context *gb, int *profile, int *level)
+{
+
+ *profile = get_bits(gb, 4);
+ *level = get_bits(gb, 4);
+
+ // for Simple profile, level 0
+ if (*profile == 0 && *level == 8) {
+ *level = 0;
+ }
+
+ return 0;
+}
+
+
+static int decode_studiovisualobject(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ struct MpegEncContext *s = &ctx->m;
+ int visual_object_type;
+
+ skip_bits(gb, 4); /* visual_object_verid */
+ visual_object_type = get_bits(gb, 4);
+ if (visual_object_type != VOT_VIDEO_ID) {
+ pr_err("VO type %u", visual_object_type);
+ return -1;
+ }
+
+ next_start_code_studio(gb);
+ extension_and_user_data(s, gb, 1);
+
+ return 0;
+}
+
+
+static int mpeg4_decode_visual_object(struct MpegEncContext *s, struct get_bits_context *gb)
+{
+ int visual_object_type;
+ int is_visual_object_identifier = get_bits1(gb);
+
+ if (is_visual_object_identifier) {
+ skip_bits(gb, 4+3);
+ }
+ visual_object_type = get_bits(gb, 4);
+
+ if (visual_object_type == VOT_VIDEO_ID ||
+ visual_object_type == VOT_STILL_TEXTURE_ID) {
+ int video_signal_type = get_bits1(gb);
+ if (video_signal_type) {
+ int video_range, color_description;
+ skip_bits(gb, 3); // video_format
+ video_range = get_bits1(gb);
+ color_description = get_bits1(gb);
+
+ s->ctx->color_range = video_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
+
+ if (color_description) {
+ s->ctx->color_primaries = get_bits(gb, 8);
+ s->ctx->color_trc = get_bits(gb, 8);
+ s->ctx->colorspace = get_bits(gb, 8);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void decode_smpte_tc(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ skip_bits(gb, 16); /* Time_code[63..48] */
+ check_marker(gb, "after Time_code[63..48]");
+ skip_bits(gb, 16); /* Time_code[47..32] */
+ check_marker(gb, "after Time_code[47..32]");
+ skip_bits(gb, 16); /* Time_code[31..16] */
+ check_marker(gb, "after Time_code[31..16]");
+ skip_bits(gb, 16); /* Time_code[15..0] */
+ check_marker(gb, "after Time_code[15..0]");
+ skip_bits(gb, 4); /* reserved_bits */
+}
+
+static void reset_studio_dc_predictors(struct MpegEncContext *s)
+{
+ /* Reset DC Predictors */
+ s->last_dc[0] =
+ s->last_dc[1] =
+ s->last_dc[2] = 1 << (s->ctx->bits_per_raw_sample + s->dct_precision + s->intra_dc_precision - 1);
+}
+
+/**
+ * Decode the next studio vop header.
+ * @return <0 if something went wrong
+ */
+static int decode_studio_vop_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ struct MpegEncContext *s = &ctx->m;
+
+ if (get_bits_left(gb) <= 32)
+ return 0;
+
+ //s->decode_mb = mpeg4_decode_studio_mb;
+
+ decode_smpte_tc(ctx, gb);
+
+ skip_bits(gb, 10); /* temporal_reference */
+ skip_bits(gb, 2); /* vop_structure */
+ s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* vop_coding_type */
+ if (get_bits1(gb)) { /* vop_coded */
+ skip_bits1(gb); /* top_field_first */
+ skip_bits1(gb); /* repeat_first_field */
+ s->progressive_frame = get_bits1(gb) ^ 1; /* progressive_frame */
+ }
+
+ if (s->pict_type == AV_PICTURE_TYPE_I) {
+ if (get_bits1(gb))
+ reset_studio_dc_predictors(s);
+ }
+
+ if (ctx->shape != BIN_ONLY_SHAPE) {
+ s->alternate_scan = get_bits1(gb);
+ s->frame_pred_frame_dct = get_bits1(gb);
+ s->dct_precision = get_bits(gb, 2);
+ s->intra_dc_precision = get_bits(gb, 2);
+ s->q_scale_type = get_bits1(gb);
+ }
+
+ //if (s->alternate_scan) { }
+
+ //mpeg4_load_default_matrices(s);
+
+ next_start_code_studio(gb);
+ extension_and_user_data(s, gb, 4);
+
+ return 0;
+}
+
+static int decode_new_pred(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ int len = FFMIN(ctx->time_increment_bits + 3, 15);
+
+ get_bits(gb, len);
+ if (get_bits1(gb))
+ get_bits(gb, len);
+ check_marker(gb, "after new_pred");
+
+ return 0;
+}
+
+static int decode_vop_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ struct MpegEncContext *s = &ctx->m;
+ int time_incr, time_increment;
+ int64_t pts;
+
+ s->mcsel = 0;
+ s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* pict type: I = 0 , P = 1 */
+ if (s->pict_type == AV_PICTURE_TYPE_B && s->low_delay &&
+ ctx->vol_control_parameters == 0) {
+ pr_err("low_delay flag set incorrectly, clearing it\n");
+ s->low_delay = 0;
+ }
+
+ s->partitioned_frame = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B;
+ /*if (s->partitioned_frame)
+ s->decode_mb = mpeg4_decode_partitioned_mb;
+ else
+ s->decode_mb = mpeg4_decode_mb;*/
+
+ time_incr = 0;
+ while (get_bits1(gb) != 0)
+ time_incr++;
+
+ check_marker(gb, "before time_increment");
+
+ if (ctx->time_increment_bits == 0 ||
+ !(show_bits(gb, ctx->time_increment_bits + 1) & 1)) {
+ pr_info("time_increment_bits %d is invalid in relation to the current bitstream, this is likely caused by a missing VOL header\n", ctx->time_increment_bits);
+
+ for (ctx->time_increment_bits = 1;
+ ctx->time_increment_bits < 16;
+ ctx->time_increment_bits++) {
+ if (s->pict_type == AV_PICTURE_TYPE_P ||
+ (s->pict_type == AV_PICTURE_TYPE_S &&
+ ctx->vol_sprite_usage == GMC_SPRITE)) {
+ if ((show_bits(gb, ctx->time_increment_bits + 6) & 0x37) == 0x30)
+ break;
+ } else if ((show_bits(gb, ctx->time_increment_bits + 5) & 0x1F) == 0x18)
+ break;
+ }
+
+ pr_info("time_increment_bits set to %d bits, based on bitstream analysis\n", ctx->time_increment_bits);
+ if (ctx->framerate.num && 4*ctx->framerate.num < 1<<ctx->time_increment_bits) {
+ ctx->framerate.num = 1<<ctx->time_increment_bits;
+ //ctx->time_base = av_inv_q(av_mul_q(ctx->framerate, (AVRational){ctx->ticks_per_frame, 1}));
+ }
+ }
+
+ if (IS_3IV1)
+ time_increment = get_bits1(gb); // FIXME investigate further
+ else
+ time_increment = get_bits(gb, ctx->time_increment_bits);
+
+ if (s->pict_type != AV_PICTURE_TYPE_B) {
+ s->last_time_base = s->time_base;
+ s->time_base += time_incr;
+ s->time = s->time_base * (int64_t)ctx->framerate.num + time_increment;
+ //if (s->workaround_bugs & FF_BUG_UMP4) { }
+ s->pp_time = s->time - s->last_non_b_time;
+ s->last_non_b_time = s->time;
+ } else {
+ s->time = (s->last_time_base + time_incr) * (int64_t)ctx->framerate.num + time_increment;
+ s->pb_time = s->pp_time - (s->last_non_b_time - s->time);
+ if (s->pp_time <= s->pb_time ||
+ s->pp_time <= s->pp_time - s->pb_time ||
+ s->pp_time <= 0) {
+ /* messed up order, maybe after seeking? skipping current B-frame */
+ return FRAME_SKIPPED;
+ }
+ //ff_mpeg4_init_direct_mv(s);
+
+ if (ctx->t_frame == 0)
+ ctx->t_frame = s->pb_time;
+ if (ctx->t_frame == 0)
+ ctx->t_frame = 1; // 1/0 protection
+ s->pp_field_time = (ROUNDED_DIV(s->last_non_b_time, ctx->t_frame) -
+ ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2;
+ s->pb_field_time = (ROUNDED_DIV(s->time, ctx->t_frame) -
+ ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2;
+ if (s->pp_field_time <= s->pb_field_time || s->pb_field_time <= 1) {
+ s->pb_field_time = 2;
+ s->pp_field_time = 4;
+ if (!s->progressive_sequence)
+ return FRAME_SKIPPED;
+ }
+ }
+
+ if (ctx->framerate.den)
+ pts = ROUNDED_DIV(s->time, ctx->framerate.den);
+ else
+ pts = AV_NOPTS_VALUE;
+ pr_info("MPEG4 PTS: %lld\n", pts);
+
+ check_marker(gb, "before vop_coded");
+
+ /* vop coded */
+ if (get_bits1(gb) != 1) {
+ if (1)
+ pr_err("vop not coded\n");
+ return FRAME_SKIPPED;
+ }
+ if (ctx->new_pred)
+ decode_new_pred(ctx, gb);
+
+ if (ctx->shape != BIN_ONLY_SHAPE &&
+ (s->pict_type == AV_PICTURE_TYPE_P ||
+ (s->pict_type == AV_PICTURE_TYPE_S &&
+ ctx->vol_sprite_usage == GMC_SPRITE))) {
+ /* rounding type for motion estimation */
+ s->no_rounding = get_bits1(gb);
+ } else {
+ s->no_rounding = 0;
+ }
+ // FIXME reduced res stuff
+
+ if (ctx->shape != RECT_SHAPE) {
+ if (ctx->vol_sprite_usage != 1 || s->pict_type != AV_PICTURE_TYPE_I) {
+ skip_bits(gb, 13); /* width */
+ check_marker(gb, "after width");
+ skip_bits(gb, 13); /* height */
+ check_marker(gb, "after height");
+ skip_bits(gb, 13); /* hor_spat_ref */
+ check_marker(gb, "after hor_spat_ref");
+ skip_bits(gb, 13); /* ver_spat_ref */
+ }
+ skip_bits1(gb); /* change_CR_disable */
+
+ if (get_bits1(gb) != 0)
+ skip_bits(gb, 8); /* constant_alpha_value */
+ }
+
+ // FIXME complexity estimation stuff
+
+ if (ctx->shape != BIN_ONLY_SHAPE) {
+ skip_bits_long(gb, ctx->cplx_estimation_trash_i);
+ if (s->pict_type != AV_PICTURE_TYPE_I)
+ skip_bits_long(gb, ctx->cplx_estimation_trash_p);
+ if (s->pict_type == AV_PICTURE_TYPE_B)
+ skip_bits_long(gb, ctx->cplx_estimation_trash_b);
+
+ if (get_bits_left(gb) < 3) {
+ pr_err("Header truncated\n");
+ return -1;
+ }
+ ctx->intra_dc_threshold = ff_mpeg4_dc_threshold[get_bits(gb, 3)];
+ if (!s->progressive_sequence) {
+ s->top_field_first = get_bits1(gb);
+ s->alternate_scan = get_bits1(gb);
+ } else
+ s->alternate_scan = 0;
+ }
+
+ /*if (s->alternate_scan) { } */
+
+ if (s->pict_type == AV_PICTURE_TYPE_S) {
+ if((ctx->vol_sprite_usage == STATIC_SPRITE ||
+ ctx->vol_sprite_usage == GMC_SPRITE)) {
+ //if (mpeg4_decode_sprite_trajectory(ctx, gb) < 0)
+ //return -1;
+ if (ctx->sprite_brightness_change)
+ pr_err("sprite_brightness_change not supported\n");
+ if (ctx->vol_sprite_usage == STATIC_SPRITE)
+ pr_err("static sprite not supported\n");
+ } else {
+ memset(s->sprite_offset, 0, sizeof(s->sprite_offset));
+ memset(s->sprite_delta, 0, sizeof(s->sprite_delta));
+ }
+ }
+
+ if (ctx->shape != BIN_ONLY_SHAPE) {
+ s->chroma_qscale = s->qscale = get_bits(gb, s->quant_precision);
+ if (s->qscale == 0) {
+ pr_err("Error, header damaged or not MPEG-4 header (qscale=0)\n");
+ return -1; // makes no sense to continue, as there is nothing left from the image then
+ }
+
+ if (s->pict_type != AV_PICTURE_TYPE_I) {
+ s->f_code = get_bits(gb, 3); /* fcode_for */
+ if (s->f_code == 0) {
+ pr_err("Error, header damaged or not MPEG-4 header (f_code=0)\n");
+ s->f_code = 1;
+ return -1; // makes no sense to continue, as there is nothing left from the image then
+ }
+ } else
+ s->f_code = 1;
+
+ if (s->pict_type == AV_PICTURE_TYPE_B) {
+ s->b_code = get_bits(gb, 3);
+ if (s->b_code == 0) {
+ pr_err("Error, header damaged or not MPEG4 header (b_code=0)\n");
+ s->b_code=1;
+ return -1; // makes no sense to continue, as the MV decoding will break very quickly
+ }
+ } else
+ s->b_code = 1;
+
+ if (1) {
+ pr_info("qp:%d fc:%d,%d %s size:%d pro:%d alt:%d top:%d %spel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%ld tincr:%d\n",
+ s->qscale, s->f_code, s->b_code,
+ s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")),
+ gb->size_in_bits,s->progressive_sequence, s->alternate_scan,
+ s->top_field_first, s->quarter_sample ? "q" : "h",
+ s->data_partitioning, ctx->resync_marker,
+ ctx->num_sprite_warping_points, s->sprite_warping_accuracy,
+ 1 - s->no_rounding, s->vo_type,
+ ctx->vol_control_parameters ? " VOLC" : " ", ctx->intra_dc_threshold,
+ ctx->cplx_estimation_trash_i, ctx->cplx_estimation_trash_p,
+ ctx->cplx_estimation_trash_b,
+ s->time,
+ time_increment
+ );
+ }
+
+ if (!ctx->scalability) {
+ if (ctx->shape != RECT_SHAPE && s->pict_type != AV_PICTURE_TYPE_I)
+ skip_bits1(gb); // vop shape coding type
+ } else {
+ if (ctx->enhancement_type) {
+ int load_backward_shape = get_bits1(gb);
+ if (load_backward_shape)
+ pr_err("load backward shape isn't supported\n");
+ }
+ skip_bits(gb, 2); // ref_select_code
+ }
+ }
+ /* detect buggy encoders which don't set the low_delay flag
+ * (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames
+ * easily (although it's buggy too) */
+ if (s->vo_type == 0 && ctx->vol_control_parameters == 0 &&
+ ctx->divx_version == -1 && s->picture_number == 0) {
+ pr_info("looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag\n");
+ s->low_delay = 1;
+ }
+
+ s->picture_number++; // better than pic number==0 always ;)
+
+ // FIXME add short header support
+ //s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table;
+ //s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table;
+
+ return 0;
+}
+
+/**
+ * Decode MPEG-4 headers.
+ * @return <0 if no VOP found (or a damaged one)
+ * FRAME_SKIPPED if a not coded VOP is found
+ * 0 if a VOP is found
+ */
+int ff_mpeg4_decode_picture_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+ struct MpegEncContext *s = &ctx->m;
+
+ unsigned startcode, v;
+ int ret;
+ int vol = 0;
+ int bits_per_raw_sample = 0;
+
+ s->ctx = ctx;
+
+ /* search next start code */
+ align_get_bits(gb);
+
+ // If we have not switched to studio profile than we also did not switch bps
+ // that means something else (like a previous instance) outside set bps which
+ // would be inconsistant with the currect state, thus reset it
+ if (!s->studio_profile && bits_per_raw_sample != 8)
+ bits_per_raw_sample = 0;
+
+ if (show_bits(gb, 24) == 0x575630) {
+ skip_bits(gb, 24);
+ if (get_bits(gb, 8) == 0xF0)
+ goto end;
+ }
+
+ startcode = 0xff;
+ for (;;) {
+ if (get_bits_count(gb) >= gb->size_in_bits) {
+ if (gb->size_in_bits == 8) {
+ pr_info("frame skip %d\n", gb->size_in_bits);
+ return FRAME_SKIPPED; // divx bug
+ } else
+ return -1; // end of stream
+ }
+
+ /* use the bits after the test */
+ v = get_bits(gb, 8);
+ startcode = ((startcode << 8) | v) & 0xffffffff;
+
+ if ((startcode & 0xFFFFFF00) != 0x100)
+ continue; // no startcode
+
+ if (1) { //debug
+ pr_info("startcode: %3X \n", startcode);
+ if (startcode <= 0x11F)
+ pr_info("Video Object Start\n");
+ else if (startcode <= 0x12F)
+ pr_info("Video Object Layer Start\n");
+ else if (startcode <= 0x13F)
+ pr_info("Reserved\n");
+ else if (startcode <= 0x15F)
+ pr_info("FGS bp start\n");
+ else if (startcode <= 0x1AF)
+ pr_info("Reserved\n");
+ else if (startcode == 0x1B0)
+ pr_info("Visual Object Seq Start\n");
+ else if (startcode == 0x1B1)
+ pr_info("Visual Object Seq End\n");
+ else if (startcode == 0x1B2)
+ pr_info("User Data\n");
+ else if (startcode == 0x1B3)
+ pr_info("Group of VOP start\n");
+ else if (startcode == 0x1B4)
+ pr_info("Video Session Error\n");
+ else if (startcode == 0x1B5)
+ pr_info("Visual Object Start\n");
+ else if (startcode == 0x1B6)
+ pr_info("Video Object Plane start\n");
+ else if (startcode == 0x1B7)
+ pr_info("slice start\n");
+ else if (startcode == 0x1B8)
+ pr_info("extension start\n");
+ else if (startcode == 0x1B9)
+ pr_info("fgs start\n");
+ else if (startcode == 0x1BA)
+ pr_info("FBA Object start\n");
+ else if (startcode == 0x1BB)
+ pr_info("FBA Object Plane start\n");
+ else if (startcode == 0x1BC)
+ pr_info("Mesh Object start\n");
+ else if (startcode == 0x1BD)
+ pr_info("Mesh Object Plane start\n");
+ else if (startcode == 0x1BE)
+ pr_info("Still Texture Object start\n");
+ else if (startcode == 0x1BF)
+ pr_info("Texture Spatial Layer start\n");
+ else if (startcode == 0x1C0)
+ pr_info("Texture SNR Layer start\n");
+ else if (startcode == 0x1C1)
+ pr_info("Texture Tile start\n");
+ else if (startcode == 0x1C2)
+ pr_info("Texture Shape Layer start\n");
+ else if (startcode == 0x1C3)
+ pr_info("stuffing start\n");
+ else if (startcode <= 0x1C5)
+ pr_info("reserved\n");
+ else if (startcode <= 0x1FF)
+ pr_info("System start\n");
+ }
+
+ if (startcode >= 0x120 && startcode <= 0x12F) {
+ if (vol) {
+ pr_err("Ignoring multiple VOL headers\n");
+ continue;
+ }
+ vol++;
+ if ((ret = decode_vol_header(ctx, gb)) < 0)
+ return ret;
+ } else if (startcode == USER_DATA_STARTCODE) {
+ decode_user_data(ctx, gb);
+ } else if (startcode == GOP_STARTCODE) {
+ mpeg4_decode_gop_header(s, gb);
+ } else if (startcode == VOS_STARTCODE) {
+ int profile, level;
+ mpeg4_decode_profile_level(s, gb, &profile, &level);
+ if (profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO &&
+ (level > 0 && level < 9)) {
+ s->studio_profile = 1;
+ next_start_code_studio(gb);
+ extension_and_user_data(s, gb, 0);
+ } else if (s->studio_profile) {
+ pr_err("Mixes studio and non studio profile\n");
+ return -1;
+ }
+ ctx->profile = profile;
+ ctx->level = level;
+ } else if (startcode == VISUAL_OBJ_STARTCODE) {
+ if (s->studio_profile) {
+ if ((ret = decode_studiovisualobject(ctx, gb)) < 0)
+ return ret;
+ } else
+ mpeg4_decode_visual_object(s, gb);
+ } else if (startcode == VOP_STARTCODE) {
+ break;
+ }
+
+ align_get_bits(gb);
+ startcode = 0xff;
+ }
+
+end:
+ if (s->studio_profile) {
+ if (!bits_per_raw_sample) {
+ pr_err("Missing VOL header\n");
+ return -1;
+ }
+ return decode_studio_vop_header(ctx, gb);
+ } else
+ return decode_vop_header(ctx, gb);
+}
+
+int mpeg4_decode_extradata_ps(u8 *buf, int size, struct mpeg4_param_sets *ps)
+{
+ int ret = 0;
+ struct get_bits_context gb;
+
+ ps->head_parsed = false;
+
+ init_get_bits8(&gb, buf, size);
+
+ ret = ff_mpeg4_decode_picture_header(&ps->dec_ps, &gb);
+ if (ret < -1) {
+ pr_err("Failed to parse extradata\n");
+ return ret;
+ }
+
+ if (ps->dec_ps.m.width && ps->dec_ps.m.height)
+ ps->head_parsed = true;
+
+ return 0;
+}
+