* [FFmpeg-devel] [RFC] C++
@ 2025-10-20 17:50 Tomas Härdin via ffmpeg-devel
2025-10-20 21:34 ` [FFmpeg-devel] " Neal Gompa via ffmpeg-devel
` (6 more replies)
0 siblings, 7 replies; 22+ messages in thread
From: Tomas Härdin via ffmpeg-devel @ 2025-10-20 17:50 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Tomas Härdin
[-- Attachment #1: Type: text/plain, Size: 2930 bytes --]
Hi
I'm writing this email to get a feel for how everyone feels about
making more use of C++ in the codebase. I am only proposing using C++
*internally*, and only where it makes sense. I am not suggesting a
"move" to C++, merely using features already present in the compilers
we target: gcc, clang and cl. The impedance mismatch should therefore
be small, and any missing compiler features should be caught by FATE.
Currently C++ use is quite limited in this project, but I see no reason
why this should be the case. doc/faq.texi makes mention of Linux'
reasons for avoiding C++, but FFmpeg is not Linux. For us ABI stability
and performance are the biggest issues. Stability can be ensured by
sticking with C for the API and disabling exceptions (or marking
relevant functions as noexcept). Performance may benefit in some cases.
This would have to be tested. Again, the most performance critical
parts can be kept as C (and asm).
My main motivation is to be able to use STL, which would simplify
string handling and memory management, and give us access to its data
structures. Manual memory management has its place, especially in lavc.
In lavf less so. RAII would do wonders in de-gotofying error handling.
Features like std::filesystem, std::chrono, std::thread etc abstract
away many OS particularities. Thorough STL-ification would render parts
of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
would have security benefits. Another reason is stronger typing, which
tends to reveal bugs.
I've targeted mxfdec.c as a proof-of-concept. See attached patch, which
compiles and passes fate-mxf. It is partly inspired by our decklink
binding. Particularly notable is the ability to resolve MXF structs
into MXFMetadataSetType at compile time, as well as resolving strong
references in a more type safe manner. This revealed an issue in
mxf_parse_structural_metadata() where MXFStructuralComponent* was
blindly cast to MXFTimecodeComponent*, which could cause code further
down to interpret the latter as the former, which is a not so obvious
bug that wouldn't be caught without this stronger typing.
I've not made use of STL in the attached patch because that requires
linking with libstdc++, which I couldn't be arsed to do. One practical
example where STL would come in handy is for my work on segmented
indexes. Specifically std::map and std::lower_bound. Various tables in
mxfdec.c could also be targets for turning into std::map or even
std::unordered_map. A quick experiment with callgrind suggests
mxf_read_header() might be speed up slightly with such a change.
Details like which version of C++ to use could be agreed on later if
people feel this is a good idea. Personally I favor using the most
recent version that our compiler suite supports. Lately I've been using
C++20 with icx (Intel's compiler) which has been quite pleasant.
/Tomas
[-- Attachment #2: 0001-lavf-mxfdec-C-ify.patch --]
[-- Type: text/x-patch, Size: 60582 bytes --]
From c4b4532288904bacafa9253f0ebac4da285bbc59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= <git@haerdin.se>
Date: Mon, 20 Oct 2025 11:29:07 +0200
Subject: [PATCH] lavf/mxfdec: C++ify
---
libavformat/Makefile | 2 +-
libavformat/mxf.h | 1 +
libavformat/{mxfdec.c => mxfdec.cpp} | 419 +++++++++++++--------------
libavformat/mxfdec.h | 82 ++++++
libavformat/mxfdec_c.c | 53 ++++
5 files changed, 334 insertions(+), 223 deletions(-)
rename libavformat/{mxfdec.c => mxfdec.cpp} (93%)
create mode 100644 libavformat/mxfdec.h
create mode 100644 libavformat/mxfdec_c.c
diff --git a/libavformat/Makefile b/libavformat/Makefile
index ed93458f03..fe195e95b3 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -413,7 +413,7 @@ OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o
OBJS-$(CONFIG_MUSX_DEMUXER) += musx.o
OBJS-$(CONFIG_MV_DEMUXER) += mvdec.o
OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o
-OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o avlanguage.o
+OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxfdec_c.o mxf.o avlanguage.o
OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o
OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o
OBJS-$(CONFIG_NC_DEMUXER) += ncdec.o
diff --git a/libavformat/mxf.h b/libavformat/mxf.h
index 673703f6bc..54761c5a43 100644
--- a/libavformat/mxf.h
+++ b/libavformat/mxf.h
@@ -55,6 +55,7 @@ enum MXFMetadataSetType {
GroupOfSoundfieldGroupsLabelSubDescriptor,
FFV1SubDescriptor,
JPEG2000SubDescriptor,
+ Partition,
MetadataSetTypeNB
};
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.cpp
similarity index 93%
rename from libavformat/mxfdec.c
rename to libavformat/mxfdec.cpp
index dc5dff651a..b6eb63fa9b 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.cpp
@@ -47,6 +47,7 @@
#include <inttypes.h>
#include <time.h>
+extern "C" {
#include "libavutil/aes.h"
#include "libavutil/avstring.h"
#include "libavutil/mastering_display_metadata.h"
@@ -65,7 +66,8 @@
#include "avio_internal.h"
#include "demux.h"
#include "internal.h"
-#include "mxf.h"
+#include "mxfdec.h"
+}
#define MXF_MAX_CHUNK_SIZE (32 << 20)
#define RUN_IN_MAX (65535+1) // S377m-2004 section 5.5 and S377-1-2009 section 6.5, the +1 is to be slightly more tolerant
@@ -76,20 +78,6 @@ typedef enum {
Footer
} MXFPartitionType;
-typedef enum {
- OP1a = 1,
- OP1b,
- OP1c,
- OP2a,
- OP2b,
- OP2c,
- OP3a,
- OP3b,
- OP3c,
- OPAtom,
- OPSONYOpt, /* FATE sample, violates the spec in places */
-} MXFOP;
-
typedef enum {
UnknownWrapped = 0,
FrameWrapped,
@@ -112,6 +100,8 @@ typedef struct MXFPartition {
int64_t pack_ofs; ///< absolute offset of pack in file, including run-in
int64_t body_offset;
KLVPacket first_essence_klv;
+
+ static constexpr MXFMetadataSetType metadata_set_type = Partition;
} MXFPartition;
typedef struct MXFMetadataSet {
@@ -119,14 +109,11 @@ typedef struct MXFMetadataSet {
uint64_t partition_score;
} MXFMetadataSet;
-typedef struct MXFMetadataSetGroup {
- MXFMetadataSet **metadata_sets;
- int metadata_sets_count;
-} MXFMetadataSetGroup;
-
typedef struct MXFCryptoContext {
MXFMetadataSet meta;
UID source_container_ul;
+
+ static constexpr MXFMetadataSetType metadata_set_type = CryptoContext;
} MXFCryptoContext;
typedef struct MXFStructuralComponent {
@@ -139,6 +126,10 @@ typedef struct MXFStructuralComponent {
int source_track_id;
} MXFStructuralComponent;
+struct MXFSourceClip : public MXFStructuralComponent {
+ static constexpr MXFMetadataSetType metadata_set_type = SourceClip;
+};
+
typedef struct MXFSequence {
MXFMetadataSet meta;
UID data_definition_ul;
@@ -146,6 +137,8 @@ typedef struct MXFSequence {
int structural_components_count;
int64_t duration;
uint8_t origin;
+
+ static constexpr MXFMetadataSetType metadata_set_type = Sequence;
} MXFSequence;
typedef struct MXFTimecodeComponent {
@@ -154,27 +147,35 @@ typedef struct MXFTimecodeComponent {
int start_frame;
struct AVRational rate;
AVTimecode tc;
+
+ static constexpr MXFMetadataSetType metadata_set_type = TimecodeComponent;
} MXFTimecodeComponent;
-typedef struct {
+struct MXFPulldownComponent {
MXFMetadataSet meta;
UID input_segment_ref;
-} MXFPulldownComponent;
-typedef struct {
+ static constexpr MXFMetadataSetType metadata_set_type = PulldownComponent;
+};
+
+struct MXFEssenceGroup {
MXFMetadataSet meta;
UID *structural_components_refs;
int structural_components_count;
int64_t duration;
-} MXFEssenceGroup;
-typedef struct {
+ static constexpr MXFMetadataSetType metadata_set_type = EssenceGroup;
+};
+
+struct MXFTaggedValue {
MXFMetadataSet meta;
char *name;
char *value;
-} MXFTaggedValue;
-typedef struct {
+ static constexpr MXFMetadataSetType metadata_set_type = TaggedValue;
+};
+
+struct MXFTrack {
MXFMetadataSet meta;
MXFSequence *sequence; /* mandatory, and only one */
UID sequence_ref;
@@ -189,7 +190,9 @@ typedef struct {
int body_sid;
MXFWrappingScheme wrapping;
int edit_units_per_packet; /* how many edit units to read at a time (PCM, ClipWrapped) */
-} MXFTrack;
+
+ static constexpr MXFMetadataSetType metadata_set_type = Track;
+};
typedef struct MXFDescriptor {
MXFMetadataSet meta;
@@ -230,8 +233,14 @@ typedef struct MXFDescriptor {
size_t mastering_size;
AVContentLightMetadata *coll;
size_t coll_size;
+
+ static constexpr MXFMetadataSetType metadata_set_type = Descriptor;
} MXFDescriptor;
+struct MXFMultipleDescriptor : public MXFDescriptor {
+ static constexpr MXFMetadataSetType metadata_set_type = MultipleDescriptor;
+};
+
typedef struct MXFMCASubDescriptor {
MXFMetadataSet meta;
UID uid;
@@ -244,10 +253,24 @@ typedef struct MXFMCASubDescriptor {
char *language;
} MXFMCASubDescriptor;
+struct MXFAudioChannelLabelSubDescriptor : public MXFMCASubDescriptor {
+ static constexpr MXFMetadataSetType metadata_set_type = AudioChannelLabelSubDescriptor;
+};
+
+struct MXFGroupOfSoundfieldGroupsLabelSubDescriptor : public MXFMCASubDescriptor {
+ static constexpr MXFMetadataSetType metadata_set_type = GroupOfSoundfieldGroupsLabelSubDescriptor;
+};
+
+struct MXFSoundfieldGroupLabelSubDescriptor : public MXFMCASubDescriptor {
+ static constexpr MXFMetadataSetType metadata_set_type = SoundfieldGroupLabelSubDescriptor;
+};
+
typedef struct MXFFFV1SubDescriptor {
MXFMetadataSet meta;
uint8_t *extradata;
int extradata_size;
+
+ static constexpr MXFMetadataSetType metadata_set_type = FFV1SubDescriptor;
} MXFFFV1SubDescriptor;
typedef struct MXFIndexTableSegment {
@@ -263,6 +286,8 @@ typedef struct MXFIndexTableSegment {
uint64_t *stream_offset_entries;
int nb_index_entries;
int64_t offset;
+
+ static constexpr MXFMetadataSetType metadata_set_type = IndexTableSegment;
} MXFIndexTableSegment;
typedef struct MXFPackage {
@@ -277,12 +302,22 @@ typedef struct MXFPackage {
int comment_count;
} MXFPackage;
+struct MXFMaterialPackage : public MXFPackage {
+ static constexpr MXFMetadataSetType metadata_set_type = MaterialPackage;
+};
+
+struct MXFSourcePackage : public MXFPackage {
+ static constexpr MXFMetadataSetType metadata_set_type = SourcePackage;
+};
+
typedef struct MXFEssenceContainerData {
MXFMetadataSet meta;
UID package_uid;
UID package_ul;
int index_sid;
int body_sid;
+
+ static constexpr MXFMetadataSetType metadata_set_type = EssenceContainerData;
} MXFEssenceContainerData;
/* decoded index table */
@@ -298,32 +333,6 @@ typedef struct MXFIndexTable {
int8_t *offsets; /* temporal offsets for display order to stored order conversion */
} MXFIndexTable;
-typedef struct MXFContext {
- const AVClass *class; /**< Class for private options. */
- MXFPartition *partitions;
- unsigned partitions_count;
- MXFOP op;
- UID *packages_refs;
- int packages_count;
- UID *essence_container_data_refs;
- int essence_container_data_count;
- MXFMetadataSetGroup metadata_set_groups[MetadataSetTypeNB];
- AVFormatContext *fc;
- struct AVAES *aesc;
- uint8_t *local_tags;
- int local_tags_count;
- uint64_t footer_partition;
- KLVPacket current_klv_data;
- int run_in;
- MXFPartition *current_partition;
- int parsing_backward;
- int64_t last_forward_tell;
- int last_forward_partition;
- int nb_index_tables;
- MXFIndexTable *index_tables;
- int eia608_extract;
-} MXFContext;
-
/* NOTE: klv_offset is not set (-1) for local keys */
typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset);
@@ -511,7 +520,7 @@ static int klv_read_packet(MXFContext *mxf, KLVPacket *klv, AVIOContext *pb)
static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv, int body_sid)
{
for (int i = 0; i < s->nb_streams; i++) {
- MXFTrack *track = s->streams[i]->priv_data;
+ MXFTrack *track = (MXFTrack*)s->streams[i]->priv_data;
/* SMPTE 379M 7.3 */
if (track && (!body_sid || !track->body_sid || track->body_sid == body_sid) && !memcmp(klv->key + sizeof(mxf_essence_element_key), track->track_number, sizeof(track->track_number)))
return i;
@@ -654,7 +663,7 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt,
static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv)
{
static const uint8_t checkv[16] = {0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b};
- MXFContext *mxf = s->priv_data;
+ MXFContext *mxf = (MXFContext*)s->priv_data;
AVIOContext *pb = s->pb;
int64_t end = avio_tell(pb) + klv->length;
int64_t size;
@@ -725,7 +734,7 @@ static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv
static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFContext *mxf = arg;
+ MXFContext *mxf = (MXFContext*)arg;
int item_num = avio_rb32(pb);
int item_len = avio_rb32(pb);
@@ -741,7 +750,7 @@ static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, U
av_log(mxf->fc, AV_LOG_VERBOSE, "Multiple primer packs\n");
av_free(mxf->local_tags);
mxf->local_tags_count = 0;
- mxf->local_tags = av_calloc(item_num, item_len);
+ mxf->local_tags = (uint8_t*)av_calloc(item_num, item_len);
if (!mxf->local_tags)
return AVERROR(ENOMEM);
mxf->local_tags_count = item_num;
@@ -751,7 +760,7 @@ static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, U
static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFContext *mxf = arg;
+ MXFContext *mxf = (MXFContext*)arg;
AVFormatContext *s = mxf->fc;
MXFPartition *partition, *tmp_part;
UID op;
@@ -765,7 +774,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
av_assert0(klv_offset >= mxf->run_in);
- tmp_part = av_realloc_array(mxf->partitions, mxf->partitions_count + 1, sizeof(*mxf->partitions));
+ tmp_part = (MXFPartition*)av_realloc_array(mxf->partitions, mxf->partitions_count + 1, sizeof(*mxf->partitions));
if (!tmp_part)
return AVERROR(ENOMEM);
mxf->partitions = tmp_part;
@@ -980,7 +989,7 @@ static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set,
static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFCryptoContext *cryptocontext = arg;
+ MXFCryptoContext *cryptocontext = (MXFCryptoContext*)arg;
if (size != 16)
return AVERROR_INVALIDDATA;
if (IS_KLV_KEY(uid, mxf_crypto_source_container_ul))
@@ -988,6 +997,16 @@ static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, i
return 0;
}
+template<typename T> bool mxf_malloc_array(int count, T* &t) {
+ t = (T*)av_malloc_array(count, sizeof(T));
+ return t != NULL;
+}
+
+template<typename T> bool mxf_calloc(int count, T* &t) {
+ t = (T*)av_calloc(count, sizeof(T));
+ return t != NULL;
+}
+
static int mxf_read_strong_ref_array(AVIOContext *pb, UID **refs, int *count)
{
int64_t ret;
@@ -999,8 +1018,7 @@ static int mxf_read_strong_ref_array(AVIOContext *pb, UID **refs, int *count)
*count = c;
av_free(*refs);
- *refs = av_malloc_array(*count, sizeof(UID));
- if (!*refs) {
+ if (!mxf_malloc_array(*count, *refs)) {
*count = 0;
return AVERROR(ENOMEM);
}
@@ -1024,7 +1042,7 @@ static inline int mxf_read_us_ascii_string(AVIOContext *pb, int size, char** str
buf_size = size + 1;
av_free(*str);
- *str = av_malloc(buf_size);
+ *str = (char*)av_malloc(buf_size);
if (!*str)
return AVERROR(ENOMEM);
@@ -1048,7 +1066,7 @@ static inline int mxf_read_utf16_string(AVIOContext *pb, int size, char** str, i
buf_size = size + size / 2 + 1;
av_free(*str);
- *str = av_malloc(buf_size);
+ *str = (char*)av_malloc(buf_size);
if (!*str)
return AVERROR(ENOMEM);
@@ -1076,7 +1094,7 @@ READ_STR16(le, 0)
static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFContext *mxf = arg;
+ MXFContext *mxf = (MXFContext*)arg;
switch (tag) {
case 0x1901:
if (mxf->packages_refs)
@@ -1090,7 +1108,7 @@ static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int siz
static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFStructuralComponent *source_clip = arg;
+ MXFStructuralComponent *source_clip = (MXFStructuralComponent*)arg;
switch(tag) {
case 0x0202:
source_clip->duration = avio_rb64(pb);
@@ -1112,7 +1130,7 @@ static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, U
static int mxf_read_timecode_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFTimecodeComponent *mxf_timecode = arg;
+ MXFTimecodeComponent *mxf_timecode = (MXFTimecodeComponent*)arg;
switch(tag) {
case 0x1501:
mxf_timecode->start_frame = avio_rb64(pb);
@@ -1129,7 +1147,7 @@ static int mxf_read_timecode_component(void *arg, AVIOContext *pb, int tag, int
static int mxf_read_pulldown_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFPulldownComponent *mxf_pulldown = arg;
+ MXFPulldownComponent *mxf_pulldown = (MXFPulldownComponent*)arg;
switch(tag) {
case 0x0d01:
avio_read(pb, mxf_pulldown->input_segment_ref, 16);
@@ -1140,7 +1158,7 @@ static int mxf_read_pulldown_component(void *arg, AVIOContext *pb, int tag, int
static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFTrack *track = arg;
+ MXFTrack *track = (MXFTrack*)arg;
switch(tag) {
case 0x4801:
track->track_id = avio_rb32(pb);
@@ -1164,7 +1182,7 @@ static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid
static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFSequence *sequence = arg;
+ MXFSequence *sequence = (MXFSequence*)arg;
switch(tag) {
case 0x0202:
sequence->duration = avio_rb64(pb);
@@ -1184,7 +1202,7 @@ static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID
static int mxf_read_essence_group(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFEssenceGroup *essence_group = arg;
+ MXFEssenceGroup *essence_group = (MXFEssenceGroup*)arg;
switch (tag) {
case 0x0202:
essence_group->duration = avio_rb64(pb);
@@ -1198,7 +1216,7 @@ static int mxf_read_essence_group(void *arg, AVIOContext *pb, int tag, int size,
static int mxf_read_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFPackage *package = arg;
+ MXFPackage *package = (MXFPackage*)arg;
switch(tag) {
case 0x4403:
return mxf_read_strong_ref_array(pb, &package->tracks_refs,
@@ -1222,7 +1240,7 @@ static int mxf_read_package(void *arg, AVIOContext *pb, int tag, int size, UID u
static int mxf_read_essence_container_data(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFEssenceContainerData *essence_data = arg;
+ MXFEssenceContainerData *essence_data = (MXFEssenceContainerData*)arg;
switch(tag) {
case 0x2701:
/* linked package umid UMID */
@@ -1256,9 +1274,9 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg
if(segment->nb_index_entries && length < 11)
return AVERROR_INVALIDDATA;
- if (!FF_ALLOC_TYPED_ARRAY(segment->temporal_offset_entries, segment->nb_index_entries) ||
- !FF_ALLOC_TYPED_ARRAY(segment->flag_entries , segment->nb_index_entries) ||
- !FF_ALLOC_TYPED_ARRAY(segment->stream_offset_entries , segment->nb_index_entries)) {
+ if (!mxf_malloc_array(segment->nb_index_entries, segment->temporal_offset_entries) ||
+ !mxf_malloc_array(segment->nb_index_entries, segment->flag_entries) ||
+ !mxf_malloc_array(segment->nb_index_entries, segment->stream_offset_entries)) {
av_freep(&segment->temporal_offset_entries);
av_freep(&segment->flag_entries);
return AVERROR(ENOMEM);
@@ -1278,7 +1296,7 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg
static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFIndexTableSegment *segment = arg;
+ MXFIndexTableSegment *segment = (MXFIndexTableSegment*)arg;
switch(tag) {
case 0x3F05:
segment->edit_unit_byte_count = avio_rb32(pb);
@@ -1338,7 +1356,7 @@ static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor)
static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFDescriptor *descriptor = arg;
+ MXFDescriptor *descriptor = (MXFDescriptor*)arg;
int entry_count, entry_size;
switch(tag) {
@@ -1441,7 +1459,7 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int
av_log(NULL, AV_LOG_WARNING, "Duplicate sony_mpeg4_extradata\n");
av_free(descriptor->extradata);
descriptor->extradata_size = 0;
- descriptor->extradata = av_malloc(size);
+ descriptor->extradata = (uint8_t*)av_malloc(size);
if (!descriptor->extradata)
return AVERROR(ENOMEM);
descriptor->extradata_size = size;
@@ -1513,7 +1531,7 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int
static int mxf_read_mca_sub_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFMCASubDescriptor *mca_sub_descriptor = arg;
+ MXFMCASubDescriptor *mca_sub_descriptor = (MXFMCASubDescriptor*)arg;
if (IS_KLV_KEY(uid, mxf_mca_label_dictionary_id))
avio_read(pb, mca_sub_descriptor->mca_label_dictionary_id, 16);
@@ -1538,14 +1556,14 @@ static int mxf_read_mca_sub_descriptor(void *arg, AVIOContext *pb, int tag, int
static int mxf_read_ffv1_sub_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFFFV1SubDescriptor *ffv1_sub_descriptor = arg;
+ MXFFFV1SubDescriptor *ffv1_sub_descriptor = (MXFFFV1SubDescriptor*)arg;
if (IS_KLV_KEY(uid, mxf_ffv1_extradata) && size <= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE ) {
if (ffv1_sub_descriptor->extradata)
av_log(NULL, AV_LOG_WARNING, "Duplicate ffv1_extradata\n");
av_free(ffv1_sub_descriptor->extradata);
ffv1_sub_descriptor->extradata_size = 0;
- ffv1_sub_descriptor->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
+ ffv1_sub_descriptor->extradata = (uint8_t*)av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!ffv1_sub_descriptor->extradata)
return AVERROR(ENOMEM);
ffv1_sub_descriptor->extradata_size = size;
@@ -1557,7 +1575,7 @@ static int mxf_read_ffv1_sub_descriptor(void *arg, AVIOContext *pb, int tag, int
static int mxf_read_indirect_value(void *arg, AVIOContext *pb, int size)
{
- MXFTaggedValue *tagged_value = arg;
+ MXFTaggedValue *tagged_value = (MXFTaggedValue*)arg;
uint8_t key[17];
int ret;
@@ -1578,7 +1596,7 @@ static int mxf_read_indirect_value(void *arg, AVIOContext *pb, int size)
static int mxf_read_tagged_value(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFTaggedValue *tagged_value = arg;
+ MXFTaggedValue *tagged_value = (MXFTaggedValue*)arg;
switch (tag){
case 0x5001:
return mxf_read_utf16be_string(pb, size, &tagged_value->name);
@@ -1612,15 +1630,15 @@ static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid)
return uls;
}
-static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMetadataSetType type)
+template<class T> T* mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref)
{
- MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[type];
+ MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[T::metadata_set_type];
if (!strong_ref)
return NULL;
for (int i = mg->metadata_sets_count - 1; i >= 0; i--)
if (!memcmp(*strong_ref, mg->metadata_sets[i]->uid, 16))
- return mg->metadata_sets[i];
+ return (T*)mg->metadata_sets[i];
return NULL;
}
@@ -1733,7 +1751,7 @@ static const MXFChannelOrderingUL mxf_channel_ordering[] = {
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x11,0x00,0x00 }, AV_CHAN_BOTTOM_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Below
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x12,0x00,0x00 }, AV_CHAN_BOTTOM_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Below
{ { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x13,0x00,0x00 }, AV_CHAN_BOTTOM_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Below
- { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB },
+ { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, (AVChannel)0, AV_AUDIO_SERVICE_TYPE_NB },
};
static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul)
@@ -1786,8 +1804,8 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment
if (!nb_segments)
return AVERROR_INVALIDDATA;
- if (!(unsorted_segments = av_calloc(nb_segments, sizeof(*unsorted_segments))) ||
- !(*sorted_segments = av_calloc(nb_segments, sizeof(**sorted_segments)))) {
+ if (!mxf_calloc(nb_segments, unsorted_segments) ||
+ !mxf_calloc(nb_segments, *sorted_segments)) {
av_freep(sorted_segments);
av_free(unsorted_segments);
return AVERROR(ENOMEM);
@@ -2037,10 +2055,10 @@ static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_ta
if (index_table->nb_ptses <= 0)
return 0;
- if (!(index_table->ptses = av_malloc_array(index_table->nb_ptses, sizeof(int64_t))) ||
- !(index_table->fake_index = av_calloc(index_table->nb_ptses, sizeof(AVIndexEntry))) ||
- !(index_table->offsets = av_malloc_array(index_table->nb_ptses, sizeof(int8_t))) ||
- !(flags = av_malloc_array(index_table->nb_ptses, sizeof(uint8_t)))) {
+ if (!mxf_malloc_array(index_table->nb_ptses, index_table->ptses) ||
+ !mxf_calloc(index_table->nb_ptses, index_table->fake_index) ||
+ !mxf_malloc_array(index_table->nb_ptses, index_table->offsets) ||
+ !mxf_malloc_array(index_table->nb_ptses, flags)) {
av_freep(&index_table->ptses);
av_freep(&index_table->fake_index);
av_freep(&index_table->offsets);
@@ -2155,9 +2173,7 @@ static int mxf_compute_index_tables(MXFContext *mxf)
}
}
- mxf->index_tables = av_calloc(mxf->nb_index_tables,
- sizeof(*mxf->index_tables));
- if (!mxf->index_tables) {
+ if (!mxf_calloc(mxf->nb_index_tables, mxf->index_tables)) {
av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n");
ret = AVERROR(ENOMEM);
goto finish_decoding_index;
@@ -2178,8 +2194,7 @@ static int mxf_compute_index_tables(MXFContext *mxf)
MXFTrack *mxf_track = NULL;
int64_t offset_temp = 0;
- t->segments = av_calloc(t->nb_segments, sizeof(*t->segments));
- if (!t->segments) {
+ if (!mxf_calloc(t->nb_segments, t->segments)) {
av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate IndexTableSegment"
" pointer array\n");
ret = AVERROR(ENOMEM);
@@ -2198,7 +2213,7 @@ static int mxf_compute_index_tables(MXFContext *mxf)
goto finish_decoding_index;
for (int k = 0; k < mxf->fc->nb_streams; k++) {
- MXFTrack *track = mxf->fc->streams[k]->priv_data;
+ MXFTrack *track = (MXFTrack*)mxf->fc->streams[k]->priv_data;
if (track && track->index_sid == t->index_sid) {
mxf_track = track;
break;
@@ -2305,27 +2320,23 @@ static int mxf_add_timecode_metadata(AVDictionary **pm, const char *key, AVTimec
static MXFTimecodeComponent* mxf_resolve_timecode_component(MXFContext *mxf, UID *strong_ref)
{
- MXFTimecodeComponent *timecode;
- MXFPulldownComponent *pulldown;
-
- timecode = mxf_resolve_strong_ref(mxf, strong_ref, TimecodeComponent);
+ MXFTimecodeComponent *timecode = mxf_resolve_strong_ref<MXFTimecodeComponent>(mxf, strong_ref);
if (timecode)
return timecode;
- pulldown = mxf_resolve_strong_ref(mxf, strong_ref, PulldownComponent);
+ MXFPulldownComponent *pulldown = mxf_resolve_strong_ref<MXFPulldownComponent>(mxf, strong_ref);
if (pulldown)
- return mxf_resolve_strong_ref(mxf, &pulldown->input_segment_ref, TimecodeComponent);
+ return mxf_resolve_strong_ref<MXFTimecodeComponent>(mxf, &pulldown->input_segment_ref);
return NULL;
}
-static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_ul, UID package_uid)
+static MXFSourcePackage* mxf_resolve_source_package(MXFContext *mxf, UID package_ul, UID package_uid)
{
- MXFPackage *package = NULL;
int i;
for (i = 0; i < mxf->packages_count; i++) {
- package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], SourcePackage);
+ MXFSourcePackage *package = mxf_resolve_strong_ref<MXFSourcePackage>(mxf, &mxf->packages_refs[i]);
if (!package)
continue;
@@ -2337,14 +2348,14 @@ static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_ul, U
static MXFDescriptor* mxf_resolve_descriptor(MXFContext *mxf, UID *strong_ref, int track_id)
{
- MXFDescriptor *descriptor = mxf_resolve_strong_ref(mxf, strong_ref, Descriptor);
+ MXFDescriptor *descriptor = mxf_resolve_strong_ref<MXFDescriptor>(mxf, strong_ref);
if (descriptor)
return descriptor;
- descriptor = mxf_resolve_strong_ref(mxf, strong_ref, MultipleDescriptor);
- if (descriptor) {
- for (int i = 0; i < descriptor->file_descriptors_count; i++) {
- MXFDescriptor *file_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->file_descriptors_refs[i], Descriptor);
+ MXFMultipleDescriptor *multi_descriptor = mxf_resolve_strong_ref<MXFMultipleDescriptor>(mxf, strong_ref);
+ if (multi_descriptor) {
+ for (int i = 0; i < multi_descriptor->file_descriptors_count; i++) {
+ MXFDescriptor *file_descriptor = mxf_resolve_strong_ref<MXFDescriptor>(mxf, &multi_descriptor->file_descriptors_refs[i]);
if (!file_descriptor) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve file descriptor strong ref\n");
@@ -2359,35 +2370,32 @@ static MXFDescriptor* mxf_resolve_descriptor(MXFContext *mxf, UID *strong_ref, i
return NULL;
}
-static MXFStructuralComponent* mxf_resolve_sourceclip(MXFContext *mxf, UID *strong_ref)
+static MXFSourceClip* mxf_resolve_sourceclip(MXFContext *mxf, UID *strong_ref)
{
- MXFStructuralComponent *component = NULL;
- MXFPackage *package = NULL;
- MXFDescriptor *descriptor = NULL;
- MXFEssenceGroup *essence_group;
int i;
- component = mxf_resolve_strong_ref(mxf, strong_ref, SourceClip);
- if (component)
- return component;
+ MXFSourceClip *source_clip = mxf_resolve_strong_ref<MXFSourceClip>(mxf, strong_ref);
+ if (source_clip)
+ return source_clip;
- essence_group = mxf_resolve_strong_ref(mxf, strong_ref, EssenceGroup);
+ MXFEssenceGroup *essence_group = mxf_resolve_strong_ref<MXFEssenceGroup>(mxf, strong_ref);
if (!essence_group)
return NULL;
/* essence groups contains multiple representations of the same media,
this return the first components with a valid Descriptor typically index 0 */
for (i =0; i < essence_group->structural_components_count; i++){
- component = mxf_resolve_strong_ref(mxf, &essence_group->structural_components_refs[i], SourceClip);
- if (!component)
+ source_clip = mxf_resolve_strong_ref<MXFSourceClip>(mxf, &essence_group->structural_components_refs[i]);
+ if (!source_clip)
continue;
- if (!(package = mxf_resolve_source_package(mxf, component->source_package_ul, component->source_package_uid)))
+ MXFSourcePackage *source_package;
+ if (!(source_package = mxf_resolve_source_package(mxf, source_clip->source_package_ul, source_clip->source_package_uid)))
continue;
- descriptor = mxf_resolve_strong_ref(mxf, &package->descriptor_ref, Descriptor);
+ MXFDescriptor *descriptor = mxf_resolve_strong_ref<MXFDescriptor>(mxf, &source_package->descriptor_ref);
if (descriptor)
- return component;
+ return source_clip;
}
return NULL;
@@ -2395,12 +2403,11 @@ static MXFStructuralComponent* mxf_resolve_sourceclip(MXFContext *mxf, UID *stro
static int mxf_parse_package_comments(MXFContext *mxf, AVDictionary **pm, MXFPackage *package)
{
- MXFTaggedValue *tag;
int i;
char *key = NULL;
for (i = 0; i < package->comment_count; i++) {
- tag = mxf_resolve_strong_ref(mxf, &package->comment_refs[i], TaggedValue);
+ MXFTaggedValue *tag = mxf_resolve_strong_ref<MXFTaggedValue>(mxf, &package->comment_refs[i]);
if (!tag || !tag->name || !tag->value)
continue;
@@ -2417,7 +2424,6 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t
{
MXFPackage *physical_package = NULL;
MXFTrack *physical_track = NULL;
- MXFStructuralComponent *sourceclip = NULL;
MXFTimecodeComponent *mxf_tc = NULL;
int i, j, k;
AVTimecode tc;
@@ -2425,7 +2431,7 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t
int64_t start_position;
for (i = 0; i < source_track->sequence->structural_components_count; i++) {
- sourceclip = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip);
+ MXFStructuralComponent *sourceclip = mxf_resolve_strong_ref<MXFSourceClip>(mxf, &source_track->sequence->structural_components_refs[i]);
if (!sourceclip)
continue;
@@ -2442,12 +2448,12 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t
* to the start_frame of the timecode component located on one of the tracks of the physical source package.
*/
for (j = 0; j < physical_package->tracks_count; j++) {
- if (!(physical_track = mxf_resolve_strong_ref(mxf, &physical_package->tracks_refs[j], Track))) {
+ if (!(physical_track = mxf_resolve_strong_ref<MXFTrack>(mxf, &physical_package->tracks_refs[j]))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
continue;
}
- if (!(physical_track->sequence = mxf_resolve_strong_ref(mxf, &physical_track->sequence_ref, Sequence))) {
+ if (!(physical_track->sequence = mxf_resolve_strong_ref<MXFSequence>(mxf, &physical_track->sequence_ref))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n");
continue;
}
@@ -2488,19 +2494,19 @@ static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_t
static int mxf_add_metadata_stream(MXFContext *mxf, MXFTrack *track)
{
- MXFStructuralComponent *component = NULL;
+ MXFSourceClip *source_clip = NULL;
const MXFCodecUL *codec_ul = NULL;
MXFPackage tmp_package;
AVStream *st;
int j;
for (j = 0; j < track->sequence->structural_components_count; j++) {
- component = mxf_resolve_sourceclip(mxf, &track->sequence->structural_components_refs[j]);
- if (!component)
+ source_clip = mxf_resolve_sourceclip(mxf, &track->sequence->structural_components_refs[j]);
+ if (!source_clip)
continue;
break;
}
- if (!component)
+ if (!source_clip)
return 0;
st = avformat_new_stream(mxf->fc, NULL);
@@ -2513,14 +2519,14 @@ static int mxf_add_metadata_stream(MXFContext *mxf, MXFTrack *track)
st->codecpar->codec_id = AV_CODEC_ID_NONE;
st->id = track->track_id;
- memcpy(&tmp_package.package_ul, component->source_package_ul, 16);
- memcpy(&tmp_package.package_uid, component->source_package_uid, 16);
+ memcpy(&tmp_package.package_ul, source_clip->source_package_ul, 16);
+ memcpy(&tmp_package.package_uid, source_clip->source_package_uid, 16);
mxf_add_umid_metadata(&st->metadata, "file_package_umid", &tmp_package);
if (track->name && track->name[0])
av_dict_set(&st->metadata, "track_name", track->name, 0);
codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &track->sequence->data_definition_ul);
- av_dict_set(&st->metadata, "data_type", av_get_media_type_string(codec_ul->id), 0);
+ av_dict_set(&st->metadata, "data_type", av_get_media_type_string((AVMediaType)codec_ul->id), 0);
return 0;
}
@@ -2583,7 +2589,7 @@ static MXFMCASubDescriptor *find_mca_link_id(MXFContext *mxf, enum MXFMetadataSe
static void parse_ffv1_sub_descriptor(MXFContext *mxf, MXFTrack *source_track, MXFDescriptor *descriptor, AVStream *st)
{
for (int i = 0; i < descriptor->sub_descriptors_count; i++) {
- MXFFFV1SubDescriptor *ffv1_sub_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], FFV1SubDescriptor);
+ MXFFFV1SubDescriptor *ffv1_sub_descriptor = mxf_resolve_strong_ref<MXFFFV1SubDescriptor>(mxf, &descriptor->sub_descriptors_refs[i]);
if (ffv1_sub_descriptor == NULL)
continue;
@@ -2607,7 +2613,7 @@ static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescript
for (int i = 0; i < descriptor->sub_descriptors_count; i++) {
char *channel_language;
- MXFMCASubDescriptor *label = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], AudioChannelLabelSubDescriptor);
+ MXFAudioChannelLabelSubDescriptor *label = mxf_resolve_strong_ref<MXFAudioChannelLabelSubDescriptor>(mxf, &descriptor->sub_descriptors_refs[i]);
if (label == NULL)
continue;
@@ -2675,7 +2681,7 @@ static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescript
*ast = service_type;
}
- ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
+ ret = av_channel_layout_retype(ch_layout, AV_CHANNEL_ORDER_UNSPEC, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
if (ret < 0)
return ret;
@@ -2684,12 +2690,12 @@ static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescript
static int mxf_parse_structural_metadata(MXFContext *mxf)
{
- MXFPackage *material_package = NULL;
+ MXFMaterialPackage *material_package = NULL;
int k, ret;
/* TODO: handle multiple material packages (OP3x) */
for (int i = 0; i < mxf->packages_count; i++) {
- material_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], MaterialPackage);
+ material_package = mxf_resolve_strong_ref<MXFMaterialPackage>(mxf, &mxf->packages_refs[i]);
if (material_package) break;
}
if (!material_package) {
@@ -2719,30 +2725,28 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
AVTimecode tc;
int flags;
- if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) {
+ if (!(material_track = mxf_resolve_strong_ref<MXFTrack>(mxf, &material_package->tracks_refs[i]))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n");
continue;
}
- if ((component = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, TimecodeComponent))) {
- mxf_tc = (MXFTimecodeComponent*)component;
+ if ((mxf_tc = mxf_resolve_strong_ref<MXFTimecodeComponent>(mxf, &material_track->sequence_ref))) {
flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf->fc) == 0) {
mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
}
}
- if (!(material_track->sequence = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, Sequence))) {
+ if (!(material_track->sequence = mxf_resolve_strong_ref<MXFSequence>(mxf, &material_track->sequence_ref))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track sequence strong ref\n");
continue;
}
for (int j = 0; j < material_track->sequence->structural_components_count; j++) {
- component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], TimecodeComponent);
- if (!component)
+ mxf_tc = mxf_resolve_strong_ref<MXFTimecodeComponent>(mxf, &material_track->sequence->structural_components_refs[j]);
+ if (!mxf_tc)
continue;
- mxf_tc = (MXFTimecodeComponent*)component;
flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf->fc) == 0) {
mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
@@ -2766,7 +2770,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
continue;
}
for (k = 0; k < source_package->tracks_count; k++) {
- if (!(temp_track = mxf_resolve_strong_ref(mxf, &source_package->tracks_refs[k], Track))) {
+ if (!(temp_track = mxf_resolve_strong_ref<MXFTrack>(mxf, &source_package->tracks_refs[k]))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
ret = AVERROR_INVALIDDATA;
goto fail_and_free;
@@ -2784,7 +2788,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
for (k = 0; k < mxf->essence_container_data_count; k++) {
MXFEssenceContainerData *essence_data;
- if (!(essence_data = mxf_resolve_strong_ref(mxf, &mxf->essence_container_data_refs[k], EssenceContainerData))) {
+ if (!(essence_data = mxf_resolve_strong_ref<MXFEssenceContainerData>(mxf, &mxf->essence_container_data_refs[k]))) {
av_log(mxf->fc, AV_LOG_TRACE, "could not resolve essence container data strong ref\n");
continue;
}
@@ -2804,7 +2808,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
continue;
}
- if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref, Sequence))) {
+ if (!(source_track->sequence = mxf_resolve_strong_ref<MXFSequence>(mxf, &source_track->sequence_ref))) {
av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n");
ret = AVERROR_INVALIDDATA;
goto fail_and_free;
@@ -2856,7 +2860,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul);
codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul);
- st->codecpar->codec_type = codec_ul->id;
+ st->codecpar->codec_type = (AVMediaType)codec_ul->id;
if (!descriptor) {
av_log(mxf->fc, AV_LOG_INFO, "source track %d: stream %d, no descriptor found\n", source_track->track_id, st->index);
@@ -2909,7 +2913,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
source_track->intra_only = mxf_is_intra_only(descriptor);
container_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul);
if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
- st->codecpar->codec_id = container_ul->id;
+ st->codecpar->codec_id = (AVCodecID)container_ul->id;
st->codecpar->width = descriptor->width;
st->codecpar->height = descriptor->height; /* Field height, not frame height */
switch (descriptor->frame_layout) {
@@ -3034,9 +3038,9 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
if (descriptor->aspect_ratio.num && descriptor->aspect_ratio.den)
sti->display_aspect_ratio = descriptor->aspect_ratio;
st->codecpar->color_range = mxf_get_color_range(mxf, descriptor);
- st->codecpar->color_primaries = mxf_get_codec_ul(ff_mxf_color_primaries_uls, &descriptor->color_primaries_ul)->id;
- st->codecpar->color_trc = mxf_get_codec_ul(ff_mxf_color_trc_uls, &descriptor->color_trc_ul)->id;
- st->codecpar->color_space = mxf_get_codec_ul(ff_mxf_color_space_uls, &descriptor->color_space_ul)->id;
+ st->codecpar->color_primaries = (AVColorPrimaries)mxf_get_codec_ul(ff_mxf_color_primaries_uls, &descriptor->color_primaries_ul)->id;
+ st->codecpar->color_trc = (AVColorTransferCharacteristic)mxf_get_codec_ul(ff_mxf_color_trc_uls, &descriptor->color_trc_ul)->id;
+ st->codecpar->color_space = (AVColorSpace)mxf_get_codec_ul(ff_mxf_color_space_uls, &descriptor->color_space_ul)->id;
if (descriptor->mastering) {
if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
@@ -3109,7 +3113,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
enum AVMediaType type;
container_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul);
if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
- st->codecpar->codec_id = container_ul->id;
+ st->codecpar->codec_id = (AVCodecID)container_ul->id;
type = avcodec_get_type(st->codecpar->codec_id);
if (type == AVMEDIA_TYPE_SUBTITLE)
st->codecpar->codec_type = type;
@@ -3142,10 +3146,10 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
}
for (int i = 0; i < mxf->fc->nb_streams; i++) {
- MXFTrack *track1 = mxf->fc->streams[i]->priv_data;
+ MXFTrack *track1 = (MXFTrack*)mxf->fc->streams[i]->priv_data;
if (track1 && track1->body_sid) {
for (int j = i + 1; j < mxf->fc->nb_streams; j++) {
- MXFTrack *track2 = mxf->fc->streams[j]->priv_data;
+ MXFTrack *track2 = (MXFTrack*)mxf->fc->streams[j]->priv_data;
if (track2 && track1->body_sid == track2->body_sid && track1->wrapping != track2->wrapping) {
if (track1->wrapping == UnknownWrapped)
track1->wrapping = track2->wrapping;
@@ -3219,7 +3223,7 @@ static int64_t mxf_timestamp_to_int64(uint64_t timestamp)
static int mxf_read_identification_metadata(void *arg, AVIOContext *pb, int tag, int size, UID _uid, int64_t klv_offset)
{
- MXFContext *mxf = arg;
+ MXFContext *mxf = (MXFContext*)arg;
AVFormatContext *s = mxf->fc;
int ret;
UID uid = { 0 };
@@ -3263,7 +3267,7 @@ static int mxf_read_identification_metadata(void *arg, AVIOContext *pb, int tag,
static int mxf_read_preface_metadata(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
{
- MXFContext *mxf = arg;
+ MXFContext *mxf = (MXFContext*)arg;
AVFormatContext *s = mxf->fc;
int ret;
char *str = NULL;
@@ -3343,7 +3347,7 @@ static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadF
void *ctx;
if (ctx_size) {
- meta = av_mallocz(ctx_size);
+ meta = (MXFMetadataSet*)av_mallocz(ctx_size);
if (!meta)
return AVERROR(ENOMEM);
ctx = meta;
@@ -3498,7 +3502,7 @@ static int mxf_seek_to_previous_partition(MXFContext *mxf)
return AVERROR_INVALIDDATA;
}
- if ((ret = mxf_parse_klv(mxf, klv, mxf_read_partition_pack, 0, 0)) < 0)
+ if ((ret = mxf_parse_klv(mxf, klv, mxf_read_partition_pack, 0, Partition)) < 0)
return ret;
return 1;
@@ -3559,7 +3563,7 @@ static int mxf_parse_handle_partition_or_eof(MXFContext *mxf)
static MXFWrappingScheme mxf_get_wrapping_by_body_sid(AVFormatContext *s, int body_sid)
{
for (int i = 0; i < s->nb_streams; i++) {
- MXFTrack *track = s->streams[i]->priv_data;
+ MXFTrack *track = (MXFTrack*)s->streams[i]->priv_data;
if (track && track->body_sid == body_sid && track->wrapping != UnknownWrapped)
return track->wrapping;
}
@@ -3571,7 +3575,7 @@ static MXFWrappingScheme mxf_get_wrapping_by_body_sid(AVFormatContext *s, int bo
*/
static void mxf_compute_essence_containers(AVFormatContext *s)
{
- MXFContext *mxf = s->priv_data;
+ MXFContext *mxf = (MXFContext*)s->priv_data;
int x;
for (x = 0; x < mxf->partitions_count; x++) {
@@ -3624,7 +3628,7 @@ static MXFIndexTable *mxf_find_index_table(MXFContext *mxf, int index_sid)
*/
static void mxf_compute_edit_units_per_packet(MXFContext *mxf, AVStream *st)
{
- MXFTrack *track = st->priv_data;
+ MXFTrack *track = (MXFTrack*)st->priv_data;
MXFIndexTable *t;
if (!track)
@@ -3655,7 +3659,7 @@ static void mxf_compute_edit_units_per_packet(MXFContext *mxf, AVStream *st)
*/
static int mxf_handle_missing_index_segment(MXFContext *mxf, AVStream *st)
{
- MXFTrack *track = st->priv_data;
+ MXFTrack *track = (MXFTrack*)st->priv_data;
MXFIndexTableSegment *segment = NULL;
MXFPartition *p = NULL;
int essence_partition_count = 0;
@@ -3699,7 +3703,7 @@ static int mxf_handle_missing_index_segment(MXFContext *mxf, AVStream *st)
av_log(mxf->fc, AV_LOG_WARNING, "guessing index for stream %d using edit unit byte count %d\n", st->index, edit_unit_byte_count);
- if (!(segment = av_mallocz(sizeof(*segment))))
+ if (!(segment = (MXFIndexTableSegment*)av_mallocz(sizeof(*segment))))
return AVERROR(ENOMEM);
if ((ret = mxf_add_metadata_set(mxf, (MXFMetadataSet**)&segment, IndexTableSegment)))
@@ -3722,7 +3726,7 @@ static int mxf_handle_missing_index_segment(MXFContext *mxf, AVStream *st)
static void mxf_read_random_index_pack(AVFormatContext *s)
{
- MXFContext *mxf = s->priv_data;
+ MXFContext *mxf = (MXFContext*)s->priv_data;
uint32_t length;
int64_t file_size, max_rip_length, min_rip_length;
KLVPacket klv;
@@ -3774,9 +3778,9 @@ end:
avio_seek(s->pb, mxf->run_in, SEEK_SET);
}
-static int mxf_read_header(AVFormatContext *s)
+int mxf_read_header(AVFormatContext *s)
{
- MXFContext *mxf = s->priv_data;
+ MXFContext *mxf = (MXFContext*)s->priv_data;
KLVPacket klv;
int64_t essence_offset = 0;
int ret;
@@ -3926,7 +3930,7 @@ static int mxf_get_next_track_edit_unit(MXFContext *mxf, MXFTrack *track, int64_
static int64_t mxf_compute_sample_count(MXFContext *mxf, AVStream *st,
int64_t edit_unit)
{
- MXFTrack *track = st->priv_data;
+ MXFTrack *track = (MXFTrack*)st->priv_data;
AVRational time_base = av_inv_q(track->edit_rate);
AVRational sample_rate = av_inv_q(st->time_base);
@@ -3957,7 +3961,7 @@ static int64_t mxf_compute_sample_count(MXFContext *mxf, AVStream *st,
static int64_t mxf_set_current_edit_unit(MXFContext *mxf, AVStream *st, int64_t current_offset, int resync)
{
int64_t next_ofs = -1;
- MXFTrack *track = st->priv_data;
+ MXFTrack *track = (MXFTrack*)st->priv_data;
int64_t edit_unit = av_rescale_q(track->sample_count, st->time_base, av_inv_q(track->edit_rate));
int64_t new_edit_unit;
MXFIndexTable *t = mxf_find_index_table(mxf, track->index_sid);
@@ -3996,7 +4000,7 @@ static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par,
AVPacket *pkt)
{
AVStream *st = mxf->fc->streams[pkt->stream_index];
- MXFTrack *track = st->priv_data;
+ MXFTrack *track = (MXFTrack*)st->priv_data;
int64_t bits_per_sample = par->bits_per_coded_sample;
if (!bits_per_sample)
@@ -4017,7 +4021,7 @@ static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par,
static int mxf_set_pts(MXFContext *mxf, AVStream *st, AVPacket *pkt)
{
AVCodecParameters *par = st->codecpar;
- MXFTrack *track = st->priv_data;
+ MXFTrack *track = (MXFTrack*)st->priv_data;
if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
/* see if we have an index table to derive timestamps from */
@@ -4044,10 +4048,10 @@ static int mxf_set_pts(MXFContext *mxf, AVStream *st, AVPacket *pkt)
return 0;
}
-static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
+int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
KLVPacket klv;
- MXFContext *mxf = s->priv_data;
+ MXFContext *mxf = (MXFContext*)s->priv_data;
int ret;
while (1) {
@@ -4093,7 +4097,7 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
}
st = s->streams[index];
- track = st->priv_data;
+ track = (MXFTrack*)st->priv_data;
if (s->streams[index]->discard == AVDISCARD_ALL)
goto skip;
@@ -4172,9 +4176,9 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
return avio_feof(s->pb) ? AVERROR_EOF : ret;
}
-static int mxf_read_close(AVFormatContext *s)
+int mxf_read_close(AVFormatContext *s)
{
- MXFContext *mxf = s->priv_data;
+ MXFContext *mxf = (MXFContext*)s->priv_data;
av_freep(&mxf->packages_refs);
av_freep(&mxf->essence_container_data_refs);
@@ -4185,7 +4189,7 @@ static int mxf_read_close(AVFormatContext *s)
for (int type = 0; type < FF_ARRAY_ELEMS(mxf->metadata_set_groups); type++) {
MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[type];
for (int i = 0; i < mg->metadata_sets_count; i++)
- mxf_free_metadataset(mg->metadata_sets + i, type);
+ mxf_free_metadataset(mg->metadata_sets + i, (MXFMetadataSetType)type);
mg->metadata_sets_count = 0;
av_freep(&mg->metadata_sets);
}
@@ -4206,7 +4210,7 @@ static int mxf_read_close(AVFormatContext *s)
return 0;
}
-static int mxf_probe(const AVProbeData *p) {
+int mxf_probe(const AVProbeData *p) {
const uint8_t *bufp = p->buf;
const uint8_t *end = p->buf + FFMIN(p->buf_size, RUN_IN_MAX + 1 + sizeof(mxf_header_partition_pack_key));
@@ -4233,15 +4237,15 @@ static int mxf_probe(const AVProbeData *p) {
/* rudimentary byte seek */
/* XXX: use MXF Index */
-static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
+int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
{
AVStream *st = s->streams[stream_index];
int64_t seconds;
- MXFContext* mxf = s->priv_data;
+ MXFContext* mxf = (MXFContext*)s->priv_data;
int64_t seekpos;
int ret;
MXFIndexTable *t;
- MXFTrack *source_track = st->priv_data;
+ MXFTrack *source_track = (MXFTrack*)st->priv_data;
if (!source_track)
return 0;
@@ -4272,7 +4276,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
int i;
/* If the first index table does not belong to the stream, then find a stream which does belong to the index table */
for (i = 0; i < s->nb_streams; i++) {
- MXFTrack *new_source_track = s->streams[i]->priv_data;
+ MXFTrack *new_source_track = (MXFTrack*)s->streams[i]->priv_data;
if (new_source_track && new_source_track->index_sid == t->index_sid) {
sample_time = av_rescale_q(sample_time, new_source_track->edit_rate, source_track->edit_rate);
source_track = new_source_track;
@@ -4333,7 +4337,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
// Update all tracks sample count
for (int i = 0; i < s->nb_streams; i++) {
AVStream *cur_st = s->streams[i];
- MXFTrack *cur_track = cur_st->priv_data;
+ MXFTrack *cur_track = (MXFTrack*)cur_st->priv_data;
if (cur_track) {
int64_t track_edit_unit = sample_time;
if (st != cur_st)
@@ -4343,32 +4347,3 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
}
return 0;
}
-
-static const AVOption options[] = {
- { "eia608_extract", "extract eia 608 captions from s436m track",
- offsetof(MXFContext, eia608_extract), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1,
- AV_OPT_FLAG_DECODING_PARAM },
- { NULL },
-};
-
-static const AVClass demuxer_class = {
- .class_name = "mxf",
- .item_name = av_default_item_name,
- .option = options,
- .version = LIBAVUTIL_VERSION_INT,
- .category = AV_CLASS_CATEGORY_DEMUXER,
-};
-
-const FFInputFormat ff_mxf_demuxer = {
- .p.name = "mxf",
- .p.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
- .p.flags = AVFMT_SEEK_TO_PTS | AVFMT_NOGENSEARCH,
- .p.priv_class = &demuxer_class,
- .priv_data_size = sizeof(MXFContext),
- .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
- .read_probe = mxf_probe,
- .read_header = mxf_read_header,
- .read_packet = mxf_read_packet,
- .read_close = mxf_read_close,
- .read_seek = mxf_read_seek,
-};
diff --git a/libavformat/mxfdec.h b/libavformat/mxfdec.h
new file mode 100644
index 0000000000..3680e0a8ac
--- /dev/null
+++ b/libavformat/mxfdec.h
@@ -0,0 +1,82 @@
+/*
+ * C-to-C++ bridge header for MXF demuxer.
+ * Copyright (c) 2025 Tomas Härdin
+ *
+ * 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 AVFORMAT_MXFDEC_H
+#define AVFORMAT_MXFDEC_H
+
+#include "mxf.h"
+
+typedef enum {
+ OP1a = 1,
+ OP1b,
+ OP1c,
+ OP2a,
+ OP2b,
+ OP2c,
+ OP3a,
+ OP3b,
+ OP3c,
+ OPAtom,
+ OPSONYOpt, /* FATE sample, violates the spec in places */
+} MXFOP;
+
+struct MXFIndexTable;
+struct MXFMetadataSet;
+struct MXFPartition;
+
+typedef struct MXFMetadataSetGroup {
+ struct MXFMetadataSet **metadata_sets;
+ int metadata_sets_count;
+} MXFMetadataSetGroup;
+
+typedef struct MXFContext {
+ const AVClass *_class; /**< Class for private options. */
+ struct MXFPartition *partitions;
+ unsigned partitions_count;
+ MXFOP op;
+ UID *packages_refs;
+ int packages_count;
+ UID *essence_container_data_refs;
+ int essence_container_data_count;
+ MXFMetadataSetGroup metadata_set_groups[MetadataSetTypeNB];
+ AVFormatContext *fc;
+ struct AVAES *aesc;
+ uint8_t *local_tags;
+ int local_tags_count;
+ uint64_t footer_partition;
+ KLVPacket current_klv_data;
+ int run_in;
+ struct MXFPartition *current_partition;
+ int parsing_backward;
+ int64_t last_forward_tell;
+ int last_forward_partition;
+ int nb_index_tables;
+ struct MXFIndexTable *index_tables;
+ int eia608_extract;
+} MXFContext;
+
+int mxf_probe(const AVProbeData *p);
+int mxf_read_header(AVFormatContext *s);
+int mxf_read_packet(AVFormatContext *s, AVPacket *pkt);
+int mxf_read_close(AVFormatContext *s);
+int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags);
+
+#endif /* AVFORMAT_MXFDEC_H */
diff --git a/libavformat/mxfdec_c.c b/libavformat/mxfdec_c.c
new file mode 100644
index 0000000000..4465b76e58
--- /dev/null
+++ b/libavformat/mxfdec_c.c
@@ -0,0 +1,53 @@
+/*
+ * C binding for MXF demuxer.
+ * Copyright (c) 2025 Tomas Härdin
+ *
+ * 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/opt.h"
+#include "demux.h"
+#include "mxfdec.h"
+
+static const AVOption options[] = {
+ { "eia608_extract", "extract eia 608 captions from s436m track",
+ offsetof(MXFContext, eia608_extract), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1,
+ AV_OPT_FLAG_DECODING_PARAM },
+ { NULL },
+};
+
+static const AVClass demuxer_class = {
+ .class_name = "mxf",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .category = AV_CLASS_CATEGORY_DEMUXER,
+};
+
+const FFInputFormat ff_mxf_demuxer = {
+ .p.name = "mxf",
+ .p.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
+ .p.flags = AVFMT_SEEK_TO_PTS | AVFMT_NOGENSEARCH,
+ .p.priv_class = &demuxer_class,
+ .priv_data_size = sizeof(MXFContext),
+ .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
+ .read_probe = mxf_probe,
+ .read_header = mxf_read_header,
+ .read_packet = mxf_read_packet,
+ .read_close = mxf_read_close,
+ .read_seek = mxf_read_seek,
+};
--
2.47.2
[-- Attachment #3: Type: text/plain, Size: 163 bytes --]
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
@ 2025-10-20 21:34 ` Neal Gompa via ffmpeg-devel
2025-10-21 2:24 ` Lynne via ffmpeg-devel
` (5 subsequent siblings)
6 siblings, 0 replies; 22+ messages in thread
From: Neal Gompa via ffmpeg-devel @ 2025-10-20 21:34 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Tomas Härdin, Neal Gompa
On Mon, Oct 20, 2025 at 1:51 PM Tomas Härdin via ffmpeg-devel
<ffmpeg-devel@ffmpeg.org> wrote:
>
> Hi
>
> I'm writing this email to get a feel for how everyone feels about
> making more use of C++ in the codebase. I am only proposing using C++
> *internally*, and only where it makes sense. I am not suggesting a
> "move" to C++, merely using features already present in the compilers
> we target: gcc, clang and cl. The impedance mismatch should therefore
> be small, and any missing compiler features should be caught by FATE.
>
> Currently C++ use is quite limited in this project, but I see no reason
> why this should be the case. doc/faq.texi makes mention of Linux'
> reasons for avoiding C++, but FFmpeg is not Linux. For us ABI stability
> and performance are the biggest issues. Stability can be ensured by
> sticking with C for the API and disabling exceptions (or marking
> relevant functions as noexcept). Performance may benefit in some cases.
> This would have to be tested. Again, the most performance critical
> parts can be kept as C (and asm).
>
> My main motivation is to be able to use STL, which would simplify
> string handling and memory management, and give us access to its data
> structures. Manual memory management has its place, especially in lavc.
> In lavf less so. RAII would do wonders in de-gotofying error handling.
> Features like std::filesystem, std::chrono, std::thread etc abstract
> away many OS particularities. Thorough STL-ification would render parts
> of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
> would have security benefits. Another reason is stronger typing, which
> tends to reveal bugs.
>
> I've targeted mxfdec.c as a proof-of-concept. See attached patch, which
> compiles and passes fate-mxf. It is partly inspired by our decklink
> binding. Particularly notable is the ability to resolve MXF structs
> into MXFMetadataSetType at compile time, as well as resolving strong
> references in a more type safe manner. This revealed an issue in
> mxf_parse_structural_metadata() where MXFStructuralComponent* was
> blindly cast to MXFTimecodeComponent*, which could cause code further
> down to interpret the latter as the former, which is a not so obvious
> bug that wouldn't be caught without this stronger typing.
>
> I've not made use of STL in the attached patch because that requires
> linking with libstdc++, which I couldn't be arsed to do. One practical
> example where STL would come in handy is for my work on segmented
> indexes. Specifically std::map and std::lower_bound. Various tables in
> mxfdec.c could also be targets for turning into std::map or even
> std::unordered_map. A quick experiment with callgrind suggests
> mxf_read_header() might be speed up slightly with such a change.
>
> Details like which version of C++ to use could be agreed on later if
> people feel this is a good idea. Personally I favor using the most
> recent version that our compiler suite supports. Lately I've been using
> C++20 with icx (Intel's compiler) which has been quite pleasant.
>
I think it'd be great if this was done. Actually, RPM made a similar
move for RPM 6.0[1] for precisely the same reason.
From my point of view, it would make it easier for me to understand
the code as I'm more of a C++ guy than a C guy. And I feel like
there's a longer-term benefit to simplify code by not needing to
recreate data structures that are perfectly usable from the STL.
That said, from a C++ standard perspective, C++20 is a great place to
start from. RPM, KDE, and other major Free Software projects using C++
have moved to it and liked the improvements to C/C++ it offers.
[1]: https://rpm.org/releases/6.0.0
--
真実はいつも一つ!/ Always, there's only one truth!
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
2025-10-20 21:34 ` [FFmpeg-devel] " Neal Gompa via ffmpeg-devel
@ 2025-10-21 2:24 ` Lynne via ffmpeg-devel
2025-10-22 8:57 ` Tomas Härdin via ffmpeg-devel
2025-10-22 10:46 ` Tomas Härdin via ffmpeg-devel
2025-10-21 18:41 ` Niklas Haas via ffmpeg-devel
` (4 subsequent siblings)
6 siblings, 2 replies; 22+ messages in thread
From: Lynne via ffmpeg-devel @ 2025-10-21 2:24 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Lynne
On 20/10/2025 19:50, Tomas Härdin via ffmpeg-devel wrote:
> Hi
>
> I'm writing this email to get a feel for how everyone feels about
> making more use of C++ in the codebase. I am only proposing using C++
> *internally*, and only where it makes sense. I am not suggesting a
> "move" to C++, merely using features already present in the compilers
> we target: gcc, clang and cl. The impedance mismatch should therefore
> be small, and any missing compiler features should be caught by FATE.
Definitely not.
The patch you posted hardly changes anything.
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
2025-10-20 21:34 ` [FFmpeg-devel] " Neal Gompa via ffmpeg-devel
2025-10-21 2:24 ` Lynne via ffmpeg-devel
@ 2025-10-21 18:41 ` Niklas Haas via ffmpeg-devel
2025-10-22 3:15 ` Romain Beauxis via ffmpeg-devel
` (3 subsequent siblings)
6 siblings, 0 replies; 22+ messages in thread
From: Niklas Haas via ffmpeg-devel @ 2025-10-21 18:41 UTC (permalink / raw)
To: Tomas Härdin via ffmpeg-devel,
FFmpeg development discussions and patches
Cc: Tomas Härdin, Niklas Haas
On Mon, 20 Oct 2025 19:50:33 +0200 Tomas Härdin via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> wrote:
> Hi
>
> I'm writing this email to get a feel for how everyone feels about
> making more use of C++ in the codebase. I am only proposing using C++
> *internally*, and only where it makes sense. I am not suggesting a
> "move" to C++, merely using features already present in the compilers
> we target: gcc, clang and cl. The impedance mismatch should therefore
> be small, and any missing compiler features should be caught by FATE.
>
> Currently C++ use is quite limited in this project, but I see no reason
> why this should be the case. doc/faq.texi makes mention of Linux'
> reasons for avoiding C++, but FFmpeg is not Linux. For us ABI stability
> and performance are the biggest issues. Stability can be ensured by
> sticking with C for the API and disabling exceptions (or marking
> relevant functions as noexcept). Performance may benefit in some cases.
> This would have to be tested. Again, the most performance critical
> parts can be kept as C (and asm).
I personally have always felt like debugging C++ in gdb is a bit of a
sub-par experience compared to C; but maybe things have gotten better
these days?
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
` (2 preceding siblings ...)
2025-10-21 18:41 ` Niklas Haas via ffmpeg-devel
@ 2025-10-22 3:15 ` Romain Beauxis via ffmpeg-devel
2025-10-22 4:19 ` InnocentZero via ffmpeg-devel
` (2 more replies)
2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
` (2 subsequent siblings)
6 siblings, 3 replies; 22+ messages in thread
From: Romain Beauxis via ffmpeg-devel @ 2025-10-22 3:15 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Romain Beauxis
On Mon, Oct 20, 2025, 12:51 Tomas Härdin via ffmpeg-devel <
ffmpeg-devel@ffmpeg.org> wrote:
> Hi
>
> I'm writing this email to get a feel for how everyone feels about
> making more use of C++ in the codebase. I am only proposing using C++
> *internally*, and only where it makes sense. I am not suggesting a
> "move" to C++, merely using features already present in the compilers
> we target: gcc, clang and cl. The impedance mismatch should therefore
> be small, and any missing compiler features should be caught by FATE.
>
> Currently C++ use is quite limited in this project, but I see no reason
> why this should be the case. doc/faq.texi makes mention of Linux'
> reasons for avoiding C++, but FFmpeg is not Linux. For us ABI stability
> and performance are the biggest issues. Stability can be ensured by
> sticking with C for the API and disabling exceptions (or marking
> relevant functions as noexcept). Performance may benefit in some cases.
> This would have to be tested. Again, the most performance critical
> parts can be kept as C (and asm).
>
> My main motivation is to be able to use STL, which would simplify
> string handling and memory management, and give us access to its data
> structures. Manual memory management has its place, especially in lavc.
> In lavf less so. RAII would do wonders in de-gotofying error handling.
> Features like std::filesystem, std::chrono, std::thread etc abstract
> away many OS particularities. Thorough STL-ification would render parts
> of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
> would have security benefits. Another reason is stronger typing, which
> tends to reveal bugs.
>
> I've targeted mxfdec.c as a proof-of-concept. See attached patch, which
> compiles and passes fate-mxf. It is partly inspired by our decklink
> binding. Particularly notable is the ability to resolve MXF structs
> into MXFMetadataSetType at compile time, as well as resolving strong
> references in a more type safe manner. This revealed an issue in
> mxf_parse_structural_metadata() where MXFStructuralComponent* was
> blindly cast to MXFTimecodeComponent*, which could cause code further
> down to interpret the latter as the former, which is a not so obvious
> bug that wouldn't be caught without this stronger typing.
>
> I've not made use of STL in the attached patch because that requires
> linking with libstdc++, which I couldn't be arsed to do.
I understand the benefit of using higher order APIs borrowed from C++ but,
to fully make your case I think it'd be important to know: is it possible
to use STL and avoid linking with libstc++?
One practical
> example where STL would come in handy is for my work on segmented
> indexes. Specifically std::map and std::lower_bound. Various tables in
> mxfdec.c could also be targets for turning into std::map or even
> std::unordered_map. A quick experiment with callgrind suggests
> mxf_read_header() might be speed up slightly with such a change.
>
> Details like which version of C++ to use could be agreed on later if
> people feel this is a good idea. Personally I favor using the most
> recent version that our compiler suite supports. Lately I've been using
> C++20 with icx (Intel's compiler) which has been quite pleasant.
>
> /Tomas
> _______________________________________________
> ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
> To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
>
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 3:15 ` Romain Beauxis via ffmpeg-devel
@ 2025-10-22 4:19 ` InnocentZero via ffmpeg-devel
2025-10-22 8:24 ` Nicolas George via ffmpeg-devel
2025-10-22 10:53 ` Tomas Härdin via ffmpeg-devel
2 siblings, 0 replies; 22+ messages in thread
From: InnocentZero via ffmpeg-devel @ 2025-10-22 4:19 UTC (permalink / raw)
To: Romain Beauxis via ffmpeg-devel; +Cc: InnocentZero
Romain Beauxis via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> writes:
> I understand the benefit of using higher order APIs borrowed from C++ but,
> to fully make your case I think it'd be important to know: is it possible
> to use STL and avoid linking with libstc++?
I'm new to the list, so forgive me for asking if it's a mundane
question, but what exactly is the reason for avoiding linking with
libstc++?
Is it solely to avoid having a dependency on a library? Or some other
specific reason?
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 3:15 ` Romain Beauxis via ffmpeg-devel
2025-10-22 4:19 ` InnocentZero via ffmpeg-devel
@ 2025-10-22 8:24 ` Nicolas George via ffmpeg-devel
2025-10-22 10:53 ` Tomas Härdin via ffmpeg-devel
2 siblings, 0 replies; 22+ messages in thread
From: Nicolas George via ffmpeg-devel @ 2025-10-22 8:24 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Nicolas George
Romain Beauxis via ffmpeg-devel (HE12025-10-21):
> is it possible
> to use STL and avoid linking with libstc++?
It is possible to use the data structures and algorithms of the STL,
which are the key to the performance gains, by implementing them in
libavutil. We can even gain a little more performance by making them
more specifically suited to our needs and style.
Regards,
--
Nicolas George
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-21 2:24 ` Lynne via ffmpeg-devel
@ 2025-10-22 8:57 ` Tomas Härdin via ffmpeg-devel
2025-10-22 10:46 ` Tomas Härdin via ffmpeg-devel
1 sibling, 0 replies; 22+ messages in thread
From: Tomas Härdin via ffmpeg-devel @ 2025-10-22 8:57 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Lynne, Tomas Härdin
tis 2025-10-21 klockan 04:24 +0200 skrev Lynne via ffmpeg-devel:
> On 20/10/2025 19:50, Tomas Härdin via ffmpeg-devel wrote:
> > Hi
> >
> > I'm writing this email to get a feel for how everyone feels about
> > making more use of C++ in the codebase. I am only proposing using
> > C++
> > *internally*, and only where it makes sense. I am not suggesting a
> > "move" to C++, merely using features already present in the
> > compilers
> > we target: gcc, clang and cl. The impedance mismatch should
> > therefore
> > be small, and any missing compiler features should be caught by
> > FATE.
>
> Definitely not.
> The patch you posted hardly changes anything.
That's on purpose. If you want I can make more thoroughgoing changes
like turning all tables into std::map, lambdafying things etc etc. For
example parts of mxf_read_packet() could be turned into map<UID,λ>. The
IndexTableSegment stuff also comes to mind
/Tomas
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-21 2:24 ` Lynne via ffmpeg-devel
2025-10-22 8:57 ` Tomas Härdin via ffmpeg-devel
@ 2025-10-22 10:46 ` Tomas Härdin via ffmpeg-devel
1 sibling, 0 replies; 22+ messages in thread
From: Tomas Härdin via ffmpeg-devel @ 2025-10-22 10:46 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Tomas Härdin
[-- Attachment #1: Type: text/plain, Size: 1629 bytes --]
tis 2025-10-21 klockan 04:24 +0200 skrev Lynne via ffmpeg-devel:
> On 20/10/2025 19:50, Tomas Härdin via ffmpeg-devel wrote:
> > Hi
> >
> > I'm writing this email to get a feel for how everyone feels about
> > making more use of C++ in the codebase. I am only proposing using
> > C++
> > *internally*, and only where it makes sense. I am not suggesting a
> > "move" to C++, merely using features already present in the
> > compilers
> > we target: gcc, clang and cl. The impedance mismatch should
> > therefore
> > be small, and any missing compiler features should be caught by
> > FATE.
>
> Definitely not.
> The patch you posted hardly changes anything.
Here's a more illustrative example. What it means for a given offset to
be contained "within" a partition is made explicit. This also allows us
to reject files where partitions are overlapping, which wasn't obvious
with the previous code
The codebase is actually littered with binary searches like the one the
attached patchset removes. That's a major code stink imo
KLV keys could be given a similar treatment. Most importantly, the
entire index code could be made far more readable and robust. That's a
rather large task however, which I'm not going to undertake unless I
know I won't face major opposition
A continuation of the partition stuff attached is to remove
MXFContext::partitions and instead use an std::map in MXFCppContext for
the partitions themselves, not just their offsets. This would address
some performance issues with the present code for files with a large
number of partitions, such as mxfenc.c
/Tomas
[-- Attachment #2: 0001-lavf-mxfdec-Add-C-context.patch --]
[-- Type: text/x-patch, Size: 1880 bytes --]
From bda56e7d1259047e65c02cc40ab53728eedbfc6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= <git@haerdin.se>
Date: Wed, 22 Oct 2025 11:01:21 +0200
Subject: [PATCH 1/2] lavf/mxfdec: Add C++ context
---
libavformat/mxfdec.cpp | 5 +++++
libavformat/mxfdec.h | 2 ++
2 files changed, 7 insertions(+)
diff --git a/libavformat/mxfdec.cpp b/libavformat/mxfdec.cpp
index 1b3c00c07c..522d870981 100644
--- a/libavformat/mxfdec.cpp
+++ b/libavformat/mxfdec.cpp
@@ -333,6 +333,9 @@ typedef struct MXFIndexTable {
int8_t *offsets; /* temporal offsets for display order to stored order conversion */
} MXFIndexTable;
+struct MXFCppContext {
+};
+
/* NOTE: klv_offset is not set (-1) for local keys */
typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset);
@@ -3786,6 +3789,7 @@ int mxf_read_header(AVFormatContext *s)
int ret;
int64_t run_in;
+ mxf->cpp_context = new MXFCppContext();
mxf->last_forward_tell = INT64_MAX;
if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) {
@@ -4206,6 +4210,7 @@ int mxf_read_close(AVFormatContext *s)
}
}
av_freep(&mxf->index_tables);
+ delete mxf->cpp_context;
return 0;
}
diff --git a/libavformat/mxfdec.h b/libavformat/mxfdec.h
index 3680e0a8ac..f4ad85fb46 100644
--- a/libavformat/mxfdec.h
+++ b/libavformat/mxfdec.h
@@ -41,6 +41,7 @@ typedef enum {
struct MXFIndexTable;
struct MXFMetadataSet;
struct MXFPartition;
+struct MXFCppContext;
typedef struct MXFMetadataSetGroup {
struct MXFMetadataSet **metadata_sets;
@@ -71,6 +72,7 @@ typedef struct MXFContext {
int nb_index_tables;
struct MXFIndexTable *index_tables;
int eia608_extract;
+ struct MXFCppContext *cpp_context; //< C++ context
} MXFContext;
int mxf_probe(const AVProbeData *p);
--
2.47.2
[-- Attachment #3: 0002-lavf-mxfdec-Switch-mxf_absolute_bodysid_offset-to-st.patch --]
[-- Type: text/x-patch, Size: 5104 bytes --]
From 682a647df0af169a673175eab13f99c7b58fffbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomas=20H=C3=A4rdin?= <git@haerdin.se>
Date: Wed, 22 Oct 2025 12:28:32 +0200
Subject: [PATCH 2/2] lavf/mxfdec: Switch mxf_absolute_bodysid_offset() to
std::map
This allows us to detect and reject evil files which have been constructed to have overlapping partitions
---
libavformat/mxfdec.cpp | 90 +++++++++++++++++++++++++++++-------------
1 file changed, 62 insertions(+), 28 deletions(-)
diff --git a/libavformat/mxfdec.cpp b/libavformat/mxfdec.cpp
index 522d870981..7a7b824e26 100644
--- a/libavformat/mxfdec.cpp
+++ b/libavformat/mxfdec.cpp
@@ -47,6 +47,9 @@
#include <inttypes.h>
#include <time.h>
+#include <algorithm>
+#include <map>
+
extern "C" {
#include "libavutil/aes.h"
#include "libavutil/avstring.h"
@@ -334,6 +337,26 @@ typedef struct MXFIndexTable {
} MXFIndexTable;
struct MXFCppContext {
+ typedef std::map<int64_t, MXFPartition*> OffsetMap; //< maps BodyOffset -> MXFPartition*
+ std::map<int, OffsetMap> bodysid_offset_partition_map; //< maps (BodySID, BodyOffset) -> MXFPartition*
+
+ // comparator for whether a given offset is contained within [body_offset, body_offset + essence_length)
+ struct OffsetInPartitionComp {
+ bool operator() (const std::pair<int64_t, MXFPartition*> &a, int64_t b) const {
+ if (a.second->essence_length) {
+ // <= because the end of the range is exclusive
+ return a.second->body_offset + a.second->essence_length <= b;
+ } else {
+ // if essence_length == 0 then this partition spans the rest of the file
+ // this should only happen for the last partition
+ return false; // we can never be "less than" any given offset
+ }
+ }
+
+ bool operator() (int64_t a, const std::pair<int64_t, MXFPartition*> &b) const {
+ return a < b.second->body_offset;
+ }
+ };
};
/* NOTE: klv_offset is not set (-1) for local keys */
@@ -1880,35 +1903,40 @@ static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segment
*/
static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t offset, int64_t *offset_out, MXFPartition **partition_out)
{
- MXFPartition *last_p = NULL;
- int a, b, m, m0;
-
- if (offset < 0)
- return AVERROR(EINVAL);
-
- a = -1;
- b = mxf->partitions_count;
-
- while (b - a > 1) {
- m0 = m = (a + b) >> 1;
-
- while (m < b && mxf->partitions[m].body_sid != body_sid)
- m++;
-
- if (m < b && mxf->partitions[m].body_offset <= offset)
- a = m;
- else
- b = m0;
- }
-
- if (a >= 0)
- last_p = &mxf->partitions[a];
+ auto &partition_map = mxf->cpp_context->bodysid_offset_partition_map;
+ auto it = partition_map.find(body_sid);
+
+ if (it != partition_map.end()) {
+ // find range of partitions within which offset is contained
+ // there should be exactly one
+ auto [start, end] = std::equal_range(
+ it->second.begin(),
+ it->second.end(),
+ offset,
+ MXFCppContext::OffsetInPartitionComp()
+ );
+ auto d = std::distance(start, end);
+
+ if (d > 1) {
+ // this could happen for evil files - reject them
+ av_log(mxf->fc, AV_LOG_ERROR, "absolute offset %" PRIX64 " contained in more than one partition\n", offset);
+
+ // log offending partitions
+ for (; start != end; start++) {
+ MXFPartition *p = start->second;
+ av_log(mxf->fc, AV_LOG_ERROR, "BodyOffset %" PRIX64 " BodyOffset+essence_length %" PRIX64 "\n", p->body_offset, p->body_offset + p->essence_length);
+ }
- if (last_p && (!last_p->essence_length || last_p->essence_length > (offset - last_p->body_offset))) {
- *offset_out = last_p->essence_offset + (offset - last_p->body_offset);
- if (partition_out)
- *partition_out = last_p;
- return 0;
+ return AVERROR_INVALIDDATA;
+ } else if (d == 1) {
+ MXFPartition *last_p = start->second;
+ if ((!last_p->essence_length || last_p->essence_length > (offset - last_p->body_offset))) {
+ *offset_out = last_p->essence_offset + (offset - last_p->body_offset);
+ if (partition_out)
+ *partition_out = last_p;
+ return 0;
+ }
+ }
}
av_log(mxf->fc, AV_LOG_ERROR,
@@ -3899,6 +3927,12 @@ int mxf_read_header(AVFormatContext *s)
mxf_compute_essence_containers(s);
+ // set up bodysid_offset_partition_map
+ for (int x = 0; x < mxf->partitions_count; x++) {
+ MXFPartition *partition = &mxf->partitions[x];
+ mxf->cpp_context->bodysid_offset_partition_map[partition->body_sid][partition->body_offset] = partition;
+ }
+
for (int i = 0; i < s->nb_streams; i++)
mxf_compute_edit_units_per_packet(mxf, s->streams[i]);
--
2.47.2
[-- Attachment #4: Type: text/plain, Size: 163 bytes --]
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 3:15 ` Romain Beauxis via ffmpeg-devel
2025-10-22 4:19 ` InnocentZero via ffmpeg-devel
2025-10-22 8:24 ` Nicolas George via ffmpeg-devel
@ 2025-10-22 10:53 ` Tomas Härdin via ffmpeg-devel
2 siblings, 0 replies; 22+ messages in thread
From: Tomas Härdin via ffmpeg-devel @ 2025-10-22 10:53 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Cc: Romain Beauxis, Tomas Härdin
tis 2025-10-21 klockan 22:15 -0500 skrev Romain Beauxis via ffmpeg-
devel:
> I understand the benefit of using higher order APIs borrowed from C++
> but,
> to fully make your case I think it'd be important to know: is it
> possible
> to use STL and avoid linking with libstc++?
It's technically possible, but I don't see why you'd want to. It'd be
like us writing our own libc. It's already required for decklink.
/Tomas
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
` (3 preceding siblings ...)
2025-10-22 3:15 ` Romain Beauxis via ffmpeg-devel
@ 2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
2025-10-22 12:42 ` Michael Niedermayer via ffmpeg-devel
` (3 more replies)
2025-10-22 13:05 ` Michael Niedermayer via ffmpeg-devel
2025-10-22 14:03 ` Leo Izen via ffmpeg-devel
6 siblings, 4 replies; 22+ messages in thread
From: Gregor Riepl via ffmpeg-devel @ 2025-10-22 12:09 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Gregor Riepl
> My main motivation is to be able to use STL, which would simplify
> string handling and memory management, and give us access to its data
> structures. Manual memory management has its place, especially in lavc.
> In lavf less so. RAII would do wonders in de-gotofying error handling.
> Features like std::filesystem, std::chrono, std::thread etc abstract
> away many OS particularities. Thorough STL-ification would render parts
> of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
> would have security benefits. Another reason is stronger typing, which
> tends to reveal bugs.
Just for the sake of the argument: Wouldn't it be better to opt for an even safer language than C++, like Rust?
C++ has received a lot of criticism in being just as memory unsafe as C, and I personally think that it adds an epic amount of complexity to writing correct code. Although - that may or may not be the case depending on where and how it's used in the code base.
I don't have any preference either way, but it seems to me that investing effort to make the internals of FFmpeg safer and easier to use would be better spent on a more modern and robust language than C++.
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
@ 2025-10-22 12:42 ` Michael Niedermayer via ffmpeg-devel
2025-10-22 13:07 ` Timo Rothenpieler via ffmpeg-devel
` (2 subsequent siblings)
3 siblings, 0 replies; 22+ messages in thread
From: Michael Niedermayer via ffmpeg-devel @ 2025-10-22 12:42 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Michael Niedermayer
[-- Attachment #1.1: Type: text/plain, Size: 1190 bytes --]
Hi
On Wed, Oct 22, 2025 at 02:09:32PM +0200, Gregor Riepl via ffmpeg-devel wrote:
> > My main motivation is to be able to use STL, which would simplify
> > string handling and memory management, and give us access to its data
> > structures. Manual memory management has its place, especially in lavc.
> > In lavf less so. RAII would do wonders in de-gotofying error handling.
> > Features like std::filesystem, std::chrono, std::thread etc abstract
> > away many OS particularities. Thorough STL-ification would render parts
> > of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
> > would have security benefits. Another reason is stronger typing, which
> > tends to reveal bugs.
>
> Just for the sake of the argument: Wouldn't it be better to opt for an even safer language than C++, like Rust?
+1
i think the main question in choosing a language is the size of
the pool of developers potentially able/willing to contribute to FFmpeg using that
language
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Nations do behave wisely once they have exhausted all other alternatives.
-- Abba Eban
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 163 bytes --]
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
` (4 preceding siblings ...)
2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
@ 2025-10-22 13:05 ` Michael Niedermayer via ffmpeg-devel
2025-10-23 21:49 ` Tomas Härdin via ffmpeg-devel
2025-10-22 14:03 ` Leo Izen via ffmpeg-devel
6 siblings, 1 reply; 22+ messages in thread
From: Michael Niedermayer via ffmpeg-devel @ 2025-10-22 13:05 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Michael Niedermayer
[-- Attachment #1.1: Type: text/plain, Size: 3737 bytes --]
On Mon, Oct 20, 2025 at 07:50:33PM +0200, Tomas Härdin via ffmpeg-devel wrote:
> Hi
>
> I'm writing this email to get a feel for how everyone feels about
> making more use of C++ in the codebase. I am only proposing using C++
> *internally*, and only where it makes sense. I am not suggesting a
> "move" to C++, merely using features already present in the compilers
> we target: gcc, clang and cl. The impedance mismatch should therefore
> be small, and any missing compiler features should be caught by FATE.
>
> Currently C++ use is quite limited in this project, but I see no reason
> why this should be the case. doc/faq.texi makes mention of Linux'
> reasons for avoiding C++, but FFmpeg is not Linux. For us ABI stability
> and performance are the biggest issues. Stability can be ensured by
> sticking with C for the API and disabling exceptions (or marking
> relevant functions as noexcept). Performance may benefit in some cases.
> This would have to be tested. Again, the most performance critical
> parts can be kept as C (and asm).
>
> My main motivation is to be able to use STL, which would simplify
> string handling and memory management, and give us access to its data
> structures. Manual memory management has its place, especially in lavc.
> In lavf less so. RAII would do wonders in de-gotofying error handling.
> Features like std::filesystem, std::chrono, std::thread etc abstract
> away many OS particularities. Thorough STL-ification would render parts
> of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
> would have security benefits. Another reason is stronger typing, which
> tends to reveal bugs.
>
> I've targeted mxfdec.c as a proof-of-concept. See attached patch, which
> compiles and passes fate-mxf. It is partly inspired by our decklink
> binding. Particularly notable is the ability to resolve MXF structs
> into MXFMetadataSetType at compile time, as well as resolving strong
> references in a more type safe manner. This revealed an issue in
> mxf_parse_structural_metadata() where MXFStructuralComponent* was
> blindly cast to MXFTimecodeComponent*, which could cause code further
> down to interpret the latter as the former, which is a not so obvious
> bug that wouldn't be caught without this stronger typing.
>
> I've not made use of STL in the attached patch because that requires
> linking with libstdc++, which I couldn't be arsed to do. One practical
> example where STL would come in handy is for my work on segmented
> indexes. Specifically std::map and std::lower_bound. Various tables in
> mxfdec.c could also be targets for turning into std::map or even
> std::unordered_map. A quick experiment with callgrind suggests
> mxf_read_header() might be speed up slightly with such a change.
>
> Details like which version of C++ to use could be agreed on later if
> people feel this is a good idea. Personally I favor using the most
> recent version that our compiler suite supports. Lately I've been using
> C++20 with icx (Intel's compiler) which has been quite pleasant.
One difference that favors lower level languages is that with
high level languages one looses sight of the cost of operations
Teh closer you are to the implementation of a data structure, like
if you are on the team of people who developed or maintains it.
The more likely you are also aware of its cost or one of the reviewer
would spot you doing a O(n^2) operation as if its O(1)
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Some people wanted to paint the bikeshed green, some blue and some pink.
People argued and fought, when they finally agreed, only rust was left.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 163 bytes --]
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
2025-10-22 12:42 ` Michael Niedermayer via ffmpeg-devel
@ 2025-10-22 13:07 ` Timo Rothenpieler via ffmpeg-devel
2025-10-22 17:07 ` Rémi Denis-Courmont via ffmpeg-devel
2025-10-22 17:08 ` Rémi Denis-Courmont via ffmpeg-devel
2025-10-23 21:45 ` Tomas Härdin via ffmpeg-devel
3 siblings, 1 reply; 22+ messages in thread
From: Timo Rothenpieler via ffmpeg-devel @ 2025-10-22 13:07 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Timo Rothenpieler
[-- Attachment #1.1.1.1: Type: text/plain, Size: 2632 bytes --]
On 22.10.2025 14:09, Gregor Riepl via ffmpeg-devel wrote:
>> My main motivation is to be able to use STL, which would simplify
>> string handling and memory management, and give us access to its data
>> structures. Manual memory management has its place, especially in lavc.
>> In lavf less so. RAII would do wonders in de-gotofying error handling.
>> Features like std::filesystem, std::chrono, std::thread etc abstract
>> away many OS particularities. Thorough STL-ification would render parts
>> of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
>> would have security benefits. Another reason is stronger typing, which
>> tends to reveal bugs.
>
> Just for the sake of the argument: Wouldn't it be better to opt for an
> even safer language than C++, like Rust?
C++ can be used as-is, since it can read all our headers just fine.
Using anything else needs extensive and constant porting work, that then
will also make future iterations of internal APIs much harder if not
impossible, forcing people who have zero experience with the other
language to learn it, just to enhance the C side of things.
Plus, most of these fancy modern languages are not just a programming
language, but they also want to play package-manager, which then forces
all of its downstream users to babysit a ton of package version, which
largely don't give a damn about stable APIs.
So we then need to constantly monitor all those dependencies for bugs
and issues, and potentially a fix for one pulls in breaking API changes,
which then need to be addressed and backported.
So stuff like Rust, and anything with similar insane package ecosystems,
is a huge no from me.
Zig kinda seems interesting under those aspects, but seems a bit too
immature still, and also kinda seems weird to me with its approach of
taking over the entire build system, and not just being a compiler to
integrate like any other.
> C++ has received a lot of criticism in being just as memory unsafe as C,
> and I personally think that it adds an epic amount of complexity to
> writing correct code. Although - that may or may not be the case
> depending on where and how it's used in the code base.
>
> I don't have any preference either way, but it seems to me that
> investing effort to make the internals of FFmpeg safer and easier to use
> would be better spent on a more modern and robust language than C++.
>
> _______________________________________________
> ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
> To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
[-- Attachment #1.1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3203 bytes --]
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]
[-- Attachment #2: Type: text/plain, Size: 163 bytes --]
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
` (5 preceding siblings ...)
2025-10-22 13:05 ` Michael Niedermayer via ffmpeg-devel
@ 2025-10-22 14:03 ` Leo Izen via ffmpeg-devel
6 siblings, 0 replies; 22+ messages in thread
From: Leo Izen via ffmpeg-devel @ 2025-10-22 14:03 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Leo Izen
On 10/20/25 13:50, Tomas Härdin via ffmpeg-devel wrote:
> Hi
>
> I'm writing this email to get a feel for how everyone feels about
> making more use of C++ in the codebase. I am only proposing using C++
> *internally*, and only where it makes sense. I am not suggesting a
> "move" to C++, merely using features already present in the compilers
> we target: gcc, clang and cl. The impedance mismatch should therefore
> be small, and any missing compiler features should be caught by FATE.
>
> Currently C++ use is quite limited in this project, but I see no reason
> why this should be the case. doc/faq.texi makes mention of Linux'
> reasons for avoiding C++, but FFmpeg is not Linux. For us ABI stability
> and performance are the biggest issues. Stability can be ensured by
> sticking with C for the API and disabling exceptions (or marking
> relevant functions as noexcept). Performance may benefit in some cases.
> This would have to be tested. Again, the most performance critical
> parts can be kept as C (and asm).
>
> My main motivation is to be able to use STL...
I'm not thrilled about including the STL with C++. I've noticed from
working with C++ codebases that compile time is a lot slower because of
STL usage in header files.
- Leo Izen
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 13:07 ` Timo Rothenpieler via ffmpeg-devel
@ 2025-10-22 17:07 ` Rémi Denis-Courmont via ffmpeg-devel
2025-10-22 18:12 ` Timo Rothenpieler via ffmpeg-devel
0 siblings, 1 reply; 22+ messages in thread
From: Rémi Denis-Courmont via ffmpeg-devel @ 2025-10-22 17:07 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Rémi Denis-Courmont
Le keskiviikkona 22. lokakuuta 2025, 16.07.36 Itä-Euroopan kesäaika Timo
Rothenpieler via ffmpeg-devel a écrit :
> C++ can be used as-is, since it can read all our headers just fine.
FFmpeg public headers are C++-compatible and, frankly as a C developer, I find
that annoying. Not sure about Zig, but Rust does not care about your C headers
and won't require C programmers to muck with their header files to appease
rustc.
Or more accurately, it gives you the choice to use or not to use bindgen to
parse the C headers. And frankly, you are more often than not better off not
using it.
> Using anything else needs extensive and constant porting work, that then
> will also make future iterations of internal APIs much harder if not
> impossible, forcing people who have zero experience with the other
> language to learn it, just to enhance the C side of things.
> Plus, most of these fancy modern languages are not just a programming
> language, but they also want to play package-manager, which then forces
> all of its downstream users to babysit a ton of package version, which
> largely don't give a damn about stable APIs.
C++ sucks just as badly as Rust to make stable APIs/ABIs. In the end, you end
up having to expose a C interface, whether you're using C, C++, Zig, Rust or
anything else. And you'll have to do that forever, since C is the lingua
franca of system-level programming interfaces.
> So we then need to constantly monitor all those dependencies for bugs
> and issues, and potentially a fix for one pulls in breaking API changes,
> which then need to be addressed and backported.
FUD much? How exactly do any other language relieve you from the problem of
tracking bugs in dependencies?
Cargo gives you the *choice* of pinning or not pinning the versions through
the lock. FFmpeg should *probably* not pin anything and just specify minimum
version requirements. And it'll be the exact same dependency hell that we
already have (or don't have - that's subjective) with C. Nothing to see here.
--
ヅニ-クーモン・レミ
Villeneuve de Tapiola, ex-République finlandaise d´Uusimaa
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
2025-10-22 12:42 ` Michael Niedermayer via ffmpeg-devel
2025-10-22 13:07 ` Timo Rothenpieler via ffmpeg-devel
@ 2025-10-22 17:08 ` Rémi Denis-Courmont via ffmpeg-devel
2025-10-23 21:45 ` Tomas Härdin via ffmpeg-devel
3 siblings, 0 replies; 22+ messages in thread
From: Rémi Denis-Courmont via ffmpeg-devel @ 2025-10-22 17:08 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Rémi Denis-Courmont
Le keskiviikkona 22. lokakuuta 2025, 15.09.32 Itä-Euroopan kesäaika Gregor
Riepl via ffmpeg-devel a écrit :
> > My main motivation is to be able to use STL, which would simplify
> > string handling and memory management, and give us access to its data
> > structures. Manual memory management has its place, especially in lavc.
> > In lavf less so. RAII would do wonders in de-gotofying error handling.
> > Features like std::filesystem, std::chrono, std::thread etc abstract
> > away many OS particularities. Thorough STL-ification would render parts
> > of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind. This
> > would have security benefits. Another reason is stronger typing, which
> > tends to reveal bugs.
>
> Just for the sake of the argument: Wouldn't it be better to opt for an even
> safer language than C++, like Rust?
Yes. If the goal is to use better abstraction, notably for data structures and
memory handling, than are possible with C, then Rust provides zero-cost
abstractions. In C++, you can't do that; for instance, your virtual methods
may or may not be specialised, and you have no control over it. Also C++
provides a lot of abstractions that are nowadays widely considered just *bad*,
even by C++ advocates, such as multiple inheritance.
Rust also doesn't need its own runtime library, so it would be essentially
transparent for (binary) downstreams, whether statically or dynamically
linked. And it's actually easy for experienced C programmers to learn (been
there, done that).
The static memory safety features are just icing on the cake.
The big difficult is integrating dependency tracking from rustc, compilation
(rustc or cargo) and linking into an existing build system. But that's a one-
time cost for one motivated person to deal with. Sure, C++ would be much
easier with respect to that one specific aspect, but so what?
> C++ has received a lot of criticism in being just as memory unsafe as C, and
> I personally think that it adds an epic amount of complexity to writing
> correct code. Although - that may or may not be the case depending on where
> and how it's used in the code base.
+1
--
德尼-库尔蒙‧雷米
Tapiolan uusi kaupunki, Uudenmaan entinen Suomen tasavalta
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 17:07 ` Rémi Denis-Courmont via ffmpeg-devel
@ 2025-10-22 18:12 ` Timo Rothenpieler via ffmpeg-devel
2025-10-22 18:50 ` Rémi Denis-Courmont via ffmpeg-devel
0 siblings, 1 reply; 22+ messages in thread
From: Timo Rothenpieler via ffmpeg-devel @ 2025-10-22 18:12 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Timo Rothenpieler
[-- Attachment #1.1.1.1: Type: text/plain, Size: 2468 bytes --]
On 22.10.2025 19:07, Rémi Denis-Courmont via ffmpeg-devel wrote:
> Le keskiviikkona 22. lokakuuta 2025, 16.07.36 Itä-Euroopan kesäaika Timo
> Rothenpieler via ffmpeg-devel a écrit :
>> C++ can be used as-is, since it can read all our headers just fine.
>
> FFmpeg public headers are C++-compatible and, frankly as a C developer, I find
> that annoying. Not sure about Zig, but Rust does not care about your C headers
> and won't require C programmers to muck with their header files to appease
> rustc.
>
> Or more accurately, it gives you the choice to use or not to use bindgen to
> parse the C headers. And frankly, you are more often than not better off not
> using it.
>
>> Using anything else needs extensive and constant porting work, that then
>> will also make future iterations of internal APIs much harder if not
>> impossible, forcing people who have zero experience with the other
>> language to learn it, just to enhance the C side of things.
>
>> Plus, most of these fancy modern languages are not just a programming
>> language, but they also want to play package-manager, which then forces
>> all of its downstream users to babysit a ton of package version, which
>> largely don't give a damn about stable APIs.
>
> C++ sucks just as badly as Rust to make stable APIs/ABIs. In the end, you end
> up having to expose a C interface, whether you're using C, C++, Zig, Rust or
> anything else. And you'll have to do that forever, since C is the lingua
> franca of system-level programming interfaces.
>
>> So we then need to constantly monitor all those dependencies for bugs
>> and issues, and potentially a fix for one pulls in breaking API changes,
>> which then need to be addressed and backported.
>
> FUD much? How exactly do any other language relieve you from the problem of
> tracking bugs in dependencies?
They allow a distributor to do it centrally, and don't burden it onto
every single developer.
> Cargo gives you the *choice* of pinning or not pinning the versions through
> the lock. FFmpeg should *probably* not pin anything and just specify minimum
> version requirements. And it'll be the exact same dependency hell that we
> already have (or don't have - that's subjective) with C. Nothing to see here.
Given that API stability is far from a given in that world, not pinning
anything does not sound like a good idea.
I'd rather just not enter that dependency hell at all.
[-- Attachment #1.1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3203 bytes --]
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]
[-- Attachment #2: Type: text/plain, Size: 163 bytes --]
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 18:12 ` Timo Rothenpieler via ffmpeg-devel
@ 2025-10-22 18:50 ` Rémi Denis-Courmont via ffmpeg-devel
0 siblings, 0 replies; 22+ messages in thread
From: Rémi Denis-Courmont via ffmpeg-devel @ 2025-10-22 18:50 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Rémi Denis-Courmont
Le keskiviikkona 22. lokakuuta 2025, 21.12.47 Itä-Euroopan kesäaika Timo
Rothenpieler via ffmpeg-devel a écrit :
> They allow a distributor to do it centrally, and don't burden it onto
> every single developer.
And? Neither does Cargo? It does not force developers to pin anything. It's
*recommended* to pin if (and only if) shipping a final application or OS,
rather than libraries, i.e. unless you're the distributor.
Obviously someone is going to have to be burdened with checking versions and
bugs at some point in the supply chain, with the user as the last resort -
that's true for any programming language.
> > Cargo gives you the *choice* of pinning or not pinning the versions
> > through the lock. FFmpeg should *probably* not pin anything and just
> > specify minimum version requirements. And it'll be the exact same
> > dependency hell that we already have (or don't have - that's subjective)
> > with C. Nothing to see here.
>
> Given that API stability is far from a given in that world,
It's no more or less stable than C. It is far better than C++ where you need
to be super careful and bend over backward not to leak object type layouts
through public headers.
> not pinning anything does not sound like a good idea.
And yet FFmpeg is not currently pinning any existing dependencies. This has
nothing to do with using C++ or Rust really.
> I'd rather just not enter that dependency hell at all.
Sure, you do that by not having dependencies. That's an argument against
external dependencies (which I can get behind), and it is also an argument
against C++ which requires a runtime even if you don't touch the STL.
By design, you can do C, Rust or a mix of both, without dependencies - as
exemplified by the Linux kernel. It's just a matter of project policy. FWIW,
Rust is actually handling this more consistently and flexibily than C, since it
provides an intermediate point between freestanding and hosted environment -
not that FFmpeg supports anything less than a hosted environment.
--
ヅニ-クーモン・レミ
Hagalund ny stad, f.d. Finska republik Nylands
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
` (2 preceding siblings ...)
2025-10-22 17:08 ` Rémi Denis-Courmont via ffmpeg-devel
@ 2025-10-23 21:45 ` Tomas Härdin via ffmpeg-devel
3 siblings, 0 replies; 22+ messages in thread
From: Tomas Härdin via ffmpeg-devel @ 2025-10-23 21:45 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Tomas Härdin
ons 2025-10-22 klockan 14:09 +0200 skrev Gregor Riepl via ffmpeg-devel:
> > My main motivation is to be able to use STL, which would simplify
> > string handling and memory management, and give us access to its
> > data
> > structures. Manual memory management has its place, especially in
> > lavc.
> > In lavf less so. RAII would do wonders in de-gotofying error
> > handling.
> > Features like std::filesystem, std::chrono, std::thread etc
> > abstract
> > away many OS particularities. Thorough STL-ification would render
> > parts
> > of lavu obsolete. avstring.*, bprintf.* and tree.* come to mind.
> > This
> > would have security benefits. Another reason is stronger typing,
> > which
> > tends to reveal bugs.
>
> Just for the sake of the argument: Wouldn't it be better to opt for
> an even safer language than C++, like Rust?
There was a discussion about Rust a while back. I'm not really against
it, but the impedance mismatch is much greater. Plus there's the need
for an entirely different set of compilers. Most of our users know C++
already.
That said, gccrs is making progress so perhaps at some point this might
happen. C++ is still an improvement over the present state of things.
Plus, Katamari-C++ is likely to grow the same kind of features Rust has
anyway.
I've continued to hack at mxfdec.cpp and I'm now seeing substantial
performance improvements thanks to using STL. 182% faster
mxf_read_header for a 10,000 second file generated by mxfenc.c. This is
likely to shoot up even more as I rework the MXFIndexTableSegment code.
Greater still would be the effect of lazy reading of partitions, which
is my overall goal. I'll probably push something to forgejo once it's
firmed up a bit. Especially for Baptiste to take a look at.
I feel I should reiterate the point that whatever we choose to do we
should keep the C API, because C's ABI is stable. C++'s isn't, and
based on what Rémi is saying Rust's isn't either.
/Tomas
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-22 13:05 ` Michael Niedermayer via ffmpeg-devel
@ 2025-10-23 21:49 ` Tomas Härdin via ffmpeg-devel
2025-10-23 22:24 ` Michael Niedermayer via ffmpeg-devel
0 siblings, 1 reply; 22+ messages in thread
From: Tomas Härdin via ffmpeg-devel @ 2025-10-23 21:49 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Tomas Härdin
ons 2025-10-22 klockan 15:05 +0200 skrev Michael Niedermayer via
ffmpeg-devel:
> One difference that favors lower level languages is that with
> high level languages one looses sight of the cost of operations
>
> Teh closer you are to the implementation of a data structure, like
> if you are on the team of people who developed or maintains it.
> The more likely you are also aware of its cost or one of the reviewer
> would spot you doing a O(n^2) operation as if its O(1)
I'd argue the exact opposite. There are O(N²) spots in the code that
are entirely the result of using C'isms where STL would have given you
O(NlogN) basically for free. And where that still isn't enough there's
std::unordered_met and the like. Complexity guarantees are part of the
documentation for these types.
/Tomas
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
* [FFmpeg-devel] Re: [RFC] C++
2025-10-23 21:49 ` Tomas Härdin via ffmpeg-devel
@ 2025-10-23 22:24 ` Michael Niedermayer via ffmpeg-devel
0 siblings, 0 replies; 22+ messages in thread
From: Michael Niedermayer via ffmpeg-devel @ 2025-10-23 22:24 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Michael Niedermayer
[-- Attachment #1.1: Type: text/plain, Size: 1340 bytes --]
Hi Tomas
On Thu, Oct 23, 2025 at 11:49:31PM +0200, Tomas Härdin via ffmpeg-devel wrote:
> ons 2025-10-22 klockan 15:05 +0200 skrev Michael Niedermayer via
> ffmpeg-devel:
> > One difference that favors lower level languages is that with
> > high level languages one looses sight of the cost of operations
> >
> > Teh closer you are to the implementation of a data structure, like
> > if you are on the team of people who developed or maintains it.
> > The more likely you are also aware of its cost or one of the reviewer
> > would spot you doing a O(n^2) operation as if its O(1)
>
> I'd argue the exact opposite. There are O(N²) spots in the code that
> are entirely the result of using C'isms where STL would have given you
> O(NlogN) basically for free. And where that still isn't enough there's
> std::unordered_met and the like. Complexity guarantees are part of the
> documentation for these types.
First, there are places where O(N²) is faster than O(NlogN)
And there are places where it doesnt matter.
For what remains, please open a issue and put be in the CC, not
saying ill fix em, but iam interrested
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
It is dangerous to be right in matters on which the established authorities
are wrong. -- Voltaire
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 163 bytes --]
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2025-10-23 22:25 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-20 17:50 [FFmpeg-devel] [RFC] C++ Tomas Härdin via ffmpeg-devel
2025-10-20 21:34 ` [FFmpeg-devel] " Neal Gompa via ffmpeg-devel
2025-10-21 2:24 ` Lynne via ffmpeg-devel
2025-10-22 8:57 ` Tomas Härdin via ffmpeg-devel
2025-10-22 10:46 ` Tomas Härdin via ffmpeg-devel
2025-10-21 18:41 ` Niklas Haas via ffmpeg-devel
2025-10-22 3:15 ` Romain Beauxis via ffmpeg-devel
2025-10-22 4:19 ` InnocentZero via ffmpeg-devel
2025-10-22 8:24 ` Nicolas George via ffmpeg-devel
2025-10-22 10:53 ` Tomas Härdin via ffmpeg-devel
2025-10-22 12:09 ` Gregor Riepl via ffmpeg-devel
2025-10-22 12:42 ` Michael Niedermayer via ffmpeg-devel
2025-10-22 13:07 ` Timo Rothenpieler via ffmpeg-devel
2025-10-22 17:07 ` Rémi Denis-Courmont via ffmpeg-devel
2025-10-22 18:12 ` Timo Rothenpieler via ffmpeg-devel
2025-10-22 18:50 ` Rémi Denis-Courmont via ffmpeg-devel
2025-10-22 17:08 ` Rémi Denis-Courmont via ffmpeg-devel
2025-10-23 21:45 ` Tomas Härdin via ffmpeg-devel
2025-10-22 13:05 ` Michael Niedermayer via ffmpeg-devel
2025-10-23 21:49 ` Tomas Härdin via ffmpeg-devel
2025-10-23 22:24 ` Michael Niedermayer via ffmpeg-devel
2025-10-22 14:03 ` Leo Izen via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git