diff --git a/draft-avtransport-spec.bs b/draft-avtransport-spec.bs index d14db28..48231b3 100644 --- a/draft-avtransport-spec.bs +++ b/draft-avtransport-spec.bs @@ -847,18 +847,21 @@ in the following manner: : STREAM_HEARING_IMPAIRED = 0x200 :: Stream is intended for hearing impaired audiences. - Note: If [=related_stream_id=] is not equal to [=stream_id=], both should be mixed in. + + Note: If [=related_stream_id=] is not equal to [=stream_id=], both should be mixed in. : STREAM_VISUALLY_IMPAIRED = 0x400 :: Stream is intended for visually impaired audiences. - Note: If [=related_stream_id=] is not equal to [=stream_id=], both should be mixed in. + + Note: If [=related_stream_id=] is not equal to [=stream_id=], both should be mixed in. : STREAM_NO_DIALOGUE = 0x800 :: Stream contains music and sound effects without voice. : STREAM_NON_DIEGETIC = 0x1000 :: Stream contains non-diegetic audio. - Note: If [=related_stream_id=] is not equal to [=stream_id=], both should be mixed in. + + Note: If [=related_stream_id=] is not equal to [=stream_id=], both should be mixed in. : STREAM_DESCRIPTIONS = 0x2000 :: Stream contains textual or spoken descriptions to the stream signalled in [=related_stream_id=]. @@ -1313,6 +1316,17 @@ the [[#codec-encapsulation]] addenda. :: Packet data is uncompressed : DATA_COMPRESSION_ZSTD = 0x1 :: Packet data is compressed with Zstandard, defined in IETF [[RFC8878]]. + + Note: Zstandard is a general purpose format, suitable for images, + audio, and binary data such as ICC or CUBE packets. Therefore, + it should be the preferred format for such payloads. + + : DATA_COMPRESSION_BROTLI = 0x2 + :: Packet data is compressed with Zstandard, defined in IETF [[RFC7932]]. + + Note: Brotli is more optimized for text rather than generic data, + and should be the preferred format for subtitles. Presently, it is + also more supported on the web. Any undefined values are hereby reserved and must not be present in a compliant @@ -1394,6 +1408,7 @@ FEC grouped streams MUST be registered first via a special packet: Indicates the ID for this FEC grouping.
+ Note: Must not overlap with [=stream_id=]. @@ -2061,6 +2076,7 @@ The following structure MUST be followed: The stream ID for which to make the font available. + Note: may be set to ''0xffff'' to make the font available for all streams. @@ -2415,7 +2431,9 @@ The [=colorspace=] field must be interpreted in the following way: :: Video contains [[CIE1931]] XYZ color data. : CSP_XYB = 0x6 :: Video contains XYB color data, as defined by [[ISO18181]]. - Note: [matrix] must be equal to ''0xFF'' and the [=custom_matrix=] must be a valid matrix to transform XYB into RGB. + + Note: [matrix] must be equal to ''0xFF'' and the [=custom_matrix=] must be a valid matrix to transform XYB into RGB. + : CSP_ICTCP = 0x5 :: Video contains [[BT2100]] ICtCp color data. : CSP_BAYER_BGGR = 0x6 @@ -2438,10 +2456,10 @@ The [=colorspace=] field must be interpreted in the following way: :: Video sample values contains the limited range of the [=bit_depth=]. Note: this describes the cannonical limited range representation: - (219 * E + 16) * 2([=bit_depth=]-8), - where E, the input range, is ''0.0'' to ''1.0'' for luma planes and - ''-0.5'' to ''0.5'' for chroma planes. This means, for 8-bits, the luma - range is 16-235 and the chroma range is 16-240. + (219 * E + 16) * 2([=bit_depth=]-8), + where E, the input range, is ''0.0'' to ''1.0'' for luma planes and + ''-0.5'' to ''0.5'' for chroma planes. This means, for 8-bits, the luma + range is 16-235 and the chroma range is 16-240. @@ -2466,7 +2484,7 @@ to interpret the value of [=field_id=] in stream data packet headers. : ILACE_PROG = 0x0 :: Video contains progressive data, or interlacing does not apply. - Note: in this mode, the [=field_id=] bit is free to use by users. Implementations must ignore it, and preserve it. + Note: in this mode, the [=field_id=] bit is free to use by users. Implementations must ignore it, and preserve it. : ILACE_TFF = 0x1 :: Video is interlaced. One [[#stream-data-packets]] packet per field. If the data packet's [=field_id=] bit is unset, indicates the field contained is the top field, otherwise it's the bottom field. @@ -2491,17 +2509,17 @@ the setting used, if the codec supports this. : CHROMA_POS_LEFT = 0x1 :: Chroma position is between 2 luma samples on different lines. - Note: This is the default chroma position for MPEG-2, H.263 with {{CHROMA_422}}, and H.264 with {{CHROMA_420}}. + Note: This is the default chroma position for MPEG-2, H.263 with {{CHROMA_422}}, and H.264 with {{CHROMA_420}}. : CHROMA_POS_CENTER = 0x2 :: Chroma position is in the middle between all neighbouring luma samples on 2 lines. - Note: This is the default chroma position for JPEG with {{CHROMA_420}}, and H.263 with {{CHROMA_420}}. + Note: This is the default chroma position for JPEG with {{CHROMA_420}}, and H.263 with {{CHROMA_420}}. : CHROMA_POS_TOPLEFT = 0x3 :: Chroma position coincides with top left's luma sample position. - Note: This is the default chroma position for MPEG-2 with {{CHROMA_422}}. + Note: This is the default chroma position for MPEG-2 with {{CHROMA_422}}. : CHROMA_POS_TOP = 0x4 :: Chroma position is between 2 luma samples on the same top line. diff --git a/libavtransport/output_packet.c b/libavtransport/output_packet.c index 5b46f4f..61d6835 100644 --- a/libavtransport/output_packet.c +++ b/libavtransport/output_packet.c @@ -28,10 +28,16 @@ #include "output_packet.h" +#include "../config.h" + #ifdef CONFIG_HAVE_LIBZSTD #include #endif +#ifdef CONFIG_HAVE_LIBBROTLI +#include +#endif + static inline int avt_send_pkt(union AVTPacketData pkt) { @@ -49,13 +55,21 @@ static inline int avt_interleave_start(AVTOutput *out, AVTStream *st, return 0; } +#ifdef CONFIG_HAVE_LIBBROTLI +static void avt_brotli_data_free(void *opaque, void *base_data) +{ + BrotliEncoderState *brotli_ctx = opaque; + BrotliEncoderDestroyInstance(brotli_ctx); +} +#endif + static inline int avt_payload_compress(AVTOutput *out, AVTBuffer **data, enum AVTPktDescriptors desc, enum AVTDataCompression *data_compression) { int err = 0; - int lvl = 0; + int lvl = -1; enum AVTDataCompression method = AVT_DATA_COMPRESSION_NONE; switch (method) { @@ -71,7 +85,8 @@ static inline int avt_payload_compress(AVTOutput *out, if (!dst) return AVT_ERROR(ENOMEM); - size_t dst_len = ZSTD_compressCCtx(out->zstd_ctx, dst, dst_size, src, src_len, lvl); + size_t dst_len = ZSTD_compressCCtx(out->zstd_ctx, dst, dst_size, src, src_len, + lvl < 0 ? ZSTD_CLEVEL_DEFAULT : lvl); if (!dst_len) { avt_log(out, AVT_LOG_ERROR, "Error while compressing with ZSTD!\n"); err = AVT_ERROR(EINVAL); @@ -90,6 +105,44 @@ static inline int avt_payload_compress(AVTOutput *out, #else avt_log(out, AVT_LOG_ERROR, "ZSTD compression not enabled during build!\n"); err = AVT_ERROR(EINVAL); +#endif + break; + } + case AVT_DATA_COMPRESSION_BROTLI: { +#ifdef CONFIG_HAVE_LIBBROTLI + size_t src_len; + uint8_t *src = avt_buffer_get_data(*data, &src_len); + + size_t dst_size = BrotliEncoderMaxCompressedSize(src_len); + + /* TODO: use a buffer pool */ + uint8_t *dst = malloc(dst_size); + if (!dst) + return AVT_ERROR(ENOMEM); + + /* Brotli has a braindead advanced API that + * makes it really hard to use pooling. Since Brotli is mostly + * used by text, meh, good enough for now. */ + if (!BrotliEncoderCompress(lvl < 0 ? BROTLI_DEFAULT_QUALITY : lvl, + BROTLI_DEFAULT_WINDOW, BROTLI_DEFAULT_MODE, + src_len, src, &dst_size, dst)) { + avt_log(out, AVT_LOG_ERROR, "Error while compressing with Brotli!\n"); + err = AVT_ERROR(EINVAL); + free(dst); + break; + } + + AVTBuffer *tmp = avt_buffer_create(dst, dst_size, NULL, avt_buffer_default_free); + if (!tmp) { + free(dst); + err = AVT_ERROR(ENOMEM); + break; + } + + *data = tmp; +#else + avt_log(out, AVT_LOG_ERROR, "Brotli compression not enabled during build!\n"); + err = AVT_ERROR(EINVAL); #endif break; } diff --git a/meson.build b/meson.build index 7d640cb..93daa20 100644 --- a/meson.build +++ b/meson.build @@ -87,12 +87,14 @@ endif threads_dep = dependency('threads', required: true) uring_dep = dependency('liburing', required: false) zstd_dep = dependency('libzstd', required: false) +brotli_dep = dependency('libzstd', required: false) lib_deps = [ cc.find_library('m', required: true), threads_dep, uring_dep, zstd_dep, + brotli_dep, ] # Configure file @@ -111,6 +113,7 @@ conf.set('CONFIG_OUTPUT', get_option('output').auto()) conf.set('CONFIG_HAVE_LIBURING', uring_dep.found()) conf.set('CONFIG_HAVE_LIBZSTD', zstd_dep.found()) +conf.set('CONFIG_HAVE_LIBBROTLI', brotli_dep.found()) if get_option('assert') > -1 conf.set('CONFIG_ASSERT_LEVEL', get_option('assert'))