|
| 1 | +# Summary |
| 2 | + |
| 3 | +This RFC intends to faciliatet discussion to find a way to move away from storing codec identifiers as strings. This is to avoid string comparisons and remove some redundancies such as outputs defining their own codec enumerations. |
| 4 | + |
| 5 | +# Motivation |
| 6 | + |
| 7 | +String comparisons are slow, error prone (case sensitivity, typos, etc.), and generally ugly. Most outputs convert from strings to internal enumerations anyway which could be made redundant by providing them in the first place. |
| 8 | + |
| 9 | +# Overview |
| 10 | + |
| 11 | +There are two components to this RFC: Codec Identifier and Codec Tags. |
| 12 | +The former specifies a codec family such as H.264/AVC, while the latter specifies a specific variant used for the encoded bitstream. |
| 13 | + |
| 14 | +## Codec Tags |
| 15 | + |
| 16 | +Codec "tags" or FourCC codes (`uint32_t`) are used by containers such as MOV/MP4 or Enhanced FLV, and are used by some codecs to identify specific flavours or variants. |
| 17 | +For example, ProRes uses several different ones depending on the specific feature set used (ProRes LT/HQ/XQ/etc.). |
| 18 | +Currently support for this is hacked in by passing a value through `obs_data` objects, but this should be implemented natively. |
| 19 | + |
| 20 | +### Proposed API |
| 21 | + |
| 22 | +Codec tags can change depending on encoder configuration, and cannot be a static value in the `obs_encoder_info` struct, thus there needs to be a function that can be called to ask the encoder for the appropiate tag for its current configuration. |
| 23 | + |
| 24 | +- New API function: `uint32_t obs_encoder_get_codec_tag(obs_encoder_t *encoder)` |
| 25 | +- New `obs_encoder_info` struct member: `uint32_t (*codec_tag)(void *data)` |
| 26 | + |
| 27 | +For most codecs the implementation of the `codec_tag´ function may be ommited and a default value is provided by libobs. This default tag could be obtained from libavcodec via `av_codec_get_tag()` or hardcoded to the ones we currently use (i.e. `avc1` for H.264, `hvc1` for HEVC, `av01` for AV1). |
| 28 | + |
| 29 | +**Note:** FFmpeg currently has two separate codec tag lists, one for ISO-BMFF/QuickTime (MP4/MOV) and one for RIFF (e.g. AVI), this proposal would only implement the MOV/MP4 tags as the RIFF ones are not relevant to OBS outside of possibly DirectShow. |
| 30 | +We may elect to remove ambiguities by having a second paramter specifying a codec tag namespace, or explicitly naming the function to indicate that it returns ISO format tags. |
| 31 | + |
| 32 | +## Codec Identifier |
| 33 | + |
| 34 | +This RFC proposes there different methods, one of which should be agreed upon: |
| 35 | + |
| 36 | +### FFmpeg AVCodecID |
| 37 | + |
| 38 | +This approach would simply use `AVCodecID` enum defined in libavcodec. |
| 39 | + |
| 40 | +#### Advantages |
| 41 | + |
| 42 | +- libobs already links against libav* libraries so IDs can be used without many changes |
| 43 | +- Easy to use in FFmpeg muxer and FFmpeg-based outputs (e.g. SRT/RIST) |
| 44 | +- libav* functions available for converting from current string-based names to FFmpeg IDs |
| 45 | + |
| 46 | +#### Drawbacks |
| 47 | + |
| 48 | +- Not all modules that interface with video data or implement encoders currently depend on ffmpeg (e.g. obs-outputs, VideoToolbox) |
| 49 | +- While unlikely, it could happen that FFmpeg does not support a codec we want to support, or support is missing from an older version, e.g. on LTS releases |
| 50 | + |
| 51 | +### Codec Tags / FourCC |
| 52 | + |
| 53 | +In this case we define the aforementioned codec tag as the new identifier. |
| 54 | + |
| 55 | +#### Advantages |
| 56 | + |
| 57 | +- Avoids a secondary API for codec identifiers |
| 58 | +- FFmpeg's ISO/QuickTime tag list should support all codecs upstream OBS supports |
| 59 | + |
| 60 | +#### Drawbacks |
| 61 | + |
| 62 | +- Many codecs have more than one tag, which could require large if clauses and may still require mapping to an internal enumeration value |
| 63 | +- Codec support for ISO and QuickTime formats is limited |
| 64 | +- Tags are mostly intended to be opaque values that are relevant to the muxer, and probably shouldn't be used as a unqiue identifier for a codec family |
| 65 | + |
| 66 | +### OBS-specific IDs |
| 67 | + |
| 68 | +In this case we would define our own enumeration, for example: |
| 69 | +```c |
| 70 | +enum OBSCodecID { |
| 71 | + OBS_CODEC_INVALID = 0, |
| 72 | + OBS_CODEC_H264, |
| 73 | + OBS_CODEC_HEVC, |
| 74 | + OBS_CODEC_AV1, |
| 75 | + OBS_CODEC_PRORES, |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +#### Advantages |
| 80 | + |
| 81 | +- Simple enum in libobs |
| 82 | +- No external dependencies |
| 83 | + |
| 84 | +#### Drawbacks |
| 85 | + |
| 86 | +- Requires libobs API changes to add new codecs |
| 87 | +- Would prevent third-party plugins from adding codecs not supported by upstream OBS |
| 88 | + |
| 89 | +A potential workaround is to still have a fallback such as `OBS_CODEC_CUSTOM` which still allows passing a string to the muxer, which would need special support for handling codec string names which is probably undesireable. |
| 90 | + |
| 91 | +# Additional Information |
| 92 | + |
| 93 | +- FFmpeg Codec Defintions: https://github.com/FFmpeg/FFmpeg/blob/0ae157b3603f27d8057febd8f2680ac1030722ee/libavcodec/codec_id.h#L49 |
| 94 | +- RFC 6381, specifying the common use of ISO codec identifiers for MIME types: https://datatracker.ietf.org/doc/html/rfc6381 |
0 commit comments