v4l: fixed the issue of vp9 can't playback on linux. [1/1]
authorNanxin Qin <nanxin.qin@amlogic.com>
Thu, 23 Jul 2020 09:17:49 +0000 (17:17 +0800)
committerNanxin Qin <nanxin.qin@amlogic.com>
Thu, 23 Jul 2020 09:42:33 +0000 (02:42 -0700)
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 <nanxin.qin@amlogic.com>
drivers/amvdec_ports/decoder/aml_vp9_parser.h
drivers/amvdec_ports/decoder/vdec_vp9_if.c

index 9f7dfd98620bc3d64ca5c23a018309edacb7f9cd..ddeddec3025e924591a537c2d3486134f891c5c7 100644 (file)
@@ -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
 
index ec9ce64ce4b5e5f765f7e6549caa095622a3bb43..be08628e15a022e1b6d9bfa792124bafa0b5f7fe 100644 (file)
@@ -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;