[vlc-commits] [Git][videolan/vlc][master] vpx: mux WebP in RIFF container
Tristan Matthews (@tmatth)
gitlab at videolan.org
Tue Jan 31 15:26:49 UTC 2023
Tristan Matthews pushed to branch master at VideoLAN / VLC
Commits:
3183c561 by Tristan Matthews at 2023-01-31T15:11:55+00:00
vpx: mux WebP in RIFF container
For now it is always the WebP Simple File Format (lossy):
https://developers.google.com/speed/webp/docs/riff_container#simple_file_format_lossy
- - - - -
1 changed file:
- modules/codec/vpx.c
Changes:
=====================================
modules/codec/vpx.c
=====================================
@@ -467,6 +467,23 @@ error:
return VLC_EGENERIC;
}
+static const uint32_t webp_simple_lossy_header[5] = {
+ VLC_FOURCC('R', 'I', 'F', 'F'),
+ 0, /* TBD: total size of VP8 data plus 12 bytes for WEBP fourcc + VP8 ChunkHeader */
+ VLC_FOURCC('W', 'E', 'B', 'P'),
+ VLC_FOURCC('V', 'P', '8', ' '),
+ 0, /* TBD: total size of VP8 data */
+};
+
+static void webp_write_header(uint8_t *p_header, uint32_t i_size, size_t i_header_size)
+{
+ assert(i_header_size == sizeof(webp_simple_lossy_header));
+
+ memcpy(p_header, webp_simple_lossy_header, i_header_size);
+ SetDWLE(p_header + 1*sizeof(uint32_t), i_size + 4 + 8);
+ SetDWLE(p_header + 4*sizeof(uint32_t), i_size);
+}
+
/****************************************************************************
* Encode: the whole thing
****************************************************************************/
@@ -508,12 +525,27 @@ static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
const vpx_codec_cx_pkt_t *pkt = NULL;
vpx_codec_iter_t iter = NULL;
block_t *p_out = NULL;
+
+ /* WebP container specific context */
+ uint32_t i_vp8_data_size = 0;
+ uint8_t *p_header = NULL;
+ const bool b_is_webp = p_enc->fmt_out.i_codec == VLC_CODEC_WEBP;
+ static const size_t i_webp_header_size = sizeof(webp_simple_lossy_header);
+
while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL)
{
if (pkt->kind == VPX_CODEC_CX_FRAME_PKT)
{
+ size_t i_block_sz = pkt->data.frame.sz;
+ const bool b_needs_padding_byte = b_is_webp && (pkt->data.frame.sz & 1);
int keyframe = pkt->data.frame.flags & VPX_FRAME_IS_KEY;
- block_t *p_block = block_Alloc(pkt->data.frame.sz);
+
+ if (b_is_webp && p_header == NULL) {
+ i_block_sz += i_webp_header_size;
+ i_block_sz += b_needs_padding_byte;
+ }
+
+ block_t *p_block = block_Alloc(i_block_sz);
if (unlikely(p_block == NULL))
{
block_ChainRelease(p_out);
@@ -521,13 +553,33 @@ static block_t *Encode(encoder_t *p_enc, picture_t *p_pict)
break;
}
- memcpy(p_block->p_buffer, pkt->data.frame.buf, pkt->data.frame.sz);
+ uint8_t *p_buffer = p_block->p_buffer;
+
+ /* Leave room at the beginning for the WebP header data. */
+ if (b_is_webp && p_header == NULL) {
+ p_header = p_buffer;
+ p_buffer += i_webp_header_size;
+ i_vp8_data_size += pkt->data.frame.sz;
+ }
+
+ memcpy(p_buffer, pkt->data.frame.buf, pkt->data.frame.sz);
p_block->i_dts = p_block->i_pts = pkt->data.frame.pts;
if (keyframe)
p_block->i_flags |= BLOCK_FLAG_TYPE_I;
+
+ /* If Chunk Size is odd, a single padding byte -- that MUST be 0 to
+ conform with RIFF -- is added. */
+ if (b_needs_padding_byte)
+ p_block->p_buffer[i_block_sz - 1] = 0;
+
block_ChainAppend(&p_out, p_block);
}
}
+
+ /* For WebP, now that we have the total size, write the RIFF header. */
+ if (b_is_webp && p_header)
+ webp_write_header(p_header, i_vp8_data_size, i_webp_header_size);
+
vpx_img_free(&img);
picture_Release(p_pict);
return p_out;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/3183c5615bed41bee5f431cd03ac4d2c1b91261d
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/3183c5615bed41bee5f431cd03ac4d2c1b91261d
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list