diff mbox series

[FFmpeg-devel,v5] avcodec/cbs_vp8: Add support for VP8 codec bitstream

Message ID DM6PR11MB26816240ED2779433BB39E06B1AAA@DM6PR11MB2681.namprd11.prod.outlook.com
State New
Headers show
Series [FFmpeg-devel,v5] avcodec/cbs_vp8: Add support for VP8 codec bitstream | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Dai, Jianhui J Nov. 6, 2023, 12:56 a.m. UTC
This commit adds support for VP8 bitstream read methods to the cbs
codec. This enables the trace_headers bitstream filter to support VP8,
in addition to AV1, H.264, H.265, and VP9. This can be useful for
debugging VP8 stream issues.

The CBS VP8 implements a simple VP8 boolean decoder using GetBitContext
to read the bitstream.

Only the read methods `read_unit` and `split_fragment` are implemented.
The write methods `write_unit` and `assemble_fragment` return the error
code AVERROR_PATCHWELCOME. This is because CBS VP8 write is unlikely to
be used by any applications at the moment. The write methods can be
added later if there is a real need for them.

TESTS: ffmpeg -i fate-suite/vp8/frame_size_change.webm -vcodec copy
-bsf:v trace_headers -f null -

Signed-off-by: Jianhui Dai <jianhui.j.dai@intel.com>
---
 configure                            |   4 +-
 libavcodec/Makefile                  |   1 +
 libavcodec/cbs.c                     |   6 +
 libavcodec/cbs_internal.h            |   1 +
 libavcodec/cbs_vp8.c                 | 548 +++++++++++++++++++++++++++
 libavcodec/cbs_vp8.h                 | 133 +++++++
 libavcodec/cbs_vp8_syntax_template.c | 248 ++++++++++++
 7 files changed, 940 insertions(+), 1 deletion(-)
 create mode 100644 libavcodec/cbs_vp8.c
 create mode 100644 libavcodec/cbs_vp8.h
 create mode 100644 libavcodec/cbs_vp8_syntax_template.c

Comments

Ronald S. Bultje Nov. 6, 2023, 2:47 a.m. UTC | #1
Hi,

On Sun, Nov 5, 2023 at 7:56 PM Dai, Jianhui J <
jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:

> This commit adds support for VP8 bitstream read methods to the cbs
> codec. This enables the trace_headers bitstream filter to support VP8,
> in addition to AV1, H.264, H.265, and VP9. This can be useful for
> debugging VP8 stream issues.
>
> The CBS VP8 implements a simple VP8 boolean decoder using GetBitContext
> to read the bitstream.
>

Is it possible to re-use the existing vp56rac decoder for this? Having two
arithmetic bool decoders that do the same thing is a bit weird.


> +static const uint8_t vp8_token_update_probs[4][8][3][11] = {
>

It would be nice if these symbols could be re-used from the existing vp8
native decoder, instead of duplicating them? Both source + binary size are
relevant here.

I'm also wondering if - longer-term - it makes sense to try to merge some
of these concepts back into the native decoders, objects like
Vp8RawFameHeader, but I'm guessing that's not super-urgent...

Ronald
Dai, Jianhui J Nov. 6, 2023, 4:13 a.m. UTC | #2
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Ronald S. Bultje
> Sent: Monday, November 6, 2023 10:48 AM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v5] avcodec/cbs_vp8: Add support for
> VP8 codec bitstream
> 
> Hi,
> 
> On Sun, Nov 5, 2023 at 7:56 PM Dai, Jianhui J < jianhui.j.dai-at-
> intel.com@ffmpeg.org> wrote:
> 
> > This commit adds support for VP8 bitstream read methods to the cbs
> > codec. This enables the trace_headers bitstream filter to support VP8,
> > in addition to AV1, H.264, H.265, and VP9. This can be useful for
> > debugging VP8 stream issues.
> >
> > The CBS VP8 implements a simple VP8 boolean decoder using
> > GetBitContext to read the bitstream.
> >
> 
> Is it possible to re-use the existing vp56rac decoder for this? Having two
> arithmetic bool decoders that do the same thing is a bit weird.
> 

Thank for your commentary.

The existing RAC decoder cannot be reused here because:
1. The VPXRangeCoder is optimized for performance, that it always read one more byte. However, it does not apply bounds checking to prevent overreads. 
    It was suggested to implement this simply boolean reader, in the comment of patch v1 and v2.
2. Additionally, all CBS have to use GetBitContext to read bitstream and trace the syntax elements.

> 
> > +static const uint8_t vp8_token_update_probs[4][8][3][11] = {
> >
> 
> It would be nice if these symbols could be re-used from the existing vp8
> native decoder, instead of duplicating them? Both source + binary size are
> relevant here.

Including vp8data.h would introduce many unwanted static tables other than vp8_token_update_probs and increase the binary size. 
As suggested in patch v3, it is better to use local defined vp8_token_update_probs.

> 
> I'm also wondering if - longer-term - it makes sense to try to merge some of
> these concepts back into the native decoders, objects like
> Vp8RawFameHeader, but I'm guessing that's not super-urgent...

Thanks. That can be reused in the future.

> 
> Ronald
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org
> with subject "unsubscribe".
Ronald S. Bultje Nov. 6, 2023, 12:07 p.m. UTC | #3
Hi,

On Sun, Nov 5, 2023 at 11:13 PM Dai, Jianhui J <
jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:

> > > +static const uint8_t vp8_token_update_probs[4][8][3][11] = {
> >
> > It would be nice if these symbols could be re-used from the existing vp8
> > native decoder, instead of duplicating them? Both source + binary size
> are
> > relevant here.
>
> Including vp8data.h would introduce many unwanted static tables other than
> vp8_token_update_probs and increase the binary size.
> As suggested in patch v3, it is better to use local defined
> vp8_token_update_probs.
>

I didn't mean to include vp8data.h. I mean to include a new *.h that
declares extern const uint8_t vp8_token_update_probs[][][][] and move said
table into a new *.c file. The point is to prevent symbol duplication.

Ronald
Ronald S. Bultje Nov. 6, 2023, 12:08 p.m. UTC | #4
Hi,

On Mon, Nov 6, 2023 at 7:07 AM Ronald S. Bultje <rsbultje@gmail.com> wrote:

> On Sun, Nov 5, 2023 at 11:13 PM Dai, Jianhui J <
> jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:
>
>> > > +static const uint8_t vp8_token_update_probs[4][8][3][11] = {
>> >
>> > It would be nice if these symbols could be re-used from the existing vp8
>> > native decoder, instead of duplicating them? Both source + binary size
>> are
>> > relevant here.
>>
>> Including vp8data.h would introduce many unwanted static tables other
>> than vp8_token_update_probs and increase the binary size.
>> As suggested in patch v3, it is better to use local defined
>> vp8_token_update_probs.
>>
>
> I didn't mean to include vp8data.h. I mean to include a new *.h that
> declares extern const uint8_t vp8_token_update_probs[][][][] and move said
> table into a new *.c file. The point is to prevent symbol duplication.
>

And to elaborate further, in case it's unclear: the symbol move means the
native VP8 decoder would include this probability table using the same new
mechanism also. It would no longer exist in vp8data.h.

Ronald
Dai, Jianhui J Nov. 7, 2023, 5 a.m. UTC | #5
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Ronald S. Bultje
> Sent: Monday, November 6, 2023 8:08 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v5] avcodec/cbs_vp8: Add support for
> VP8 codec bitstream
> 
> Hi,
> 
> On Mon, Nov 6, 2023 at 7:07 AM Ronald S. Bultje <rsbultje@gmail.com>
> wrote:
> 
> > On Sun, Nov 5, 2023 at 11:13 PM Dai, Jianhui J <
> > jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:
> >
> >> > > +static const uint8_t vp8_token_update_probs[4][8][3][11] = {
> >> >
> >> > It would be nice if these symbols could be re-used from the
> >> > existing vp8 native decoder, instead of duplicating them? Both
> >> > source + binary size
> >> are
> >> > relevant here.
> >>
> >> Including vp8data.h would introduce many unwanted static tables other
> >> than vp8_token_update_probs and increase the binary size.
> >> As suggested in patch v3, it is better to use local defined
> >> vp8_token_update_probs.
> >>
> >
> > I didn't mean to include vp8data.h. I mean to include a new *.h that
> > declares extern const uint8_t vp8_token_update_probs[][][][] and move
> > said table into a new *.c file. The point is to prevent symbol duplication.
> >
> 
> And to elaborate further, in case it's unclear: the symbol move means the
> native VP8 decoder would include this probability table using the same new
> mechanism also. It would no longer exist in vp8data.h.

Right. 
I made another change to reorganize the vp8data.[c|h] and only export ` ff_vp8_dct_cat_prob` and `ff_vp8_token_default_probs`.
Please take a look.

https://patchwork.ffmpeg.org/project/ffmpeg/patch/DM6PR11MB2681FCCA688553FA8F1A7218B1A9A@DM6PR11MB2681.namprd11.prod.outlook.com/

> 
> Ronald
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org
> with subject "unsubscribe".
Ronald S. Bultje Nov. 7, 2023, 8:25 p.m. UTC | #6
Hi,

On Tue, Nov 7, 2023 at 12:01 AM Dai, Jianhui J <
jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:

>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Ronald S. Bultje
> > Sent: Monday, November 6, 2023 8:08 PM
> > To: FFmpeg development discussions and patches <ffmpeg-
> > devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [PATCH v5] avcodec/cbs_vp8: Add support for
> > VP8 codec bitstream
> >
> > Hi,
> >
> > On Mon, Nov 6, 2023 at 7:07 AM Ronald S. Bultje <rsbultje@gmail.com>
> > wrote:
> >
> > > On Sun, Nov 5, 2023 at 11:13 PM Dai, Jianhui J <
> > > jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:
> > >
> > >> > > +static const uint8_t vp8_token_update_probs[4][8][3][11] = {
> > >> >
> > >> > It would be nice if these symbols could be re-used from the
> > >> > existing vp8 native decoder, instead of duplicating them? Both
> > >> > source + binary size
> > >> are
> > >> > relevant here.
> > >>
> > >> Including vp8data.h would introduce many unwanted static tables other
> > >> than vp8_token_update_probs and increase the binary size.
> > >> As suggested in patch v3, it is better to use local defined
> > >> vp8_token_update_probs.
> > >>
> > >
> > > I didn't mean to include vp8data.h. I mean to include a new *.h that
> > > declares extern const uint8_t vp8_token_update_probs[][][][] and move
> > > said table into a new *.c file. The point is to prevent symbol
> duplication.
> > >
> >
> > And to elaborate further, in case it's unclear: the symbol move means the
> > native VP8 decoder would include this probability table using the same
> new
> > mechanism also. It would no longer exist in vp8data.h.
>
> Right.
> I made another change to reorganize the vp8data.[c|h] and only export `
> ff_vp8_dct_cat_prob` and `ff_vp8_token_default_probs`.
> Please take a look.
>

I'm not sure it's a good idea to move all tables back into vp8.c. There's a
reason we added it in a separate header file, so that "large random tables
with numbers" don't obfuscate the actual source code file. Or to say it
diffrently: you could probably have accomplished the same effect with a
much smaller diff... That's just my opinion though. Anyone else care about
any of this?

Ronald
Dai, Jianhui J Nov. 8, 2023, 1:51 a.m. UTC | #7
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Ronald S.
> Bultje
> Sent: Wednesday, November 8, 2023 4:26 AM
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v5] avcodec/cbs_vp8: Add support for VP8
> codec bitstream
> 
> Hi,
> 
> On Tue, Nov 7, 2023 at 12:01 AM Dai, Jianhui J < jianhui.j.dai-at-
> intel.com@ffmpeg.org> wrote:
> 
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > > Ronald S. Bultje
> > > Sent: Monday, November 6, 2023 8:08 PM
> > > To: FFmpeg development discussions and patches <ffmpeg-
> > > devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [PATCH v5] avcodec/cbs_vp8: Add support
> > > for
> > > VP8 codec bitstream
> > >
> > > Hi,
> > >
> > > On Mon, Nov 6, 2023 at 7:07 AM Ronald S. Bultje <rsbultje@gmail.com>
> > > wrote:
> > >
> > > > On Sun, Nov 5, 2023 at 11:13 PM Dai, Jianhui J <
> > > > jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:
> > > >
> > > >> > > +static const uint8_t vp8_token_update_probs[4][8][3][11] = {
> > > >> >
> > > >> > It would be nice if these symbols could be re-used from the
> > > >> > existing vp8 native decoder, instead of duplicating them? Both
> > > >> > source + binary size
> > > >> are
> > > >> > relevant here.
> > > >>
> > > >> Including vp8data.h would introduce many unwanted static tables
> > > >> other than vp8_token_update_probs and increase the binary size.
> > > >> As suggested in patch v3, it is better to use local defined
> > > >> vp8_token_update_probs.
> > > >>
> > > >
> > > > I didn't mean to include vp8data.h. I mean to include a new *.h
> > > > that declares extern const uint8_t vp8_token_update_probs[][][][]
> > > > and move said table into a new *.c file. The point is to prevent
> > > > symbol
> > duplication.
> > > >
> > >
> > > And to elaborate further, in case it's unclear: the symbol move
> > > means the native VP8 decoder would include this probability table
> > > using the same
> > new
> > > mechanism also. It would no longer exist in vp8data.h.
> >
> > Right.
> > I made another change to reorganize the vp8data.[c|h] and only export
> > ` ff_vp8_dct_cat_prob` and `ff_vp8_token_default_probs`.
> > Please take a look.
> >
> 
> I'm not sure it's a good idea to move all tables back into vp8.c. There's a reason
> we added it in a separate header file, so that "large random tables with numbers"
> don't obfuscate the actual source code file. Or to say it
> diffrently: you could probably have accomplished the same effect with a much
> smaller diff... That's just my opinion though. Anyone else care about any of this?

The smaller delta patch to export the variable:  https://patchwork.ffmpeg.org/project/ffmpeg/patch/DM6PR11MB268186349E600824E1577DFDB1A8A@DM6PR11MB2681.namprd11.prod.outlook.com/
Personally, I prefer to limit the static data only in vp8.c. 

> 
> Ronald
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with
> subject "unsubscribe".
Ronald S. Bultje Nov. 8, 2023, 3:55 p.m. UTC | #8
Hi Jianhui,

On Tue, Nov 7, 2023 at 8:52 PM Dai, Jianhui J <
jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:

> The smaller delta patch to export the variable:
> https://patchwork.ffmpeg.org/project/ffmpeg/patch/DM6PR11MB268186349E600824E1577DFDB1A8A@DM6PR11MB2681.namprd11.prod.outlook.com/
> Personally, I prefer to limit the static data only in vp8.c.
>

Understood. It's going to be a dice-roll either way, and since I'm the
maintainer, I get to pick :-). I prefer continuing with what we have in
this version, but I'll leave it open for the majority opinion to overrule
me for a few days before we merge this.

Do you need me to merge or do you have commit access?

If you adapt the cbs patch to use this (newly) exported table, I have no
further review comments.

Ronald
Ronald S. Bultje Nov. 8, 2023, 4:37 p.m. UTC | #9
Hi,

On Wed, Nov 8, 2023 at 10:55 AM Ronald S. Bultje <rsbultje@gmail.com> wrote:

> Hi Jianhui,
>
> On Tue, Nov 7, 2023 at 8:52 PM Dai, Jianhui J <
> jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:
>
>> The smaller delta patch to export the variable:
>> https://patchwork.ffmpeg.org/project/ffmpeg/patch/DM6PR11MB268186349E600824E1577DFDB1A8A@DM6PR11MB2681.namprd11.prod.outlook.com/
>> Personally, I prefer to limit the static data only in vp8.c.
>>
>
> Understood. It's going to be a dice-roll either way, and since I'm the
> maintainer, I get to pick :-). I prefer continuing with what we have in
> this version, but I'll leave it open for the majority opinion to overrule
> me for a few days before we merge this.
>

Actually, I realize that sounds quite rude, so let me elaborate: I prefer
external data tables (in a separate source file from the rest of the code)
because they tend to be big and clunky and you can't really change them
anyway. They are essentially binary blob in numerical form. We use external
data tables in quite a few parts of ffmpeg and I've grown accustomed to
that design. For now, for old codecs where nothing much changes over time,
I prefer to keep it as it is. Small diffs means easy to trace back when
stuff breaks, as a general rule.

But I admit that all this is personal preference. There's nothing wrong
with a different approach, it's just that: different. Let's agree on a
color (green!) and move on to shiny new objects.

Ronald
Dai, Jianhui J Nov. 9, 2023, 3:23 a.m. UTC | #10
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Ronald S.
> Bultje
> Sent: Thursday, November 9, 2023 12:38 AM
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v5] avcodec/cbs_vp8: Add support for VP8
> codec bitstream
> 
> Hi,
> 
> On Wed, Nov 8, 2023 at 10:55 AM Ronald S. Bultje <rsbultje@gmail.com> wrote:
> 
> > Hi Jianhui,
> >
> > On Tue, Nov 7, 2023 at 8:52 PM Dai, Jianhui J <
> > jianhui.j.dai-at-intel.com@ffmpeg.org> wrote:
> >
> >> The smaller delta patch to export the variable:
> >>
> https://patchwork.ffmpeg.org/project/ffmpeg/patch/DM6PR11MB268186349E
> >> 600824E1577DFDB1A8A@DM6PR11MB2681.namprd11.prod.outlook.com/
> >> Personally, I prefer to limit the static data only in vp8.c.
> >>
> >
> > Understood. It's going to be a dice-roll either way, and since I'm the
> > maintainer, I get to pick :-). I prefer continuing with what we have
> > in this version, but I'll leave it open for the majority opinion to
> > overrule me for a few days before we merge this.
> >
> 
> Actually, I realize that sounds quite rude, so let me elaborate: I prefer external
> data tables (in a separate source file from the rest of the code) because they tend
> to be big and clunky and you can't really change them anyway. They are
> essentially binary blob in numerical form. We use external data tables in quite a
> few parts of ffmpeg and I've grown accustomed to that design. For now, for old
> codecs where nothing much changes over time, I prefer to keep it as it is. Small
> diffs means easy to trace back when stuff breaks, as a general rule.
> 
> But I admit that all this is personal preference. There's nothing wrong with a
> different approach, it's just that: different. Let's agree on a color (green!) and
> move on to shiny new objects.

I fully respect all of the feedback provided during the code review. 
Thank you for your patience. : )

I don’t have the commit access. Appreciate to help to submit if everything goes well.

> 
> Ronald
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with
> subject "unsubscribe".
diff mbox series

Patch

diff --git a/configure b/configure
index 7afeebebcd..8a4ea125ad 100755
--- a/configure
+++ b/configure
@@ -2471,6 +2471,7 @@  CONFIG_EXTRA="
     cbs_h266
     cbs_jpeg
     cbs_mpeg2
+    cbs_vp8
     cbs_vp9
     deflate_wrapper
     dirac_parse
@@ -2756,6 +2757,7 @@  cbs_h265_select="cbs"
 cbs_h266_select="cbs"
 cbs_jpeg_select="cbs"
 cbs_mpeg2_select="cbs"
+cbs_vp8_select="cbs"
 cbs_vp9_select="cbs"
 deflate_wrapper_deps="zlib"
 dirac_parse_select="golomb"
@@ -3339,7 +3341,7 @@  h264_redundant_pps_bsf_select="cbs_h264"
 hevc_metadata_bsf_select="cbs_h265"
 mjpeg2jpeg_bsf_select="jpegtables"
 mpeg2_metadata_bsf_select="cbs_mpeg2"
-trace_headers_bsf_select="cbs"
+trace_headers_bsf_select="cbs cbs_vp8"
 vp9_metadata_bsf_select="cbs_vp9"
 vvc_metadata_bsf_select="cbs_h266"
 
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index ab7fba394a..7b0f9ab550 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -81,6 +81,7 @@  OBJS-$(CONFIG_CBS_H265)                += cbs_h2645.o cbs_sei.o h2645_parse.o
 OBJS-$(CONFIG_CBS_H266)                += cbs_h2645.o cbs_sei.o h2645_parse.o
 OBJS-$(CONFIG_CBS_JPEG)                += cbs_jpeg.o
 OBJS-$(CONFIG_CBS_MPEG2)               += cbs_mpeg2.o
+OBJS-$(CONFIG_CBS_VP8)                 += cbs_vp8.o
 OBJS-$(CONFIG_CBS_VP9)                 += cbs_vp9.o
 OBJS-$(CONFIG_CRYSTALHD)               += crystalhd.o
 OBJS-$(CONFIG_DEFLATE_WRAPPER)         += zlib_wrapper.o
diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index cdd7adebeb..de7b1361aa 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -50,6 +50,9 @@  static const CodedBitstreamType *const cbs_type_table[] = {
 #if CONFIG_CBS_MPEG2
     &ff_cbs_type_mpeg2,
 #endif
+#if CONFIG_CBS_VP8
+    &ff_cbs_type_vp8,
+#endif
 #if CONFIG_CBS_VP9
     &ff_cbs_type_vp9,
 #endif
@@ -74,6 +77,9 @@  const enum AVCodecID ff_cbs_all_codec_ids[] = {
 #if CONFIG_CBS_MPEG2
     AV_CODEC_ID_MPEG2VIDEO,
 #endif
+#if CONFIG_CBS_VP8
+    AV_CODEC_ID_VP8,
+#endif
 #if CONFIG_CBS_VP9
     AV_CODEC_ID_VP9,
 #endif
diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h
index 07220f1f3e..d982262bd9 100644
--- a/libavcodec/cbs_internal.h
+++ b/libavcodec/cbs_internal.h
@@ -341,6 +341,7 @@  extern const CodedBitstreamType ff_cbs_type_h265;
 extern const CodedBitstreamType ff_cbs_type_h266;
 extern const CodedBitstreamType ff_cbs_type_jpeg;
 extern const CodedBitstreamType ff_cbs_type_mpeg2;
+extern const CodedBitstreamType ff_cbs_type_vp8;
 extern const CodedBitstreamType ff_cbs_type_vp9;
 
 
diff --git a/libavcodec/cbs_vp8.c b/libavcodec/cbs_vp8.c
new file mode 100644
index 0000000000..79a2a9bba6
--- /dev/null
+++ b/libavcodec/cbs_vp8.c
@@ -0,0 +1,548 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+
+#include "cbs.h"
+#include "cbs_internal.h"
+#include "cbs_vp8.h"
+
+#include <stdbool.h>
+
+#define DEFAULT_PROB 0x80
+
+static const uint8_t vp8_token_update_probs[4][8][3][11] = {
+    {
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+            {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+            {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255},
+            {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255},
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+    },
+    {
+        {
+            {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255},
+            {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255},
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+    },
+    {
+        {
+            {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255},
+            {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255},
+            {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255},
+        },
+        {
+            {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+    },
+    {
+        {
+            {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255},
+            {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+            {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+            {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+            {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+            {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+            {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+            {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+        {
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+            {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+        },
+    },
+};
+
+// Implements VP8 boolean decoder using GetBitContext to read the bitstream.
+typedef struct CBSVP8BoolDecoder {
+    GetBitContext *gbc;
+
+    uint8_t value;
+    uint8_t range;
+
+    uint8_t count; // Store the number of bits in the `value` buffer.
+
+} CBSVP8BoolDecoder;
+
+static int cbs_vp8_bool_decoder_init(CBSVP8BoolDecoder *decoder, GetBitContext *gbc)
+{
+    av_assert0(decoder);
+    av_assert0(gbc);
+
+    decoder->gbc = gbc;
+    decoder->value = 0;
+    decoder->range = 255;
+
+    decoder->count = 0;
+
+    return 0;
+}
+
+static bool cbs_vp8_bool_decoder_fill_value(CBSVP8BoolDecoder *decoder)
+{
+    int bits = 8 - decoder->count;
+
+    av_assert0(decoder->count <= 8);
+    if (decoder->count == 8) {
+      return true;
+    }
+
+    if (get_bits_left(decoder->gbc) >= bits) {
+        decoder->value |= get_bits(decoder->gbc, bits);
+        decoder->count += bits;
+    }
+
+    return (decoder->count == 8);
+}
+
+static int cbs_vp8_bool_decoder_read_bool(CBSVP8BoolDecoder *decoder,
+                                          const uint8_t prob, uint8_t *output)
+{
+    uint8_t split = 1 + (((decoder->range - 1) * prob) >> 8);
+
+    if (!cbs_vp8_bool_decoder_fill_value(decoder)) {
+        return AVERROR_INVALIDDATA;
+    }
+
+    av_assert0(decoder->count == 8);
+    if (decoder->value >= split) {
+        *output = 1;
+        decoder->range -= split;
+        decoder->value -= split;
+    } else {
+        *output = 0;
+        decoder->range = split;
+    }
+
+    while (decoder->range < 128) {
+        decoder->value <<= 1;
+        decoder->range <<= 1;
+        --decoder->count;
+    }
+
+    return 0;
+}
+
+static int cbs_vp8_bool_decoder_read_literal(CBSVP8BoolDecoder *decoder,
+                                             const uint8_t prob,
+                                             uint32_t num_bits,
+                                             uint32_t *output)
+{
+    int ret = 0;
+
+    av_assert0(num_bits <= 32);
+
+    *output = 0;
+    for (; num_bits > 0; --num_bits) {
+        uint8_t bit_output = 0;
+        if ((ret = cbs_vp8_bool_decoder_read_bool(decoder, prob,
+                                                  &bit_output)) != 0) {
+            return ret;
+        }
+
+        *output = (*output << 1) | bit_output;
+    }
+
+    return 0;
+}
+
+static int cbs_vp8_bool_decoder_read_unsigned(
+    CodedBitstreamContext *ctx, CBSVP8BoolDecoder *bool_decoder, int width,
+    uint8_t prob, const char *name, const int *subscripts, uint32_t *write_to,
+    bool trace_enable)
+{
+    int ret = 0;
+    GetBitContext *gbc = bool_decoder->gbc;
+    uint32_t value;
+
+    CBS_TRACE_READ_START();
+
+    av_assert0(width >= 0 && width <= 8);
+
+    ret = cbs_vp8_bool_decoder_read_literal(bool_decoder, prob, width, &value);
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (trace_enable) {
+      CBS_TRACE_READ_END();
+    }
+
+    *write_to = value;
+    return 0;
+}
+
+static int cbs_vp8_bool_decoder_read_signed(
+    CodedBitstreamContext *ctx, CBSVP8BoolDecoder *bool_decoder, int width,
+    uint8_t prob, const char *name, const int *subscripts, int32_t *write_to)
+{
+    int ret = 0;
+    GetBitContext *gbc = bool_decoder->gbc;
+    int32_t value;
+    uint8_t sign = 0;
+
+    CBS_TRACE_READ_START();
+
+    av_assert0(width >= 0 && width <= 8);
+
+    ret = cbs_vp8_bool_decoder_read_literal(bool_decoder, prob, width, &value);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = cbs_vp8_bool_decoder_read_bool(bool_decoder, prob, &sign);
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (sign) {
+        value = -value;
+    }
+
+    CBS_TRACE_READ_END();
+
+    *write_to = value;
+    return 0;
+}
+
+static int cbs_vp8_read_unsigned_le(CodedBitstreamContext *ctx, GetBitContext *gbc,
+                                 int width, const char *name,
+                                 const int *subscripts, uint32_t *write_to)
+{
+    int32_t value;
+
+    CBS_TRACE_READ_START();
+
+    av_assert0(width > 0 && width <= 24);
+
+    if (get_bits_left(gbc) < width) {
+        av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value: bitstream ended.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    value = get_bits_le(gbc, width);
+
+    CBS_TRACE_READ_END();
+
+    *write_to = value;
+    return 0;
+}
+
+#define HEADER(name) \
+    do { \
+        ff_cbs_trace_header(ctx, name); \
+    } while (0)
+
+#define CHECK(call) \
+    do { \
+        int err = (call); \
+        if (err < 0) \
+            return err; \
+    } while (0)
+
+#define FUNC_NAME(rw, codec, name) cbs_##codec##_##rw##_##name
+#define FUNC_VP8(rw, name) FUNC_NAME(rw, vp8, name)
+#define FUNC(name) FUNC_VP8(READWRITE, name)
+
+#define SUBSCRIPTS(subs, ...) \
+    (subs > 0 ? ((int[subs + 1]){subs, __VA_ARGS__}) : NULL)
+
+#define f(width, name) xf(width, name, 0)
+
+// bool [de|en]coder methods.
+#define bc_f(width, name) bc_unsigned_subs(width, DEFAULT_PROB, true, name, 0)
+#define bc_s(width, name) bc_signed_subs(width, DEFAULT_PROB, name, 0)
+#define bc_fs(width, name, subs, ...) \
+    bc_unsigned_subs(width, DEFAULT_PROB, true, name, subs, __VA_ARGS__)
+#define bc_ss(width, name, subs, ...) \
+    bc_signed_subs(width, DEFAULT_PROB, name, subs, __VA_ARGS__)
+
+// bool [de|en]coder methods for boolean value and disable tracing.
+#define bc_b(name) bc_unsigned_subs(1, DEFAULT_PROB, false, name, 0)
+#define bc_b_prob(prob, name) bc_unsigned_subs(1, prob, false, name, 0)
+
+#define READ
+#define READWRITE read
+#define RWContext GetBitContext
+#define CBSVP8BoolCodingRW CBSVP8BoolDecoder
+
+#define xf(width, name, subs, ...) \
+    do { \
+        uint32_t value; \
+        CHECK(cbs_vp8_read_unsigned_le(ctx, rw, width, #name, \
+                                    SUBSCRIPTS(subs, __VA_ARGS__), &value)); \
+        current->name = value; \
+    } while (0)
+
+#define fixed(width, name, value) \
+    do { \
+        uint32_t fixed_value; \
+        CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, 0, &fixed_value, \
+                                   value, value)); \
+    } while (0)
+
+#define bc_unsigned_subs(width, prob, enable_trace, name, subs, ...) \
+    do { \
+        uint32_t value; \
+        CHECK(cbs_vp8_bool_decoder_read_unsigned( \
+            ctx, bool_coding_rw, width, prob, #name, \
+            SUBSCRIPTS(subs, __VA_ARGS__), &value, enable_trace)); \
+        current->name = value; \
+    } while (0)
+
+#define bc_signed_subs(width, prob, name, subs, ...) \
+    do { \
+        int32_t value; \
+        CHECK(cbs_vp8_bool_decoder_read_signed( \
+            ctx, bool_coding_rw, width, prob, #name, \
+            SUBSCRIPTS(subs, __VA_ARGS__), &value)); \
+        current->name = value; \
+    } while (0)
+
+#include "cbs_vp8_syntax_template.c"
+
+static int cbs_vp8_split_fragment(CodedBitstreamContext *ctx,
+                                  CodedBitstreamFragment *frag, int header)
+{
+    int err;
+
+    if (frag->data_size == 0)
+        return AVERROR_INVALIDDATA;
+
+    err = ff_cbs_append_unit_data(frag, 0, frag->data, frag->data_size,
+                                  frag->data_ref);
+    if (err < 0)
+        return err;
+
+    return 0;
+}
+
+static int cbs_vp8_read_unit(CodedBitstreamContext *ctx,
+                             CodedBitstreamUnit *unit)
+{
+    VP8RawFrame *frame;
+    GetBitContext gbc;
+    CBSVP8BoolDecoder bool_decoder;
+    int err, pos;
+
+    err = ff_cbs_alloc_unit_content(ctx, unit);
+    if (err < 0)
+        return err;
+    frame = unit->content;
+
+    // Create GetBitContext for uncompressed header.
+    err = init_get_bits8_le(&gbc, unit->data, 8 * unit->data_size);
+    if (err < 0)
+        return err;
+
+    err = cbs_vp8_read_uncompressed_header(ctx, &gbc, frame);
+    if (err < 0)
+        return err;
+
+    pos = get_bits_count(&gbc);
+    av_assert0(pos % 8 == 0);
+
+    // Create boolean decoder for compressed header.
+    err = cbs_vp8_bool_decoder_init(&bool_decoder, &gbc);
+    if (err < 0)
+        return err;
+
+    err = cbs_vp8_read_compressed_header(ctx, &bool_decoder, frame);
+    if (err < 0)
+        return err;
+
+    pos = get_bits_count(&gbc);
+    pos /= 8;
+    av_assert0(pos <= unit->data_size);
+
+    frame->data_ref = av_buffer_ref(unit->data_ref);
+    if (!frame->data_ref)
+        return AVERROR(ENOMEM);
+
+    frame->data = unit->data + pos;
+    frame->data_size = unit->data_size - pos;
+
+    return 0;
+}
+
+static int cbs_vp8_write_unit(CodedBitstreamContext *ctx,
+                              CodedBitstreamUnit *unit, PutBitContext *pbc)
+{
+    return AVERROR_PATCHWELCOME;
+}
+
+static int cbs_vp8_assemble_fragment(CodedBitstreamContext *ctx,
+                                     CodedBitstreamFragment *frag)
+{
+    return AVERROR_PATCHWELCOME;
+}
+
+static void cbs_vp8_flush(CodedBitstreamContext *ctx)
+{
+    // Do nothing.
+}
+
+static const CodedBitstreamUnitTypeDescriptor cbs_vp8_unit_types[] = {
+    CBS_UNIT_TYPE_INTERNAL_REF(0, VP8RawFrame, data),
+    CBS_UNIT_TYPE_END_OF_LIST,
+};
+
+const CodedBitstreamType ff_cbs_type_vp8 = {
+    .codec_id          = AV_CODEC_ID_VP8,
+
+    .priv_data_size    = 0,
+
+    .unit_types        = cbs_vp8_unit_types,
+
+    .split_fragment    = &cbs_vp8_split_fragment,
+    .read_unit         = &cbs_vp8_read_unit,
+    .write_unit        = &cbs_vp8_write_unit,
+
+    .flush             = &cbs_vp8_flush,
+
+    .assemble_fragment = &cbs_vp8_assemble_fragment,
+};
diff --git a/libavcodec/cbs_vp8.h b/libavcodec/cbs_vp8.h
new file mode 100644
index 0000000000..9c09e21a1c
--- /dev/null
+++ b/libavcodec/cbs_vp8.h
@@ -0,0 +1,133 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_CBS_VP8_H
+#define AVCODEC_CBS_VP8_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "cbs.h"
+
+enum {
+    VP8_START_CODE_0 = 0x9D,
+    VP8_START_CODE_1 = 0x01,
+    VP8_START_CODE_2 = 0x2A,
+};
+
+enum {
+    VP8_KEY_FRAME = 0,
+    VP8_NON_KEY_FRAME = 1,
+};
+
+typedef struct VP8RawFrameHeader {
+    // frame tag
+    uint8_t frame_type;
+    uint8_t profile;
+    uint8_t show_frame;
+    uint32_t first_partition_length_in_bytes;
+
+    uint16_t width;
+    uint8_t horizontal_scale;
+    uint16_t height;
+    uint8_t vertical_scale;
+
+    // frame header
+    uint8_t color_space;
+    uint8_t clamping_type;
+
+    // segmentation
+    uint8_t segmentation_enable;
+    uint8_t update_segment_map;
+    uint8_t update_segment_feature_data;
+    uint8_t segment_feature_mode;
+    uint8_t segment_qp_update[4];
+    int8_t segment_qp[4];
+    uint8_t segment_loop_filter_level_update[4];
+    int8_t segment_loop_filter_level[4];
+    uint8_t segment_probs_update[3];
+    uint8_t segment_probs[3];
+
+    // loop filter
+    uint8_t loop_filter_type;
+    uint8_t loop_filter_level;
+    uint8_t loop_filter_sharpness;
+    uint8_t mode_ref_lf_delta_enable;
+    uint8_t mode_ref_lf_delta_update;
+    uint8_t ref_lf_deltas_update[4];
+    int8_t ref_lf_deltas[4];
+    uint8_t mode_lf_deltas_update[4];
+    int8_t mode_lf_deltas[4];
+
+    uint8_t log2_token_partitions;
+
+    // qp
+    uint8_t base_qindex;
+    uint8_t y1dc_delta_q_present;
+    int8_t y1dc_delta_q;
+    uint8_t y2dc_delta_q_present;
+    int8_t y2dc_delta_q;
+    uint8_t y2ac_delta_q_present;
+    int8_t y2ac_delta_q;
+    uint8_t uvdc_delta_q_present;
+    int8_t uvdc_delta_q;
+    uint8_t uvac_delta_q_present;
+    int8_t uvac_delta_q;
+
+    // ref
+    uint8_t refresh_golden_frame;
+    uint8_t refresh_alternate_frame;
+    uint8_t copy_buffer_to_golden;
+    uint8_t copy_buffer_to_alternate;
+    uint8_t ref_frame_sign_bias_golden;
+    uint8_t ref_frame_sign_bias_alternate;
+    uint8_t refresh_last_frame;
+
+    uint8_t refresh_entropy_probs;
+
+    // token probs
+    uint8_t coeff_prob_update[4][8][3][11];
+    uint8_t coeff_prob[4][8][3][11];
+
+    uint8_t mb_no_skip_coeff;
+    uint8_t prob_skip_false;
+
+    uint8_t prob_intra;
+    uint8_t prob_last;
+    uint8_t prob_golden;
+
+    uint8_t intra_16x16_prob_update;
+    uint8_t intra_16x16_prob[4];
+
+    uint8_t intra_chrome_prob_update;
+    uint8_t intra_chrome_prob[3];
+
+    // mv probs
+    uint8_t mv_prob_update[2][19];
+    uint8_t mv_prob[2][19];
+} VP8RawFrameHeader;
+
+typedef struct VP8RawFrame {
+    VP8RawFrameHeader header;
+
+    uint8_t *data;
+    AVBufferRef *data_ref;
+    size_t data_size;
+} VP8RawFrame;
+
+#endif /* AVCODEC_CBS_VP8_H */
diff --git a/libavcodec/cbs_vp8_syntax_template.c b/libavcodec/cbs_vp8_syntax_template.c
new file mode 100644
index 0000000000..0bdf699f39
--- /dev/null
+++ b/libavcodec/cbs_vp8_syntax_template.c
@@ -0,0 +1,248 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+static int FUNC(update_segmentation)(CodedBitstreamContext *ctx,
+                                     CBSVP8BoolCodingRW *bool_coding_rw,
+                                     VP8RawFrameHeader *current)
+{
+    bc_f(1, update_segment_map);
+    bc_f(1, update_segment_feature_data);
+
+    if (current->update_segment_feature_data) {
+        bc_f(1, segment_feature_mode);
+        // quantizer
+        for (int i = 0; i < 4; i++) {
+            bc_b(segment_qp_update[i]);
+            if (current->segment_qp_update[i])
+                bc_ss(7, segment_qp[i], 1, i);
+        }
+        // loop filter
+        for (int i = 0; i < 4; i++) {
+            bc_b(segment_loop_filter_level_update[i]);
+            if (current->segment_loop_filter_level_update[i])
+                bc_ss(6, segment_loop_filter_level[i], 1, i);
+        }
+    }
+
+    if (current->update_segment_map) {
+        for (int i = 0; i < 3; i++) {
+            bc_b(segment_probs_update[i]);
+            if (current->segment_probs_update[i])
+                bc_fs(8, segment_probs[i], 1, i);
+        }
+    }
+
+    return 0;
+}
+
+static int FUNC(mode_ref_lf_deltas)(CodedBitstreamContext *ctx,
+                                    CBSVP8BoolCodingRW *bool_coding_rw,
+                                    VP8RawFrameHeader *current)
+{
+    bc_f(1, mode_ref_lf_delta_enable);
+    if (current->mode_ref_lf_delta_enable) {
+        bc_b(mode_ref_lf_delta_update);
+        if (current->mode_ref_lf_delta_update) {
+            // ref_lf_deltas
+            for (int i = 0; i < 4; i++) {
+                bc_b(ref_lf_deltas_update[i]);
+                if (current->ref_lf_deltas_update[i])
+                    bc_ss(6, ref_lf_deltas[i], 1, i);
+            }
+            // mode_lf_deltas
+            for (int i = 0; i < 4; i++) {
+                bc_b(mode_lf_deltas_update[i]);
+                if (current->mode_lf_deltas_update[i])
+                    bc_ss(6, mode_lf_deltas[i], 1, i);
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int FUNC(quantization_params)(CodedBitstreamContext *ctx,
+                                     CBSVP8BoolCodingRW *bool_coding_rw,
+                                     VP8RawFrameHeader *current)
+{
+    bc_f(7, base_qindex);
+
+    bc_b(y1dc_delta_q_present);
+    if (current->y1dc_delta_q_present)
+        bc_s(4, y1dc_delta_q);
+
+    bc_b(y2dc_delta_q_present);
+    if (current->y2dc_delta_q_present)
+        bc_s(4, y2dc_delta_q);
+
+    bc_b(y2ac_delta_q_present);
+    if (current->y2ac_delta_q_present)
+        bc_s(4, y2ac_delta_q);
+
+    bc_b(uvdc_delta_q_present);
+    if (current->uvdc_delta_q_present)
+        bc_s(4, uvdc_delta_q);
+
+    bc_b(uvac_delta_q_present);
+    if (current->uvac_delta_q_present)
+        bc_s(4, uvac_delta_q);
+
+    return 0;
+}
+
+static int FUNC(update_token_probs)(CodedBitstreamContext *ctx,
+                                    CBSVP8BoolCodingRW *bool_coding_rw,
+                                    VP8RawFrameHeader *current)
+{
+    for (int i = 0; i < 4; ++i) {
+        for (int j = 0; j < 8; ++j) {
+            for (int k = 0; k < 3; ++k) {
+                for (int l = 0; l < 11; ++l) {
+                    bc_b_prob(vp8_token_update_probs[i][j][k][l],
+                              coeff_prob_update[i][j][k][l]);
+                    if (current->coeff_prob_update[i][j][k][l])
+                        bc_fs(8, coeff_prob[i][j][k][l], 4, i, j, k, l);
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int FUNC(update_mv_probs)(CodedBitstreamContext *ctx,
+                                 CBSVP8BoolCodingRW *bool_coding_rw,
+                                 VP8RawFrameHeader *current)
+{
+    for (int i = 0; i < 2; ++i) {
+        for (int j = 0; j < 19; ++j) {
+            bc_b(mv_prob_update[i][j]);
+            if (current->mv_prob_update[i][j])
+                bc_fs(7, mv_prob[i][j], 2, i, j);
+        }
+    }
+
+    return 0;
+}
+
+static int FUNC(frame_tag)(CodedBitstreamContext *ctx, RWContext *rw,
+                           VP8RawFrameHeader *current)
+{
+    f(1, frame_type);
+    f(3, profile);
+    f(1, show_frame);
+    f(19, first_partition_length_in_bytes);
+
+    if (current->frame_type == VP8_KEY_FRAME) {
+        fixed(8, start_code_0, VP8_START_CODE_0);
+        fixed(8, start_code_1, VP8_START_CODE_1);
+        fixed(8, start_code_2, VP8_START_CODE_2);
+
+        f(14, width);
+        f(2, horizontal_scale);
+        f(14, height);
+        f(2, vertical_scale);
+    }
+
+    return 0;
+}
+
+static int FUNC(frame_header)(CodedBitstreamContext *ctx,
+                              CBSVP8BoolCodingRW *bool_coding_rw,
+                              VP8RawFrameHeader *current)
+{
+    if (current->frame_type == VP8_KEY_FRAME) {
+        bc_f(1, color_space);
+        bc_f(1, clamping_type);
+    }
+
+    bc_f(1, segmentation_enable);
+    if (current->segmentation_enable)
+        CHECK(FUNC(update_segmentation)(ctx, bool_coding_rw, current));
+
+    bc_f(1, loop_filter_type);
+    bc_f(6, loop_filter_level);
+    bc_f(3, loop_filter_sharpness);
+
+    CHECK(FUNC(mode_ref_lf_deltas)(ctx, bool_coding_rw, current));
+
+    bc_f(2, log2_token_partitions);
+
+    CHECK(FUNC(quantization_params)(ctx, bool_coding_rw, current));
+
+    if (current->frame_type != VP8_KEY_FRAME) {
+        bc_f(1, refresh_golden_frame);
+        bc_f(1, refresh_alternate_frame);
+        if (!current->refresh_golden_frame)
+            bc_f(2, copy_buffer_to_golden);
+        if (!current->refresh_alternate_frame)
+            bc_f(2, copy_buffer_to_alternate);
+        bc_f(1, ref_frame_sign_bias_golden);
+        bc_f(1, ref_frame_sign_bias_alternate);
+    }
+    bc_f(1, refresh_entropy_probs);
+    if (current->frame_type != VP8_KEY_FRAME)
+        bc_f(1, refresh_last_frame);
+
+    CHECK(FUNC(update_token_probs)(ctx, bool_coding_rw, current));
+
+    bc_f(1, mb_no_skip_coeff);
+    if (current->mb_no_skip_coeff)
+        bc_f(8, prob_skip_false);
+
+    if (current->frame_type != VP8_KEY_FRAME) {
+        bc_f(8, prob_intra);
+        bc_f(8, prob_last);
+        bc_f(8, prob_golden);
+
+        // intra_16x16_prob
+        bc_b(intra_16x16_prob_update);
+        if (current->intra_16x16_prob_update)
+            for (int i = 0; i < 4; i++)
+                bc_fs(8, intra_16x16_prob[i], 1, i);
+
+        // intra_chroma_prob
+        bc_b(intra_chrome_prob_update);
+        if (current->intra_chrome_prob_update)
+            for (int i = 0; i < 3; i++)
+                bc_fs(8, intra_chrome_prob[i], 1, i);
+
+        CHECK(FUNC(update_mv_probs)(ctx, bool_coding_rw, current));
+    }
+
+    return 0;
+}
+
+static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw,
+                                     VP8RawFrame *current)
+{
+    HEADER("Frame");
+
+    CHECK(FUNC(frame_tag)(ctx, rw, &current->header));
+
+    return 0;
+}
+
+static int FUNC(compressed_header)(CodedBitstreamContext *ctx,
+                                   CBSVP8BoolCodingRW *bool_coding_rw,
+                                   VP8RawFrame *current)
+{
+    CHECK(FUNC(frame_header)(ctx, bool_coding_rw, &current->header));
+
+    return 0;
+}