diff mbox series

[FFmpeg-devel,vaapi-cavs,2/7] cavs: skip bits between pic header and slc header

Message ID 20240121141846.4077778-2-jianfeng.zheng@mthreads.com
State New
Headers show
Series [FFmpeg-devel,vaapi-cavs,1/7] cavs: add cavs profile defs | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Jianfeng Zheng Jan. 21, 2024, 2:18 p.m. UTC
Signed-off-by: jianfeng.zheng <jianfeng.zheng@mthreads.com>
---
 libavcodec/cavs.h    |  2 +
 libavcodec/cavsdec.c | 87 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 89 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/cavs.h b/libavcodec/cavs.h
index 244c322b35..ad49abff92 100644
--- a/libavcodec/cavs.h
+++ b/libavcodec/cavs.h
@@ -39,8 +39,10 @@ 
 #define EXT_START_CODE          0x000001b5
 #define USER_START_CODE         0x000001b2
 #define CAVS_START_CODE         0x000001b0
+#define VIDEO_SEQ_END_CODE      0x000001b1
 #define PIC_I_START_CODE        0x000001b3
 #define PIC_PB_START_CODE       0x000001b6
+#define VIDEO_EDIT_CODE         0x000001b7
 
 #define A_AVAIL                          1
 #define B_AVAIL                          2
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index b356da0b04..9742bd1011 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -954,6 +954,80 @@  static inline int decode_slice_header(AVSContext *h, GetBitContext *gb)
     return 0;
 }
 
+/**
+ * skip stuffing bits before next start code "0x000001"
+ * @return '0' no stuffing bits placed at h->gb being skip, else '1'.
+ */
+static inline int skip_stuffing_bits(AVSContext *h)
+{
+    GetBitContext gb0 = h->gb;
+    GetBitContext *gb = &h->gb;
+    const uint8_t *start;
+    const uint8_t *ptr;
+    const uint8_t *end;
+    int align;
+    int stuffing_zeros;
+
+    /**
+     * According to spec, there should be one stuffing_bit '1' and
+     * 0~7 stuffing_bit '0'. But seems not all the stream follow
+     * "next_start_code()" strictly.
+     */
+    align = (-get_bits_count(gb)) & 7;
+    if (align == 0 && show_bits_long(gb, 8) == 0x80) {
+        skip_bits_long(gb, 8);
+    }
+
+    /**
+     *  skip leading zero bytes before 0x 00 00 01 stc
+     */
+    ptr = start = align_get_bits(gb);
+    end = gb->buffer_end;
+    while (ptr < end && *ptr == 0)
+        ptr++;
+
+    if ((ptr >= end) || (*ptr == 1 && ptr - start >= 2)) {
+        stuffing_zeros = (ptr >= end ? end - start : ptr - start - 2);
+        if (stuffing_zeros > 0)
+            av_log(h->avctx, AV_LOG_DEBUG, "Skip 0x%x stuffing zeros @0x%x.\n",
+                    stuffing_zeros, (int)(start - gb->buffer));
+        skip_bits_long(gb, stuffing_zeros * 8);
+        return 1;
+    } else {
+        av_log(h->avctx, AV_LOG_DEBUG, "No next_start_code() found @0x%x.\n",
+                (int)(start - gb->buffer));
+        goto restore_get_bits;
+    }
+
+restore_get_bits:
+    h->gb = gb0;
+    return 0;
+}
+
+static inline int skip_extension_and_user_data(AVSContext *h)
+{
+    int stc = -1;
+    const uint8_t *start = align_get_bits(&h->gb);
+    const uint8_t *end = h->gb.buffer_end;
+    const uint8_t *ptr, *next;
+
+    for (ptr = start; ptr + 4 < end; ptr = next) {
+        stc = show_bits_long(&h->gb, 32);
+        if (stc != EXT_START_CODE && stc != USER_START_CODE) {
+            break;
+        }
+        next = avpriv_find_start_code(ptr + 4, end, &stc);
+        if (next < end) {
+            next -= 4;
+        }
+        skip_bits(&h->gb, (next - ptr) * 8);
+        av_log(h->avctx, AV_LOG_DEBUG, "skip %d byte ext/user data\n",
+                (int)(next - ptr));
+    }
+
+    return ptr > start;
+}
+
 static inline int check_for_slice(AVSContext *h)
 {
     GetBitContext *gb = &h->gb;
@@ -1019,6 +1093,8 @@  static int decode_pic(AVSContext *h)
             h->stream_revision = 1;
         if (h->stream_revision > 0)
             skip_bits(&h->gb, 1); //marker_bit
+
+        av_log(h->avctx, AV_LOG_DEBUG, "stream_revision: %d\n", h->stream_revision);
     }
 
     if (get_bits_left(&h->gb) < 23)
@@ -1096,6 +1172,11 @@  static int decode_pic(AVSContext *h)
         h->alpha_offset = h->beta_offset  = 0;
     }
 
+    if (h->stream_revision > 0) {
+        skip_stuffing_bits(h);
+        skip_extension_and_user_data(h);
+    }
+
     ret = 0;
     if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
         do {
@@ -1309,6 +1390,12 @@  static int cavs_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
         case USER_START_CODE:
             //mpeg_decode_user_data(avctx, buf_ptr, input_size);
             break;
+        case VIDEO_EDIT_CODE:
+            av_log(h->avctx, AV_LOG_WARNING, "Skip video_edit_code\n");
+            break;
+        case VIDEO_SEQ_END_CODE:
+            av_log(h->avctx, AV_LOG_WARNING, "Skip video_sequence_end_code\n");
+            break;
         default:
             if (stc <= SLICE_MAX_START_CODE) {
                 init_get_bits(&h->gb, buf_ptr, input_size);