From bb5d3a9b20b3d51b9c07346ec43504cac5016c67 Mon Sep 17 00:00:00 2001 From: Nanxin Qin Date: Thu, 23 Jul 2020 17:17:49 +0800 Subject: [PATCH] v4l: fixed the issue of vp9 can't playback on linux. [1/1] PD#SWPL-29656 Problem: has wrong of the private head data of vp9 cause playback failed, becuase usually the head process on the omx but if on the linux the v4l codec driver need to handle it. Solution: restore the function of use supperframe split filter make sure add head data process normal if work on linux. Verify: u212 Change-Id: Ie3cf4858c2c4160b9ca551e39faca5a5c127fe19 Signed-off-by: Nanxin Qin --- drivers/amvdec_ports/decoder/aml_vp9_parser.h | 2 - drivers/amvdec_ports/decoder/vdec_vp9_if.c | 88 +++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/drivers/amvdec_ports/decoder/aml_vp9_parser.h b/drivers/amvdec_ports/decoder/aml_vp9_parser.h index 9f7dfd9..ddeddec 100644 --- a/drivers/amvdec_ports/decoder/aml_vp9_parser.h +++ b/drivers/amvdec_ports/decoder/aml_vp9_parser.h @@ -174,12 +174,10 @@ struct vp9_param_sets { struct VP9Context ctx; }; - #ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER int vp9_superframe_split_filter(struct vp9_superframe_split *s); int vp9_decode_extradata_ps(u8 *data, int size, struct vp9_param_sets *ps); #else -inline int vp9_superframe_split_filter(struct vp9_superframe_split *s) { return -1;} inline int vp9_decode_extradata_ps(u8 *data, int size, struct vp9_param_sets *ps) { return -1; } #endif diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c index ec9ce64..be08628 100644 --- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c +++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c @@ -669,6 +669,94 @@ static void add_prefix_data(struct vp9_superframe_split *s, *out_size = length; } +#ifndef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER +static int vp9_superframe_split_filter(struct vp9_superframe_split *s) +{ + int i, j, ret, marker; + bool is_superframe = false; + int *prefix = (int *)s->data; + + if (!s->data) + return -1; + +#define AML_PREFIX ('V' << 24 | 'L' << 16 | 'M' << 8 | 'A') + if (prefix[3] == AML_PREFIX) { + s->prefix_size = 16; + /*pr_info("the frame data has beed added header\n");*/ + } + + marker = s->data[s->data_size - 1]; + if ((marker & 0xe0) == 0xc0) { + int length_size = 1 + ((marker >> 3) & 0x3); + int nb_frames = 1 + (marker & 0x7); + int idx_size = 2 + nb_frames * length_size; + + if (s->data_size >= idx_size && + s->data[s->data_size - idx_size] == marker) { + s64 total_size = 0; + int idx = s->data_size + 1 - idx_size; + + for (i = 0; i < nb_frames; i++) { + int frame_size = 0; + for (j = 0; j < length_size; j++) + frame_size |= s->data[idx++] << (j * 8); + + total_size += frame_size; + if (frame_size < 0 || + total_size > s->data_size - idx_size) { + v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid frame size in a sframe: %d\n", + frame_size); + ret = -EINVAL; + goto fail; + } + s->sizes[i] = frame_size; + } + + s->nb_frames = nb_frames; + s->size = total_size; + s->next_frame = 0; + s->next_frame_offset = 0; + is_superframe = true; + } + }else { + s->nb_frames = 1; + s->sizes[0] = s->data_size; + s->size = s->data_size; + } + + /*pr_info("sframe: %d, frames: %d, IN: %x, OUT: %x\n", + is_superframe, s->nb_frames, + s->data_size, s->size);*/ + + /* parse uncompressed header. */ + if (is_superframe) { + /* bitstream profile. */ + /* frame type. (intra or inter) */ + /* colorspace descriptor */ + /* ... */ + + v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "the frame is a superframe.\n"); + } + + /*pr_err("in: %x, %d, out: %x, sizes %d,%d,%d,%d,%d,%d,%d,%d\n", + s->data_size, + s->nb_frames, + s->size, + s->sizes[0], + s->sizes[1], + s->sizes[2], + s->sizes[3], + s->sizes[4], + s->sizes[5], + s->sizes[6], + s->sizes[7]);*/ + + return 0; +fail: + return ret; +} +#endif + static void trigger_decoder(struct aml_vdec_adapt *vdec) { int i, ret; -- 2.20.1