FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/mxfdec.c
Date: 2025-08-19 23:55:23
Exec Total Coverage
Lines: 1709 2323 73.6%
Functions: 86 93 92.5%
Branches: 1007 1668 60.4%

Line Branch Exec Source
1 /*
2 * MXF demuxer.
3 * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /*
23 * References
24 * SMPTE 336M KLV Data Encoding Protocol Using Key-Length-Value
25 * SMPTE 377M MXF File Format Specifications
26 * SMPTE 378M Operational Pattern 1a
27 * SMPTE 379M MXF Generic Container
28 * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container
29 * SMPTE 382M Mapping AES3 and Broadcast Wave Audio into the MXF Generic Container
30 * SMPTE 383M Mapping DV-DIF Data to the MXF Generic Container
31 * SMPTE 2067-21 Interoperable Master Format — Application #2E
32 *
33 * Principle
34 * Search for Track numbers which will identify essence element KLV packets.
35 * Search for SourcePackage which define tracks which contains Track numbers.
36 * Material Package contains tracks with reference to SourcePackage tracks.
37 * Search for Descriptors (Picture, Sound) which contains codec info and parameters.
38 * Assign Descriptors to correct Tracks.
39 *
40 * Metadata reading functions read Local Tags, get InstanceUID(0x3C0A) then add MetaDataSet to MXFContext.
41 * Metadata parsing resolves Strong References to objects.
42 *
43 * Simple demuxer, only OP1A supported and some files might not work at all.
44 * Only tracks with associated descriptors will be decoded. "Highly Desirable" SMPTE 377M D.1
45 */
46
47 #include <inttypes.h>
48 #include <time.h>
49
50 #include "libavutil/aes.h"
51 #include "libavutil/avstring.h"
52 #include "libavutil/mastering_display_metadata.h"
53 #include "libavutil/mathematics.h"
54 #include "libavutil/mem.h"
55 #include "libavcodec/bytestream.h"
56 #include "libavcodec/defs.h"
57 #include "libavcodec/internal.h"
58 #include "libavutil/channel_layout.h"
59 #include "libavutil/intreadwrite.h"
60 #include "libavutil/parseutils.h"
61 #include "libavutil/timecode.h"
62 #include "libavutil/opt.h"
63 #include "avformat.h"
64 #include "avlanguage.h"
65 #include "avio_internal.h"
66 #include "demux.h"
67 #include "internal.h"
68 #include "mxf.h"
69
70 #define MXF_MAX_CHUNK_SIZE (32 << 20)
71 #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
72
73 typedef enum {
74 Header,
75 BodyPartition,
76 Footer
77 } MXFPartitionType;
78
79 typedef enum {
80 OP1a = 1,
81 OP1b,
82 OP1c,
83 OP2a,
84 OP2b,
85 OP2c,
86 OP3a,
87 OP3b,
88 OP3c,
89 OPAtom,
90 OPSONYOpt, /* FATE sample, violates the spec in places */
91 } MXFOP;
92
93 typedef enum {
94 UnknownWrapped = 0,
95 FrameWrapped,
96 ClipWrapped,
97 } MXFWrappingScheme;
98
99 typedef struct MXFPartition {
100 int closed;
101 int complete;
102 MXFPartitionType type;
103 uint64_t previous_partition;
104 int index_sid;
105 int body_sid;
106 int64_t essence_offset; ///< absolute offset of essence
107 int64_t essence_length;
108 int32_t kag_size;
109 int64_t header_byte_count;
110 int64_t index_byte_count;
111 int pack_length;
112 int64_t pack_ofs; ///< absolute offset of pack in file, including run-in
113 int64_t body_offset;
114 KLVPacket first_essence_klv;
115 } MXFPartition;
116
117 typedef struct MXFMetadataSet {
118 UID uid;
119 uint64_t partition_score;
120 } MXFMetadataSet;
121
122 typedef struct MXFMetadataSetGroup {
123 MXFMetadataSet **metadata_sets;
124 int metadata_sets_count;
125 } MXFMetadataSetGroup;
126
127 typedef struct MXFCryptoContext {
128 MXFMetadataSet meta;
129 UID source_container_ul;
130 } MXFCryptoContext;
131
132 typedef struct MXFStructuralComponent {
133 MXFMetadataSet meta;
134 UID source_package_ul;
135 UID source_package_uid;
136 UID data_definition_ul;
137 int64_t duration;
138 int64_t start_position;
139 int source_track_id;
140 } MXFStructuralComponent;
141
142 typedef struct MXFSequence {
143 MXFMetadataSet meta;
144 UID data_definition_ul;
145 UID *structural_components_refs;
146 int structural_components_count;
147 int64_t duration;
148 uint8_t origin;
149 } MXFSequence;
150
151 typedef struct MXFTimecodeComponent {
152 MXFMetadataSet meta;
153 int drop_frame;
154 int start_frame;
155 struct AVRational rate;
156 AVTimecode tc;
157 } MXFTimecodeComponent;
158
159 typedef struct {
160 MXFMetadataSet meta;
161 UID input_segment_ref;
162 } MXFPulldownComponent;
163
164 typedef struct {
165 MXFMetadataSet meta;
166 UID *structural_components_refs;
167 int structural_components_count;
168 int64_t duration;
169 } MXFEssenceGroup;
170
171 typedef struct {
172 MXFMetadataSet meta;
173 char *name;
174 char *value;
175 } MXFTaggedValue;
176
177 typedef struct {
178 MXFMetadataSet meta;
179 MXFSequence *sequence; /* mandatory, and only one */
180 UID sequence_ref;
181 int track_id;
182 char *name;
183 uint8_t track_number[4];
184 AVRational edit_rate;
185 int intra_only;
186 uint64_t sample_count;
187 int64_t original_duration; /* st->duration in SampleRate/EditRate units */
188 int index_sid;
189 int body_sid;
190 MXFWrappingScheme wrapping;
191 int edit_units_per_packet; /* how many edit units to read at a time (PCM, ClipWrapped) */
192 } MXFTrack;
193
194 typedef struct MXFDescriptor {
195 MXFMetadataSet meta;
196 UID essence_container_ul;
197 UID essence_codec_ul;
198 UID codec_ul;
199 AVRational sample_rate;
200 AVRational aspect_ratio;
201 int width;
202 int height; /* Field height, not frame height */
203 int frame_layout; /* See MXFFrameLayout enum */
204 int video_line_map[2];
205 #define MXF_FIELD_DOMINANCE_DEFAULT 0
206 #define MXF_FIELD_DOMINANCE_FF 1 /* coded first, displayed first */
207 #define MXF_FIELD_DOMINANCE_FL 2 /* coded first, displayed last */
208 int field_dominance;
209 int channels;
210 int bits_per_sample;
211 int64_t duration; /* ContainerDuration optional property */
212 unsigned int component_depth;
213 unsigned int black_ref_level;
214 unsigned int white_ref_level;
215 unsigned int color_range;
216 unsigned int horiz_subsampling;
217 unsigned int vert_subsampling;
218 UID *file_descriptors_refs;
219 int file_descriptors_count;
220 UID *sub_descriptors_refs;
221 int sub_descriptors_count;
222 int linked_track_id;
223 uint8_t *extradata;
224 int extradata_size;
225 enum AVPixelFormat pix_fmt;
226 UID color_primaries_ul;
227 UID color_trc_ul;
228 UID color_space_ul;
229 AVMasteringDisplayMetadata *mastering;
230 size_t mastering_size;
231 AVContentLightMetadata *coll;
232 size_t coll_size;
233 } MXFDescriptor;
234
235 typedef struct MXFMCASubDescriptor {
236 MXFMetadataSet meta;
237 UID uid;
238 UID mca_link_id;
239 UID soundfield_group_link_id;
240 UID *group_of_soundfield_groups_link_id_refs;
241 int group_of_soundfield_groups_link_id_count;
242 UID mca_label_dictionary_id;
243 int mca_channel_id;
244 char *language;
245 } MXFMCASubDescriptor;
246
247 typedef struct MXFFFV1SubDescriptor {
248 MXFMetadataSet meta;
249 uint8_t *extradata;
250 int extradata_size;
251 } MXFFFV1SubDescriptor;
252
253 typedef struct MXFIndexTableSegment {
254 MXFMetadataSet meta;
255 unsigned edit_unit_byte_count;
256 int index_sid;
257 int body_sid;
258 AVRational index_edit_rate;
259 uint64_t index_start_position;
260 uint64_t index_duration;
261 int8_t *temporal_offset_entries;
262 int *flag_entries;
263 uint64_t *stream_offset_entries;
264 int nb_index_entries;
265 int64_t offset;
266 } MXFIndexTableSegment;
267
268 typedef struct MXFPackage {
269 MXFMetadataSet meta;
270 UID package_uid;
271 UID package_ul;
272 UID *tracks_refs;
273 int tracks_count;
274 UID descriptor_ref;
275 char *name;
276 UID *comment_refs;
277 int comment_count;
278 } MXFPackage;
279
280 typedef struct MXFEssenceContainerData {
281 MXFMetadataSet meta;
282 UID package_uid;
283 UID package_ul;
284 int index_sid;
285 int body_sid;
286 } MXFEssenceContainerData;
287
288 /* decoded index table */
289 typedef struct MXFIndexTable {
290 int index_sid;
291 int body_sid;
292 int nb_ptses; /* number of PTSes or total duration of index */
293 int64_t first_dts; /* DTS = EditUnit + first_dts */
294 int64_t *ptses; /* maps EditUnit -> PTS */
295 int nb_segments;
296 MXFIndexTableSegment **segments; /* sorted by IndexStartPosition */
297 AVIndexEntry *fake_index; /* used for calling ff_index_search_timestamp() */
298 int8_t *offsets; /* temporal offsets for display order to stored order conversion */
299 } MXFIndexTable;
300
301 typedef struct MXFContext {
302 const AVClass *class; /**< Class for private options. */
303 MXFPartition *partitions;
304 unsigned partitions_count;
305 MXFOP op;
306 UID *packages_refs;
307 int packages_count;
308 UID *essence_container_data_refs;
309 int essence_container_data_count;
310 MXFMetadataSetGroup metadata_set_groups[MetadataSetTypeNB];
311 AVFormatContext *fc;
312 struct AVAES *aesc;
313 uint8_t *local_tags;
314 int local_tags_count;
315 uint64_t footer_partition;
316 KLVPacket current_klv_data;
317 int run_in;
318 MXFPartition *current_partition;
319 int parsing_backward;
320 int64_t last_forward_tell;
321 int last_forward_partition;
322 int nb_index_tables;
323 MXFIndexTable *index_tables;
324 int eia608_extract;
325 } MXFContext;
326
327 /* NOTE: klv_offset is not set (-1) for local keys */
328 typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset);
329
330 typedef struct MXFMetadataReadTableEntry {
331 const UID key;
332 MXFMetadataReadFunc *read; /* if NULL then skip KLV */
333 int ctx_size;
334 enum MXFMetadataSetType type;
335 } MXFMetadataReadTableEntry;
336
337 /* partial keys to match */
338 static const uint8_t mxf_header_partition_pack_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 };
339 static const uint8_t mxf_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 };
340 static const uint8_t mxf_avid_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0e,0x04,0x03,0x01 };
341 static const uint8_t mxf_canopus_essence_element_key[] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x0a,0x0e,0x0f,0x03,0x01 };
342 static const uint8_t mxf_system_item_key_cp[] = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x03,0x01,0x04 };
343 static const uint8_t mxf_system_item_key_gc[] = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x03,0x01,0x14 };
344 static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 };
345 static const uint8_t mxf_apple_coll_prefix[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01 };
346
347 /* complete keys to match */
348 static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 };
349 static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 };
350 static const uint8_t mxf_encrypted_essence_container[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0b,0x01,0x00 };
351 static const uint8_t mxf_sony_mpeg4_extradata[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0e,0x06,0x06,0x02,0x02,0x01,0x00,0x00 };
352 static const uint8_t mxf_ffv1_extradata[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x01,0x06,0x0c,0x01,0x00,0x00,0x00 }; // FFV1InitializationMetadata
353 static const uint8_t mxf_avid_project_name[] = { 0xa5,0xfb,0x7b,0x25,0xf6,0x15,0x94,0xb9,0x62,0xfc,0x37,0x17,0x49,0x2d,0x42,0xbf };
354 static const uint8_t mxf_jp2k_rsiz[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0a,0x04,0x01,0x06,0x03,0x01,0x00,0x00,0x00 };
355 static const uint8_t mxf_indirect_value_utf16le[] = { 0x4c,0x00,0x02,0x10,0x01,0x00,0x00,0x00,0x00,0x06,0x0e,0x2b,0x34,0x01,0x04,0x01,0x01 };
356 static const uint8_t mxf_indirect_value_utf16be[] = { 0x42,0x01,0x10,0x02,0x00,0x00,0x00,0x00,0x00,0x06,0x0e,0x2b,0x34,0x01,0x04,0x01,0x01 };
357 static const uint8_t mxf_apple_coll_max_cll[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x01 };
358 static const uint8_t mxf_apple_coll_max_fall[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x02 };
359
360 static const uint8_t mxf_mca_label_dictionary_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x01,0x00,0x00,0x00 };
361 static const uint8_t mxf_mca_tag_symbol[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x02,0x00,0x00,0x00 };
362 static const uint8_t mxf_mca_tag_name[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x03,0x00,0x00,0x00 };
363 static const uint8_t mxf_group_of_soundfield_groups_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x04,0x00,0x00,0x00 };
364 static const uint8_t mxf_mca_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x05,0x00,0x00,0x00 };
365 static const uint8_t mxf_mca_channel_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x04,0x0a,0x00,0x00,0x00,0x00 };
366 static const uint8_t mxf_soundfield_group_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x06,0x00,0x00,0x00 };
367 static const uint8_t mxf_mca_rfc5646_spoken_language[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0d,0x03,0x01,0x01,0x02,0x03,0x15,0x00,0x00 };
368
369 static const uint8_t mxf_sub_descriptor[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00 };
370
371 static const uint8_t mxf_mastering_display_prefix[13] = { FF_MXF_MasteringDisplay_PREFIX };
372 static const uint8_t mxf_mastering_display_uls[4][16] = {
373 FF_MXF_MasteringDisplayPrimaries,
374 FF_MXF_MasteringDisplayWhitePointChromaticity,
375 FF_MXF_MasteringDisplayMaximumLuminance,
376 FF_MXF_MasteringDisplayMinimumLuminance,
377 };
378
379 #define IS_KLV_KEY(x, y) (!memcmp(x, y, sizeof(y)))
380
381 2953 static void mxf_free_metadataset(MXFMetadataSet **ctx, enum MXFMetadataSetType type)
382 {
383 MXFIndexTableSegment *seg;
384
9/10
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 692 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 225 times.
✓ Branch 6 taken 105 times.
✓ Branch 7 taken 692 times.
✓ Branch 8 taken 112 times.
✓ Branch 9 taken 801 times.
2953 switch (type) {
385 323 case Descriptor:
386 case MultipleDescriptor:
387 323 av_freep(&((MXFDescriptor *)*ctx)->extradata);
388 323 av_freep(&((MXFDescriptor *)*ctx)->mastering);
389 323 av_freep(&((MXFDescriptor *)*ctx)->coll);
390 323 av_freep(&((MXFDescriptor *)*ctx)->file_descriptors_refs);
391 323 av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs);
392 323 break;
393 1 case FFV1SubDescriptor:
394 1 av_freep(&((MXFFFV1SubDescriptor *)*ctx)->extradata);
395 1 break;
396 case AudioChannelLabelSubDescriptor:
397 case SoundfieldGroupLabelSubDescriptor:
398 case GroupOfSoundfieldGroupsLabelSubDescriptor:
399 av_freep(&((MXFMCASubDescriptor *)*ctx)->language);
400 av_freep(&((MXFMCASubDescriptor *)*ctx)->group_of_soundfield_groups_link_id_refs);
401 break;
402 692 case Sequence:
403 692 av_freep(&((MXFSequence *)*ctx)->structural_components_refs);
404 692 break;
405 2 case EssenceGroup:
406 2 av_freep(&((MXFEssenceGroup *)*ctx)->structural_components_refs);
407 2 break;
408 225 case SourcePackage:
409 case MaterialPackage:
410 225 av_freep(&((MXFPackage *)*ctx)->tracks_refs);
411 225 av_freep(&((MXFPackage *)*ctx)->name);
412 225 av_freep(&((MXFPackage *)*ctx)->comment_refs);
413 225 break;
414 105 case TaggedValue:
415 105 av_freep(&((MXFTaggedValue *)*ctx)->name);
416 105 av_freep(&((MXFTaggedValue *)*ctx)->value);
417 105 break;
418 692 case Track:
419 692 av_freep(&((MXFTrack *)*ctx)->name);
420 692 break;
421 112 case IndexTableSegment:
422 112 seg = (MXFIndexTableSegment *)*ctx;
423 112 av_freep(&seg->temporal_offset_entries);
424 112 av_freep(&seg->flag_entries);
425 112 av_freep(&seg->stream_offset_entries);
426 913 default:
427 913 break;
428 }
429 2953 av_freep(ctx);
430 2953 }
431
432 26911 static int64_t klv_decode_ber_length(AVIOContext *pb, int *llen)
433 {
434 26911 uint64_t size = avio_r8(pb);
435
2/2
✓ Branch 0 taken 24898 times.
✓ Branch 1 taken 2013 times.
26911 if (size & 0x80) { /* long form */
436 24898 int bytes_num = size & 0x7f;
437 /* SMPTE 379M 5.3.4 guarantee that bytes_num must not exceed 8 bytes */
438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24898 times.
24898 if (bytes_num > 8)
439 return AVERROR_INVALIDDATA;
440
1/2
✓ Branch 0 taken 24898 times.
✗ Branch 1 not taken.
24898 if (llen)
441 24898 *llen = bytes_num + 1;
442 24898 size = 0;
443
2/2
✓ Branch 0 taken 98523 times.
✓ Branch 1 taken 24898 times.
123421 while (bytes_num--)
444 98523 size = size << 8 | avio_r8(pb);
445
1/2
✓ Branch 0 taken 2013 times.
✗ Branch 1 not taken.
2013 } else if (llen) {
446 2013 *llen = 1;
447 }
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26911 times.
26911 if (size > INT64_MAX)
449 return AVERROR_INVALIDDATA;
450 26911 return size;
451 }
452
453 108 static int mxf_read_sync(AVIOContext *pb, const uint8_t *key, unsigned size)
454 {
455 int i, b;
456
3/4
✓ Branch 0 taken 1520 times.
✓ Branch 1 taken 108 times.
✓ Branch 3 taken 1520 times.
✗ Branch 4 not taken.
1628 for (i = 0; i < size && !avio_feof(pb); i++) {
457 1520 b = avio_r8(pb);
458
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 1412 times.
1520 if (b == key[0])
459 108 i = 0;
460
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1404 times.
1412 else if (b != key[i])
461 8 i = -1;
462 }
463 108 return i == size;
464 }
465
466 // special case of mxf_read_sync for mxf_klv_key
467 27045 static int mxf_read_sync_klv(AVIOContext *pb)
468 {
469 27045 uint32_t key = avio_rb32(pb);
470 // key will never match mxf_klv_key on EOF
471
2/2
✓ Branch 0 taken 26903 times.
✓ Branch 1 taken 142 times.
27045 if (key == AV_RB32(mxf_klv_key))
472 26903 return 1;
473
474
2/2
✓ Branch 1 taken 60493 times.
✓ Branch 2 taken 134 times.
60627 while (!avio_feof(pb)) {
475 60493 key = (key << 8) | avio_r8(pb);
476
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 60485 times.
60493 if (key == AV_RB32(mxf_klv_key))
477 8 return 1;
478 }
479 134 return 0;
480 }
481
482 27045 static int klv_read_packet(MXFContext *mxf, KLVPacket *klv, AVIOContext *pb)
483 {
484 int64_t length, pos;
485 int llen;
486
487
2/2
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 26911 times.
27045 if (!mxf_read_sync_klv(pb))
488 134 return AVERROR_INVALIDDATA;
489 26911 klv->offset = avio_tell(pb) - 4;
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26911 times.
26911 if (klv->offset < mxf->run_in)
491 return AVERROR_INVALIDDATA;
492
493 26911 memcpy(klv->key, mxf_klv_key, 4);
494 26911 int ret = ffio_read_size(pb, klv->key + 4, 12);
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26911 times.
26911 if (ret < 0)
496 return ret;
497 26911 length = klv_decode_ber_length(pb, &llen);
498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26911 times.
26911 if (length < 0)
499 return length;
500 26911 klv->length = length;
501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26911 times.
26911 if (klv->offset > INT64_MAX - 16 - llen)
502 return AVERROR_INVALIDDATA;
503
504 26911 pos = klv->offset + 16 + llen;
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26911 times.
26911 if (pos > INT64_MAX - length)
506 return AVERROR_INVALIDDATA;
507 26911 klv->next_klv = pos + length;
508 26911 return 0;
509 }
510
511 5201 static int mxf_get_stream_index(AVFormatContext *s, KLVPacket *klv, int body_sid)
512 {
513
1/2
✓ Branch 0 taken 8408 times.
✗ Branch 1 not taken.
8408 for (int i = 0; i < s->nb_streams; i++) {
514 8408 MXFTrack *track = s->streams[i]->priv_data;
515 /* SMPTE 379M 7.3 */
516
7/10
✓ Branch 0 taken 8381 times.
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 8381 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8381 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8381 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5201 times.
✓ Branch 9 taken 3180 times.
8408 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)))
517 5201 return i;
518 }
519 /* return 0 if only one stream, for OP Atom files with 0 as track number */
520 return s->nb_streams == 1 && s->streams[0]->priv_data ? 0 : -1;
521 }
522
523 5201 static int find_body_sid_by_absolute_offset(MXFContext *mxf, int64_t offset)
524 {
525 // we look for partition where the offset is placed
526 int a, b, m;
527 int64_t pack_ofs;
528
529 5201 a = -1;
530 5201 b = mxf->partitions_count;
531
532
2/2
✓ Branch 0 taken 10317 times.
✓ Branch 1 taken 5201 times.
15518 while (b - a > 1) {
533 10317 m = (a + b) >> 1;
534 10317 pack_ofs = mxf->partitions[m].pack_ofs;
535
2/2
✓ Branch 0 taken 5201 times.
✓ Branch 1 taken 5116 times.
10317 if (pack_ofs <= offset)
536 5201 a = m;
537 else
538 5116 b = m;
539 }
540
541
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5201 times.
5201 if (a == -1)
542 return 0;
543 5201 return mxf->partitions[a].body_sid;
544 }
545
546 static int mxf_get_eia608_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt, int64_t length)
547 {
548 int count = avio_rb16(s->pb);
549 int cdp_identifier, cdp_length, cdp_footer_id, ccdata_id, cc_count;
550 int line_num, sample_coding, sample_count;
551 int did, sdid, data_length;
552 int ret;
553
554 if (count > 1)
555 av_log(s, AV_LOG_WARNING, "unsupported multiple ANC packets (%d) per KLV packet\n", count);
556
557 for (int i = 0; i < count; i++) {
558 if (length < 6) {
559 av_log(s, AV_LOG_ERROR, "error reading s436m packet %"PRId64"\n", length);
560 return AVERROR_INVALIDDATA;
561 }
562 line_num = avio_rb16(s->pb);
563 avio_r8(s->pb); // wrapping type
564 sample_coding = avio_r8(s->pb);
565 sample_count = avio_rb16(s->pb);
566 length -= 6 + 8 + sample_count;
567 if (line_num != 9 && line_num != 11)
568 continue;
569 if (sample_coding == 7 || sample_coding == 8 || sample_coding == 9) {
570 av_log(s, AV_LOG_WARNING, "unsupported s436m 10 bit sample coding\n");
571 continue;
572 }
573 if (length < 0)
574 return AVERROR_INVALIDDATA;
575
576 avio_rb32(s->pb); // array count
577 avio_rb32(s->pb); // array elem size
578 did = avio_r8(s->pb);
579 sdid = avio_r8(s->pb);
580 data_length = avio_r8(s->pb);
581 if (did != 0x61 || sdid != 1) {
582 av_log(s, AV_LOG_WARNING, "unsupported did or sdid: %x %x\n", did, sdid);
583 continue;
584 }
585 cdp_identifier = avio_rb16(s->pb); // cdp id
586 if (cdp_identifier != 0x9669) {
587 av_log(s, AV_LOG_ERROR, "wrong cdp identifier %x\n", cdp_identifier);
588 return AVERROR_INVALIDDATA;
589 }
590 cdp_length = avio_r8(s->pb);
591 avio_r8(s->pb); // cdp_frame_rate
592 avio_r8(s->pb); // cdp_flags
593 avio_rb16(s->pb); // cdp_hdr_sequence_cntr
594 ccdata_id = avio_r8(s->pb); // ccdata_id
595 if (ccdata_id != 0x72) {
596 av_log(s, AV_LOG_ERROR, "wrong cdp data section %x\n", ccdata_id);
597 return AVERROR_INVALIDDATA;
598 }
599 cc_count = avio_r8(s->pb) & 0x1f;
600 ret = av_get_packet(s->pb, pkt, cc_count * 3);
601 if (ret < 0)
602 return ret;
603 if (cdp_length - 9 - 4 < cc_count * 3) {
604 av_log(s, AV_LOG_ERROR, "wrong cdp size %d cc count %d\n", cdp_length, cc_count);
605 return AVERROR_INVALIDDATA;
606 }
607 avio_skip(s->pb, data_length - 9 - 4 - cc_count * 3);
608 cdp_footer_id = avio_r8(s->pb);
609 if (cdp_footer_id != 0x74) {
610 av_log(s, AV_LOG_ERROR, "wrong cdp footer section %x\n", cdp_footer_id);
611 return AVERROR_INVALIDDATA;
612 }
613 avio_rb16(s->pb); // cdp_ftr_sequence_cntr
614 avio_r8(s->pb); // packet_checksum
615 break;
616 }
617
618 return 0;
619 }
620
621 /* XXX: use AVBitStreamFilter */
622 924 static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length)
623 {
624 const uint8_t *buf_ptr, *end_ptr;
625 uint8_t *data_ptr;
626
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 924 times.
924 if (length > 61444) /* worst case PAL 1920 samples 8 channels */
628 return AVERROR_INVALIDDATA;
629 924 length = av_get_packet(pb, pkt, length);
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 924 times.
924 if (length < 0)
631 return length;
632 924 data_ptr = pkt->data;
633 924 end_ptr = pkt->data + length;
634 924 buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */
635
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 924 times.
924 if (st->codecpar->ch_layout.nb_channels > 8)
637 return AVERROR_INVALIDDATA;
638
639
2/2
✓ Branch 0 taken 1774080 times.
✓ Branch 1 taken 924 times.
1775004 for (; end_ptr - buf_ptr >= st->codecpar->ch_layout.nb_channels * 4; ) {
640
2/2
✓ Branch 0 taken 3824640 times.
✓ Branch 1 taken 1774080 times.
5598720 for (int i = 0; i < st->codecpar->ch_layout.nb_channels; i++) {
641 3824640 uint32_t sample = bytestream_get_le32(&buf_ptr);
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3824640 times.
3824640 if (st->codecpar->bits_per_coded_sample == 24)
643 bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff);
644 else
645 3824640 bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff);
646 }
647 // always 8 channels stored SMPTE 331M
648 1774080 buf_ptr += 32 - st->codecpar->ch_layout.nb_channels * 4;
649 }
650 924 av_shrink_packet(pkt, data_ptr - pkt->data);
651 924 return 0;
652 }
653
654 static int mxf_decrypt_triplet(AVFormatContext *s, AVPacket *pkt, KLVPacket *klv)
655 {
656 static const uint8_t checkv[16] = {0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b};
657 MXFContext *mxf = s->priv_data;
658 AVIOContext *pb = s->pb;
659 int64_t end = avio_tell(pb) + klv->length;
660 int64_t size;
661 uint64_t orig_size;
662 uint64_t plaintext_size;
663 uint8_t ivec[16];
664 uint8_t tmpbuf[16];
665 int ret;
666 int index;
667 int body_sid;
668
669 if (!mxf->aesc && s->key && s->keylen == 16) {
670 mxf->aesc = av_aes_alloc();
671 if (!mxf->aesc)
672 return AVERROR(ENOMEM);
673 av_aes_init(mxf->aesc, s->key, 128, 1);
674 }
675 // crypto context
676 size = klv_decode_ber_length(pb, NULL);
677 if (size < 0)
678 return size;
679 avio_skip(pb, size);
680 // plaintext offset
681 klv_decode_ber_length(pb ,NULL);
682 plaintext_size = avio_rb64(pb);
683 // source klv key
684 klv_decode_ber_length(pb, NULL);
685 avio_read(pb, klv->key, 16);
686 if (!IS_KLV_KEY(klv, mxf_essence_element_key))
687 return AVERROR_INVALIDDATA;
688
689 body_sid = find_body_sid_by_absolute_offset(mxf, klv->offset);
690 index = mxf_get_stream_index(s, klv, body_sid);
691 if (index < 0)
692 return AVERROR_INVALIDDATA;
693 // source size
694 klv_decode_ber_length(pb, NULL);
695 orig_size = avio_rb64(pb);
696 if (orig_size < plaintext_size)
697 return AVERROR_INVALIDDATA;
698 // enc. code
699 size = klv_decode_ber_length(pb, NULL);
700 if (size < 32 || size - 32 < orig_size || (int)orig_size != orig_size)
701 return AVERROR_INVALIDDATA;
702 avio_read(pb, ivec, 16);
703 ret = ffio_read_size(pb, tmpbuf, 16);
704 if (ret < 16)
705 return ret;
706 if (mxf->aesc)
707 av_aes_crypt(mxf->aesc, tmpbuf, tmpbuf, 1, ivec, 1);
708 if (memcmp(tmpbuf, checkv, 16))
709 av_log(s, AV_LOG_ERROR, "probably incorrect decryption key\n");
710 size -= 32;
711 size = av_get_packet(pb, pkt, size);
712 if (size < 0)
713 return size;
714 else if (size < plaintext_size)
715 return AVERROR_INVALIDDATA;
716 size -= plaintext_size;
717 if (mxf->aesc)
718 av_aes_crypt(mxf->aesc, &pkt->data[plaintext_size],
719 &pkt->data[plaintext_size], size >> 4, ivec, 1);
720 av_shrink_packet(pkt, orig_size);
721 pkt->stream_index = index;
722 avio_skip(pb, end - avio_tell(pb));
723 return 0;
724 }
725
726 109 static int mxf_read_primer_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
727 {
728 109 MXFContext *mxf = arg;
729 109 int item_num = avio_rb32(pb);
730 109 int item_len = avio_rb32(pb);
731
732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 if (item_len != 18) {
733 avpriv_request_sample(pb, "Primer pack item length %d", item_len);
734 return AVERROR_PATCHWELCOME;
735 }
736
2/4
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 109 times.
109 if (item_num > 65536 || item_num < 0) {
737 av_log(mxf->fc, AV_LOG_ERROR, "item_num %d is too large\n", item_num);
738 return AVERROR_INVALIDDATA;
739 }
740
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 108 times.
109 if (mxf->local_tags)
741 1 av_log(mxf->fc, AV_LOG_VERBOSE, "Multiple primer packs\n");
742 109 av_free(mxf->local_tags);
743 109 mxf->local_tags_count = 0;
744 109 mxf->local_tags = av_calloc(item_num, item_len);
745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109 if (!mxf->local_tags)
746 return AVERROR(ENOMEM);
747 109 mxf->local_tags_count = item_num;
748 109 avio_read(pb, mxf->local_tags, item_num*item_len);
749 109 return 0;
750 }
751
752 270 static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
753 {
754 270 MXFContext *mxf = arg;
755 270 AVFormatContext *s = mxf->fc;
756 MXFPartition *partition, *tmp_part;
757 UID op;
758 uint64_t footer_partition;
759 uint32_t nb_essence_containers;
760 uint64_t this_partition;
761 int ret;
762
763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
270 if (mxf->partitions_count >= INT_MAX / 2)
764 return AVERROR_INVALIDDATA;
765
766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
270 av_assert0(klv_offset >= mxf->run_in);
767
768 270 tmp_part = av_realloc_array(mxf->partitions, mxf->partitions_count + 1, sizeof(*mxf->partitions));
769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
270 if (!tmp_part)
770 return AVERROR(ENOMEM);
771 270 mxf->partitions = tmp_part;
772
773
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 165 times.
270 if (mxf->parsing_backward) {
774 /* insert the new partition pack in the middle
775 * this makes the entries in mxf->partitions sorted by offset */
776 105 memmove(&mxf->partitions[mxf->last_forward_partition+1],
777 105 &mxf->partitions[mxf->last_forward_partition],
778 105 (mxf->partitions_count - mxf->last_forward_partition)*sizeof(*mxf->partitions));
779 105 partition = mxf->current_partition = &mxf->partitions[mxf->last_forward_partition];
780 } else {
781 165 mxf->last_forward_partition++;
782 165 partition = mxf->current_partition = &mxf->partitions[mxf->partitions_count];
783 }
784
785 270 memset(partition, 0, sizeof(*partition));
786 270 mxf->partitions_count++;
787 270 partition->pack_length = avio_tell(pb) - klv_offset + size;
788 270 partition->pack_ofs = klv_offset;
789
790
3/4
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 101 times.
✗ Branch 3 not taken.
270 switch(uid[13]) {
791 108 case 2:
792 108 partition->type = Header;
793 108 break;
794 61 case 3:
795 61 partition->type = BodyPartition;
796 61 break;
797 101 case 4:
798 101 partition->type = Footer;
799 101 break;
800 default:
801 av_log(mxf->fc, AV_LOG_ERROR, "unknown partition type %i\n", uid[13]);
802 return AVERROR_INVALIDDATA;
803 }
804
805 /* consider both footers to be closed (there is only Footer and CompleteFooter) */
806
4/4
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 168 times.
✓ Branch 3 taken 1 times.
270 partition->closed = partition->type == Footer || !(uid[14] & 1);
807 270 partition->complete = uid[14] > 2;
808 270 avio_skip(pb, 4);
809 270 partition->kag_size = avio_rb32(pb);
810 270 this_partition = avio_rb64(pb);
811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
270 if (this_partition != klv_offset - mxf->run_in) {
812 av_log(mxf->fc, AV_LOG_ERROR,
813 "this_partition %"PRId64" mismatches %"PRId64"\n",
814 this_partition, klv_offset - mxf->run_in);
815 return AVERROR_INVALIDDATA;
816 }
817 270 partition->previous_partition = avio_rb64(pb);
818 270 footer_partition = avio_rb64(pb);
819 270 partition->header_byte_count = avio_rb64(pb);
820 270 partition->index_byte_count = avio_rb64(pb);
821 270 partition->index_sid = avio_rb32(pb);
822 270 partition->body_offset = avio_rb64(pb);
823 270 partition->body_sid = avio_rb32(pb);
824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
270 if (partition->body_offset < 0)
825 return AVERROR_INVALIDDATA;
826
827 270 ret = ffio_read_size(pb, op, sizeof(UID));
828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
270 if (ret < 0) {
829 av_log(mxf->fc, AV_LOG_ERROR, "Failed reading UID\n");
830 return ret;
831 }
832 270 nb_essence_containers = avio_rb32(pb);
833
834
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 162 times.
270 if (partition->type == Header) {
835 char str[36];
836 108 snprintf(str, sizeof(str), "%08x.%08x.%08x.%08x", AV_RB32(&op[0]), AV_RB32(&op[4]), AV_RB32(&op[8]), AV_RB32(&op[12]));
837 108 av_dict_set(&s->metadata, "operational_pattern_ul", str, 0);
838 }
839
840
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 108 times.
270 if (this_partition &&
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
162 partition->previous_partition == this_partition) {
842 av_log(mxf->fc, AV_LOG_ERROR,
843 "PreviousPartition equal to ThisPartition %"PRIx64"\n",
844 partition->previous_partition);
845 /* override with the actual previous partition offset */
846 if (!mxf->parsing_backward && mxf->last_forward_partition > 1) {
847 MXFPartition *prev =
848 mxf->partitions + mxf->last_forward_partition - 2;
849 partition->previous_partition = prev->pack_ofs - mxf->run_in;
850 }
851 /* if no previous body partition are found point to the header
852 * partition */
853 if (partition->previous_partition == this_partition)
854 partition->previous_partition = 0;
855 av_log(mxf->fc, AV_LOG_ERROR,
856 "Overriding PreviousPartition with %"PRIx64"\n",
857 partition->previous_partition);
858 }
859
860 /* some files don't have FooterPartition set in every partition */
861
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 18 times.
270 if (footer_partition) {
862
3/4
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 248 times.
252 if (mxf->footer_partition && mxf->footer_partition != footer_partition) {
863 av_log(mxf->fc, AV_LOG_ERROR,
864 "inconsistent FooterPartition value: %"PRIu64" != %"PRIu64"\n",
865 mxf->footer_partition, footer_partition);
866 } else {
867 252 mxf->footer_partition = footer_partition;
868 }
869 }
870
871 270 av_log(mxf->fc, AV_LOG_TRACE,
872 "PartitionPack: ThisPartition = 0x%"PRIX64
873 ", PreviousPartition = 0x%"PRIX64", "
874 "FooterPartition = 0x%"PRIX64", IndexSID = %i, BodySID = %i\n",
875 this_partition,
876 partition->previous_partition, footer_partition,
877 partition->index_sid, partition->body_sid);
878
879 /* sanity check PreviousPartition if set */
880 //NOTE: this isn't actually enough, see mxf_seek_to_previous_partition()
881
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 209 times.
270 if (partition->previous_partition &&
882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 mxf->run_in + partition->previous_partition >= klv_offset) {
883 av_log(mxf->fc, AV_LOG_ERROR,
884 "PreviousPartition points to this partition or forward\n");
885 return AVERROR_INVALIDDATA;
886 }
887
888
3/4
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 232 times.
✗ Branch 3 not taken.
270 if (op[12] == 1 && op[13] == 1) mxf->op = OP1a;
889
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 1 && op[13] == 2) mxf->op = OP1b;
890
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 1 && op[13] == 3) mxf->op = OP1c;
891
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 2 && op[13] == 1) mxf->op = OP2a;
892
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 2 && op[13] == 2) mxf->op = OP2b;
893
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 2 && op[13] == 3) mxf->op = OP2c;
894
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 3 && op[13] == 1) mxf->op = OP3a;
895
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 3 && op[13] == 2) mxf->op = OP3b;
896
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
38 else if (op[12] == 3 && op[13] == 3) mxf->op = OP3c;
897
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
38 else if (op[12] == 64&& op[13] == 1) mxf->op = OPSONYOpt;
898
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 else if (op[12] == 0x10) {
899 /* SMPTE 390m: "There shall be exactly one essence container"
900 * The following block deals with files that violate this, namely:
901 * 2011_DCPTEST_24FPS.V.mxf - two ECs, OP1a
902 * abcdefghiv016f56415e.mxf - zero ECs, OPAtom, output by Avid AirSpeed */
903
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 33 times.
36 if (nb_essence_containers != 1) {
904
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 MXFOP mxfop = nb_essence_containers ? OP1a : OPAtom;
905
906 /* only nag once */
907
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!mxf->op)
908
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 av_log(mxf->fc, AV_LOG_WARNING,
909 "\"OPAtom\" with %"PRIu32" ECs - assuming %s\n",
910 nb_essence_containers,
911 mxfop == OP1a ? "OP1a" : "OPAtom");
912
913 3 mxf->op = mxfop;
914 } else
915 33 mxf->op = OPAtom;
916 } else {
917 av_log(mxf->fc, AV_LOG_ERROR, "unknown operational pattern: %02xh %02xh - guessing OP1a\n", op[12], op[13]);
918 mxf->op = OP1a;
919 }
920
921
3/4
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 268 times.
270 if (partition->kag_size <= 0 || partition->kag_size > (1 << 20)) {
922 2 av_log(mxf->fc, AV_LOG_WARNING, "invalid KAGSize %"PRId32" - guessing ",
923 partition->kag_size);
924
925
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (mxf->op == OPSONYOpt)
926 2 partition->kag_size = 512;
927 else
928 partition->kag_size = 1;
929
930 2 av_log(mxf->fc, AV_LOG_WARNING, "%"PRId32"\n", partition->kag_size);
931 }
932
933 270 return 0;
934 }
935
936 2951 static uint64_t partition_score(MXFPartition *p)
937 {
938 uint64_t score;
939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2951 times.
2951 if (!p)
940 return 0;
941
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 2822 times.
2951 if (p->type == Footer)
942 129 score = 5;
943
2/2
✓ Branch 0 taken 2597 times.
✓ Branch 1 taken 225 times.
2822 else if (p->complete)
944 2597 score = 4;
945
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 75 times.
225 else if (p->closed)
946 150 score = 3;
947 else
948 75 score = 1;
949 2951 return (score << 60) | ((uint64_t)p->pack_ofs >> 4);
950 }
951
952 2953 static int mxf_add_metadata_set(MXFContext *mxf, MXFMetadataSet **metadata_set, enum MXFMetadataSetType type)
953 {
954 2953 MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[type];
955 int ret;
956
957 // Index Table is special because it might be added manually without
958 // partition and we iterate through all instances of them. Also some files
959 // use the same Instance UID for different index tables...
960
2/2
✓ Branch 0 taken 2841 times.
✓ Branch 1 taken 112 times.
2953 if (type != IndexTableSegment) {
961
2/2
✓ Branch 0 taken 7752 times.
✓ Branch 1 taken 2841 times.
10593 for (int i = 0; i < mg->metadata_sets_count; i++) {
962
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 7677 times.
7752 if (!memcmp((*metadata_set)->uid, mg->metadata_sets[i]->uid, 16)) {
963 75 uint64_t old_s = mg->metadata_sets[i]->partition_score;
964 75 uint64_t new_s = (*metadata_set)->partition_score;
965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (old_s > new_s) {
966 mxf_free_metadataset(metadata_set, type);
967 return 0;
968 }
969 }
970 }
971 }
972
973 2953 ret = av_dynarray_add_nofree(&mg->metadata_sets, &mg->metadata_sets_count, *metadata_set);
974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2953 times.
2953 if (ret < 0) {
975 mxf_free_metadataset(metadata_set, type);
976 return ret;
977 }
978 2953 return 0;
979 }
980
981 static int mxf_read_cryptographic_context(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
982 {
983 MXFCryptoContext *cryptocontext = arg;
984 if (size != 16)
985 return AVERROR_INVALIDDATA;
986 if (IS_KLV_KEY(uid, mxf_crypto_source_container_ul))
987 avio_read(pb, cryptocontext->source_container_ul, 16);
988 return 0;
989 }
990
991 1248 static int mxf_read_strong_ref_array(AVIOContext *pb, UID **refs, int *count)
992 {
993 int64_t ret;
994 1248 unsigned c = avio_rb32(pb);
995
996 //avio_read() used int
997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1248 times.
1248 if (c > INT_MAX / sizeof(UID))
998 return AVERROR_PATCHWELCOME;
999 1248 *count = c;
1000
1001 1248 av_free(*refs);
1002 1248 *refs = av_malloc_array(*count, sizeof(UID));
1003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1248 times.
1248 if (!*refs) {
1004 *count = 0;
1005 return AVERROR(ENOMEM);
1006 }
1007 1248 avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
1008 1248 ret = avio_read(pb, (uint8_t *)*refs, *count * sizeof(UID));
1009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1248 times.
1248 if (ret != *count * sizeof(UID)) {
1010 *count = ret < 0 ? 0 : ret / sizeof(UID);
1011 return ret < 0 ? ret : AVERROR_INVALIDDATA;
1012 }
1013
1014 1248 return 0;
1015 }
1016
1017 static inline int mxf_read_us_ascii_string(AVIOContext *pb, int size, char** str)
1018 {
1019 int ret;
1020 size_t buf_size;
1021
1022 if (size < 0 || size > INT_MAX - 1)
1023 return AVERROR(EINVAL);
1024
1025 buf_size = size + 1;
1026 av_free(*str);
1027 *str = av_malloc(buf_size);
1028 if (!*str)
1029 return AVERROR(ENOMEM);
1030
1031 ret = avio_get_str(pb, size, *str, buf_size);
1032
1033 if (ret < 0) {
1034 av_freep(str);
1035 return ret;
1036 }
1037
1038 return ret;
1039 }
1040
1041 635 static inline int mxf_read_utf16_string(AVIOContext *pb, int size, char** str, int be)
1042 {
1043 int ret;
1044 size_t buf_size;
1045
1046
2/4
✓ Branch 0 taken 635 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 635 times.
635 if (size < 0 || size > INT_MAX/2)
1047 return AVERROR(EINVAL);
1048
1049 635 buf_size = size + size / 2 + 1;
1050 635 av_free(*str);
1051 635 *str = av_malloc(buf_size);
1052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 635 times.
635 if (!*str)
1053 return AVERROR(ENOMEM);
1054
1055
2/2
✓ Branch 0 taken 596 times.
✓ Branch 1 taken 39 times.
635 if (be)
1056 596 ret = avio_get_str16be(pb, size, *str, buf_size);
1057 else
1058 39 ret = avio_get_str16le(pb, size, *str, buf_size);
1059
1060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 635 times.
635 if (ret < 0) {
1061 av_freep(str);
1062 return ret;
1063 }
1064
1065 635 return ret;
1066 }
1067
1068 #define READ_STR16(type, big_endian) \
1069 static int mxf_read_utf16 ## type ##_string(AVIOContext *pb, int size, char** str) \
1070 { \
1071 return mxf_read_utf16_string(pb, size, str, big_endian); \
1072 }
1073 596 READ_STR16(be, 1)
1074 39 READ_STR16(le, 0)
1075 #undef READ_STR16
1076
1077 327 static int mxf_read_content_storage(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1078 {
1079 327 MXFContext *mxf = arg;
1080
3/3
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 109 times.
✓ Branch 2 taken 109 times.
327 switch (tag) {
1081 109 case 0x1901:
1082
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 108 times.
109 if (mxf->packages_refs)
1083 1 av_log(mxf->fc, AV_LOG_VERBOSE, "Multiple packages_refs\n");
1084 109 return mxf_read_strong_ref_array(pb, &mxf->packages_refs, &mxf->packages_count);
1085 109 case 0x1902:
1086 109 return mxf_read_strong_ref_array(pb, &mxf->essence_container_data_refs, &mxf->essence_container_data_count);
1087 }
1088 109 return 0;
1089 }
1090
1091 2410 static int mxf_read_source_clip(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1092 {
1093 2410 MXFStructuralComponent *source_clip = arg;
1094
5/5
✓ Branch 0 taken 482 times.
✓ Branch 1 taken 482 times.
✓ Branch 2 taken 482 times.
✓ Branch 3 taken 482 times.
✓ Branch 4 taken 482 times.
2410 switch(tag) {
1095 482 case 0x0202:
1096 482 source_clip->duration = avio_rb64(pb);
1097 482 break;
1098 482 case 0x1201:
1099 482 source_clip->start_position = avio_rb64(pb);
1100 482 break;
1101 482 case 0x1101:
1102 /* UMID, only get last 16 bytes */
1103 482 avio_read(pb, source_clip->source_package_ul, 16);
1104 482 avio_read(pb, source_clip->source_package_uid, 16);
1105 482 break;
1106 482 case 0x1102:
1107 482 source_clip->source_track_id = avio_rb32(pb);
1108 482 break;
1109 }
1110 2410 return 0;
1111 }
1112
1113 1045 static int mxf_read_timecode_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1114 {
1115 1045 MXFTimecodeComponent *mxf_timecode = arg;
1116
4/4
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 209 times.
✓ Branch 2 taken 209 times.
✓ Branch 3 taken 418 times.
1045 switch(tag) {
1117 209 case 0x1501:
1118 209 mxf_timecode->start_frame = avio_rb64(pb);
1119 209 break;
1120 209 case 0x1502:
1121 209 mxf_timecode->rate = (AVRational){avio_rb16(pb), 1};
1122 209 break;
1123 209 case 0x1503:
1124 209 mxf_timecode->drop_frame = avio_r8(pb);
1125 209 break;
1126 }
1127 1045 return 0;
1128 }
1129
1130 6 static int mxf_read_pulldown_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1131 {
1132 6 MXFPulldownComponent *mxf_pulldown = arg;
1133
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 switch(tag) {
1134 1 case 0x0d01:
1135 1 avio_read(pb, mxf_pulldown->input_segment_ref, 16);
1136 1 break;
1137 }
1138 6 return 0;
1139 }
1140
1141 3504 static int mxf_read_track(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1142 {
1143 3504 MXFTrack *track = arg;
1144
6/6
✓ Branch 0 taken 692 times.
✓ Branch 1 taken 692 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 690 times.
✓ Branch 4 taken 692 times.
✓ Branch 5 taken 690 times.
3504 switch(tag) {
1145 692 case 0x4801:
1146 692 track->track_id = avio_rb32(pb);
1147 692 break;
1148 692 case 0x4804:
1149 692 avio_read(pb, track->track_number, 4);
1150 692 break;
1151 48 case 0x4802:
1152 48 mxf_read_utf16be_string(pb, size, &track->name);
1153 48 break;
1154 690 case 0x4b01:
1155 690 track->edit_rate.num = avio_rb32(pb);
1156 690 track->edit_rate.den = avio_rb32(pb);
1157 690 break;
1158 692 case 0x4803:
1159 692 avio_read(pb, track->sequence_ref, 16);
1160 692 break;
1161 }
1162 3504 return 0;
1163 }
1164
1165 2074 static int mxf_read_sequence(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1166 {
1167 2074 MXFSequence *sequence = arg;
1168
3/5
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 692 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 692 times.
✗ Branch 4 not taken.
2074 switch(tag) {
1169 690 case 0x0202:
1170 690 sequence->duration = avio_rb64(pb);
1171 690 break;
1172 692 case 0x0201:
1173 692 avio_read(pb, sequence->data_definition_ul, 16);
1174 692 break;
1175 case 0x4b02:
1176 sequence->origin = avio_r8(pb);
1177 break;
1178 692 case 0x1001:
1179 692 return mxf_read_strong_ref_array(pb, &sequence->structural_components_refs,
1180 &sequence->structural_components_count);
1181 }
1182 1382 return 0;
1183 }
1184
1185 8 static int mxf_read_essence_group(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1186 {
1187 8 MXFEssenceGroup *essence_group = arg;
1188
3/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
8 switch (tag) {
1189 2 case 0x0202:
1190 2 essence_group->duration = avio_rb64(pb);
1191 2 break;
1192 2 case 0x0501:
1193 2 return mxf_read_strong_ref_array(pb, &essence_group->structural_components_refs,
1194 &essence_group->structural_components_count);
1195 }
1196 6 return 0;
1197 }
1198
1199 1077 static int mxf_read_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1200 {
1201 1077 MXFPackage *package = arg;
1202
6/6
✓ Branch 0 taken 225 times.
✓ Branch 1 taken 225 times.
✓ Branch 2 taken 116 times.
✓ Branch 3 taken 25 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 476 times.
1077 switch(tag) {
1203 225 case 0x4403:
1204 225 return mxf_read_strong_ref_array(pb, &package->tracks_refs,
1205 &package->tracks_count);
1206 225 case 0x4401:
1207 /* UMID */
1208 225 avio_read(pb, package->package_ul, 16);
1209 225 avio_read(pb, package->package_uid, 16);
1210 225 break;
1211 116 case 0x4701:
1212 116 avio_read(pb, package->descriptor_ref, 16);
1213 116 break;
1214 25 case 0x4402:
1215 25 return mxf_read_utf16be_string(pb, size, &package->name);
1216 10 case 0x4406:
1217 10 return mxf_read_strong_ref_array(pb, &package->comment_refs,
1218 &package->comment_count);
1219 }
1220 817 return 0;
1221 }
1222
1223 331 static int mxf_read_essence_container_data(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1224 {
1225 331 MXFEssenceContainerData *essence_data = arg;
1226
4/4
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 107 times.
✓ Branch 2 taken 109 times.
✓ Branch 3 taken 6 times.
331 switch(tag) {
1227 109 case 0x2701:
1228 /* linked package umid UMID */
1229 109 avio_read(pb, essence_data->package_ul, 16);
1230 109 avio_read(pb, essence_data->package_uid, 16);
1231 109 break;
1232 107 case 0x3f06:
1233 107 essence_data->index_sid = avio_rb32(pb);
1234 107 break;
1235 109 case 0x3f07:
1236 109 essence_data->body_sid = avio_rb32(pb);
1237 109 break;
1238 }
1239 331 return 0;
1240 }
1241
1242 57 static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *segment)
1243 {
1244 int i, length;
1245 uint32_t nb_index_entries;
1246
1247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (segment->temporal_offset_entries)
1248 return AVERROR_INVALIDDATA;
1249
1250 57 nb_index_entries = avio_rb32(pb);
1251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if (nb_index_entries > INT_MAX)
1252 return AVERROR_INVALIDDATA;
1253 57 segment->nb_index_entries = nb_index_entries;
1254
1255 57 length = avio_rb32(pb);
1256
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
57 if(segment->nb_index_entries && length < 11)
1257 return AVERROR_INVALIDDATA;
1258
1259
1/2
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
57 if (!FF_ALLOC_TYPED_ARRAY(segment->temporal_offset_entries, segment->nb_index_entries) ||
1260
1/2
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
57 !FF_ALLOC_TYPED_ARRAY(segment->flag_entries , segment->nb_index_entries) ||
1261
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 !FF_ALLOC_TYPED_ARRAY(segment->stream_offset_entries , segment->nb_index_entries)) {
1262 av_freep(&segment->temporal_offset_entries);
1263 av_freep(&segment->flag_entries);
1264 return AVERROR(ENOMEM);
1265 }
1266
1267
2/2
✓ Branch 0 taken 1393 times.
✓ Branch 1 taken 57 times.
1450 for (i = 0; i < segment->nb_index_entries; i++) {
1268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1393 times.
1393 if(avio_feof(pb))
1269 return AVERROR_INVALIDDATA;
1270 1393 segment->temporal_offset_entries[i] = avio_r8(pb);
1271 1393 avio_r8(pb); /* KeyFrameOffset */
1272 1393 segment->flag_entries[i] = avio_r8(pb);
1273 1393 segment->stream_offset_entries[i] = avio_rb64(pb);
1274 1393 avio_skip(pb, length - 11);
1275 }
1276 57 return 0;
1277 }
1278
1279 923 static int mxf_read_index_table_segment(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1280 {
1281 923 MXFIndexTableSegment *segment = arg;
1282
8/8
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 110 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 57 times.
✓ Branch 4 taken 110 times.
✓ Branch 5 taken 110 times.
✓ Branch 6 taken 110 times.
✓ Branch 7 taken 206 times.
923 switch(tag) {
1283 110 case 0x3F05:
1284 110 segment->edit_unit_byte_count = avio_rb32(pb);
1285 110 av_log(NULL, AV_LOG_TRACE, "EditUnitByteCount %d\n", segment->edit_unit_byte_count);
1286 110 break;
1287 110 case 0x3F06:
1288 110 segment->index_sid = avio_rb32(pb);
1289 110 av_log(NULL, AV_LOG_TRACE, "IndexSID %d\n", segment->index_sid);
1290 110 break;
1291 110 case 0x3F07:
1292 110 segment->body_sid = avio_rb32(pb);
1293 110 av_log(NULL, AV_LOG_TRACE, "BodySID %d\n", segment->body_sid);
1294 110 break;
1295 57 case 0x3F0A:
1296 57 av_log(NULL, AV_LOG_TRACE, "IndexEntryArray found\n");
1297 57 return mxf_read_index_entry_array(pb, segment);
1298 110 case 0x3F0B:
1299 110 segment->index_edit_rate.num = avio_rb32(pb);
1300 110 segment->index_edit_rate.den = avio_rb32(pb);
1301
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
110 if (segment->index_edit_rate.num <= 0 ||
1302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 segment->index_edit_rate.den <= 0)
1303 return AVERROR_INVALIDDATA;
1304 110 av_log(NULL, AV_LOG_TRACE, "IndexEditRate %d/%d\n", segment->index_edit_rate.num,
1305 segment->index_edit_rate.den);
1306 110 break;
1307 110 case 0x3F0C:
1308 110 segment->index_start_position = avio_rb64(pb);
1309 110 av_log(NULL, AV_LOG_TRACE, "IndexStartPosition %"PRId64"\n", segment->index_start_position);
1310 110 break;
1311 110 case 0x3F0D:
1312 110 segment->index_duration = avio_rb64(pb);
1313 110 av_log(NULL, AV_LOG_TRACE, "IndexDuration %"PRId64"\n", segment->index_duration);
1314 110 break;
1315 }
1316 866 return 0;
1317 }
1318
1319 2 static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor)
1320 {
1321 2 int code, value, ofs = 0;
1322 2 char layout[16] = {0}; /* not for printing, may end up not terminated on purpose */
1323
1324 do {
1325 6 code = avio_r8(pb);
1326 6 value = avio_r8(pb);
1327 6 av_log(NULL, AV_LOG_TRACE, "pixel layout: code %#x\n", code);
1328
1329
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (ofs <= 14) {
1330 6 layout[ofs++] = code;
1331 6 layout[ofs++] = value;
1332 } else
1333 break; /* don't read byte by byte on sneaky files filled with lots of non-zeroes */
1334
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 } while (code != 0); /* SMPTE 377M E.2.46 */
1335
1336 2 ff_mxf_decode_pixel_layout(layout, &descriptor->pix_fmt);
1337 2 }
1338
1339 4664 static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1340 {
1341 4664 MXFDescriptor *descriptor = arg;
1342 int entry_count, entry_size;
1343
1344
27/27
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 323 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 223 times.
✓ Branch 5 taken 103 times.
✓ Branch 6 taken 104 times.
✓ Branch 7 taken 104 times.
✓ Branch 8 taken 104 times.
✓ Branch 9 taken 103 times.
✓ Branch 10 taken 104 times.
✓ Branch 11 taken 23 times.
✓ Branch 12 taken 45 times.
✓ Branch 13 taken 9 times.
✓ Branch 14 taken 8 times.
✓ Branch 15 taken 101 times.
✓ Branch 16 taken 101 times.
✓ Branch 17 taken 100 times.
✓ Branch 18 taken 100 times.
✓ Branch 19 taken 100 times.
✓ Branch 20 taken 100 times.
✓ Branch 21 taken 125 times.
✓ Branch 22 taken 14 times.
✓ Branch 23 taken 125 times.
✓ Branch 24 taken 125 times.
✓ Branch 25 taken 2 times.
✓ Branch 26 taken 2298 times.
4664 switch(tag) {
1345 93 case 0x3F01:
1346 93 return mxf_read_strong_ref_array(pb, &descriptor->file_descriptors_refs,
1347 &descriptor->file_descriptors_count);
1348 21 case 0x3002: /* ContainerDuration */
1349 21 descriptor->duration = avio_rb64(pb);
1350 21 break;
1351 323 case 0x3004:
1352 323 avio_read(pb, descriptor->essence_container_ul, 16);
1353 323 break;
1354 6 case 0x3005:
1355 6 avio_read(pb, descriptor->codec_ul, 16);
1356 6 break;
1357 223 case 0x3006:
1358 223 descriptor->linked_track_id = avio_rb32(pb);
1359 223 break;
1360 103 case 0x3201: /* PictureEssenceCoding */
1361 103 avio_read(pb, descriptor->essence_codec_ul, 16);
1362 103 break;
1363 104 case 0x3203:
1364 104 descriptor->width = avio_rb32(pb);
1365 104 break;
1366 104 case 0x3202:
1367 104 descriptor->height = avio_rb32(pb);
1368 104 break;
1369 104 case 0x320C:
1370 104 descriptor->frame_layout = avio_r8(pb);
1371 104 break;
1372 103 case 0x320D:
1373 103 entry_count = avio_rb32(pb);
1374 103 entry_size = avio_rb32(pb);
1375
1/2
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
103 if (entry_size == 4) {
1376
1/2
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
103 if (entry_count > 0)
1377 103 descriptor->video_line_map[0] = avio_rb32(pb);
1378 else
1379 descriptor->video_line_map[0] = 0;
1380
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 3 times.
103 if (entry_count > 1)
1381 100 descriptor->video_line_map[1] = avio_rb32(pb);
1382 else
1383 3 descriptor->video_line_map[1] = 0;
1384 } else
1385 av_log(NULL, AV_LOG_WARNING, "VideoLineMap element size %d currently not supported\n", entry_size);
1386 103 break;
1387 104 case 0x320E:
1388 104 descriptor->aspect_ratio.num = avio_rb32(pb);
1389 104 descriptor->aspect_ratio.den = avio_rb32(pb);
1390 104 break;
1391 23 case 0x3210:
1392 23 avio_read(pb, descriptor->color_trc_ul, 16);
1393 23 break;
1394 45 case 0x3212:
1395 45 descriptor->field_dominance = avio_r8(pb);
1396 45 break;
1397 9 case 0x3219:
1398 9 avio_read(pb, descriptor->color_primaries_ul, 16);
1399 9 break;
1400 8 case 0x321A:
1401 8 avio_read(pb, descriptor->color_space_ul, 16);
1402 8 break;
1403 101 case 0x3301:
1404 101 descriptor->component_depth = avio_rb32(pb);
1405 101 break;
1406 101 case 0x3302:
1407 101 descriptor->horiz_subsampling = avio_rb32(pb);
1408 101 break;
1409 100 case 0x3304:
1410 100 descriptor->black_ref_level = avio_rb32(pb);
1411 100 break;
1412 100 case 0x3305:
1413 100 descriptor->white_ref_level = avio_rb32(pb);
1414 100 break;
1415 100 case 0x3306:
1416 100 descriptor->color_range = avio_rb32(pb);
1417 100 break;
1418 100 case 0x3308:
1419 100 descriptor->vert_subsampling = avio_rb32(pb);
1420 100 break;
1421 125 case 0x3D03:
1422 125 descriptor->sample_rate.num = avio_rb32(pb);
1423 125 descriptor->sample_rate.den = avio_rb32(pb);
1424 125 break;
1425 14 case 0x3D06: /* SoundEssenceCompression */
1426 14 avio_read(pb, descriptor->essence_codec_ul, 16);
1427 14 break;
1428 125 case 0x3D07:
1429 125 descriptor->channels = avio_rb32(pb);
1430 125 break;
1431 125 case 0x3D01:
1432 125 descriptor->bits_per_sample = avio_rb32(pb);
1433 125 break;
1434 2 case 0x3401:
1435 2 mxf_read_pixel_layout(pb, descriptor);
1436 2 break;
1437 2298 default:
1438 /* Private uid used by SONY C0023S01.mxf */
1439
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2297 times.
2298 if (IS_KLV_KEY(uid, mxf_sony_mpeg4_extradata)) {
1440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (descriptor->extradata)
1441 av_log(NULL, AV_LOG_WARNING, "Duplicate sony_mpeg4_extradata\n");
1442 1 av_free(descriptor->extradata);
1443 1 descriptor->extradata_size = 0;
1444 1 descriptor->extradata = av_malloc(size);
1445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!descriptor->extradata)
1446 return AVERROR(ENOMEM);
1447 1 descriptor->extradata_size = size;
1448 1 avio_read(pb, descriptor->extradata, size);
1449 }
1450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2298 times.
2298 if (IS_KLV_KEY(uid, mxf_jp2k_rsiz)) {
1451 uint32_t rsiz = avio_rb16(pb);
1452 if (rsiz == AV_PROFILE_JPEG2000_DCINEMA_2K ||
1453 rsiz == AV_PROFILE_JPEG2000_DCINEMA_4K)
1454 descriptor->pix_fmt = AV_PIX_FMT_XYZ12;
1455 }
1456
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2278 times.
2298 if (IS_KLV_KEY(uid, mxf_mastering_display_prefix)) {
1457
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (!descriptor->mastering) {
1458 5 descriptor->mastering = av_mastering_display_metadata_alloc_size(&descriptor->mastering_size);
1459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!descriptor->mastering)
1460 return AVERROR(ENOMEM);
1461 }
1462
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (IS_KLV_KEY(uid, mxf_mastering_display_uls[0])) {
1463
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5 times.
20 for (int i = 0; i < 3; i++) {
1464 /* Order: large x, large y, other (i.e. RGB) */
1465 15 descriptor->mastering->display_primaries[i][0] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN);
1466 15 descriptor->mastering->display_primaries[i][1] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN);
1467 }
1468 /* Check we have seen mxf_mastering_display_white_point_chromaticity */
1469
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (descriptor->mastering->white_point[0].den != 0)
1470 5 descriptor->mastering->has_primaries = 1;
1471 }
1472
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (IS_KLV_KEY(uid, mxf_mastering_display_uls[1])) {
1473 5 descriptor->mastering->white_point[0] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN);
1474 5 descriptor->mastering->white_point[1] = av_make_q(avio_rb16(pb), FF_MXF_MASTERING_CHROMA_DEN);
1475 /* Check we have seen mxf_mastering_display_primaries */
1476
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (descriptor->mastering->display_primaries[0][0].den != 0)
1477 5 descriptor->mastering->has_primaries = 1;
1478 }
1479
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (IS_KLV_KEY(uid, mxf_mastering_display_uls[2])) {
1480 5 descriptor->mastering->max_luminance = av_make_q(avio_rb32(pb), FF_MXF_MASTERING_LUMA_DEN);
1481 /* Check we have seen mxf_mastering_display_minimum_luminance */
1482
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (descriptor->mastering->min_luminance.den != 0)
1483 5 descriptor->mastering->has_luminance = 1;
1484 }
1485
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (IS_KLV_KEY(uid, mxf_mastering_display_uls[3])) {
1486 5 descriptor->mastering->min_luminance = av_make_q(avio_rb32(pb), FF_MXF_MASTERING_LUMA_DEN);
1487 /* Check we have seen mxf_mastering_display_maximum_luminance */
1488
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (descriptor->mastering->max_luminance.den != 0)
1489 5 descriptor->mastering->has_luminance = 1;
1490 }
1491 }
1492
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2292 times.
2298 if (IS_KLV_KEY(uid, mxf_apple_coll_prefix)) {
1493
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!descriptor->coll) {
1494 3 descriptor->coll = av_content_light_metadata_alloc(&descriptor->coll_size);
1495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!descriptor->coll)
1496 return AVERROR(ENOMEM);
1497 }
1498
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (IS_KLV_KEY(uid, mxf_apple_coll_max_cll)) {
1499 3 descriptor->coll->MaxCLL = avio_rb16(pb);
1500 }
1501
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (IS_KLV_KEY(uid, mxf_apple_coll_max_fall)) {
1502 3 descriptor->coll->MaxFALL = avio_rb16(pb);
1503 }
1504 }
1505
1506
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2290 times.
2298 if (IS_KLV_KEY(uid, mxf_sub_descriptor))
1507 8 return mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs, &descriptor->sub_descriptors_count);
1508
1509 2290 break;
1510 }
1511 4563 return 0;
1512 }
1513
1514 static int mxf_read_mca_sub_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1515 {
1516 MXFMCASubDescriptor *mca_sub_descriptor = arg;
1517
1518 if (IS_KLV_KEY(uid, mxf_mca_label_dictionary_id))
1519 avio_read(pb, mca_sub_descriptor->mca_label_dictionary_id, 16);
1520
1521 if (IS_KLV_KEY(uid, mxf_mca_link_id))
1522 avio_read(pb, mca_sub_descriptor->mca_link_id, 16);
1523
1524 if (IS_KLV_KEY(uid, mxf_soundfield_group_link_id))
1525 avio_read(pb, mca_sub_descriptor->soundfield_group_link_id, 16);
1526
1527 if (IS_KLV_KEY(uid, mxf_group_of_soundfield_groups_link_id))
1528 return mxf_read_strong_ref_array(pb, &mca_sub_descriptor->group_of_soundfield_groups_link_id_refs, &mca_sub_descriptor->group_of_soundfield_groups_link_id_count);
1529
1530 if (IS_KLV_KEY(uid, mxf_mca_channel_id))
1531 mca_sub_descriptor->mca_channel_id = avio_rb32(pb);
1532
1533 if (IS_KLV_KEY(uid, mxf_mca_rfc5646_spoken_language))
1534 return mxf_read_us_ascii_string(pb, size, &mca_sub_descriptor->language);
1535
1536 return 0;
1537 }
1538
1539 3 static int mxf_read_ffv1_sub_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1540 {
1541 3 MXFFFV1SubDescriptor *ffv1_sub_descriptor = arg;
1542
1543
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
3 if (IS_KLV_KEY(uid, mxf_ffv1_extradata) && size <= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE ) {
1544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ffv1_sub_descriptor->extradata)
1545 av_log(NULL, AV_LOG_WARNING, "Duplicate ffv1_extradata\n");
1546 1 av_free(ffv1_sub_descriptor->extradata);
1547 1 ffv1_sub_descriptor->extradata_size = 0;
1548 1 ffv1_sub_descriptor->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
1549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ffv1_sub_descriptor->extradata)
1550 return AVERROR(ENOMEM);
1551 1 ffv1_sub_descriptor->extradata_size = size;
1552 1 avio_read(pb, ffv1_sub_descriptor->extradata, size);
1553 }
1554
1555 3 return 0;
1556 }
1557
1558 105 static int mxf_read_indirect_value(void *arg, AVIOContext *pb, int size)
1559 {
1560 105 MXFTaggedValue *tagged_value = arg;
1561 uint8_t key[17];
1562 int ret;
1563
1564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
105 if (size <= 17)
1565 return 0;
1566
1567 105 ret = ffio_read_size(pb, key, 17);
1568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
105 if (ret < 0)
1569 return ret;
1570 /* TODO: handle other types of of indirect values */
1571
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 66 times.
105 if (memcmp(key, mxf_indirect_value_utf16le, 17) == 0) {
1572 39 return mxf_read_utf16le_string(pb, size - 17, &tagged_value->value);
1573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 } else if (memcmp(key, mxf_indirect_value_utf16be, 17) == 0) {
1574 return mxf_read_utf16be_string(pb, size - 17, &tagged_value->value);
1575 }
1576 66 return 0;
1577 }
1578
1579 232 static int mxf_read_tagged_value(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
1580 {
1581 232 MXFTaggedValue *tagged_value = arg;
1582
3/3
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 105 times.
✓ Branch 2 taken 22 times.
232 switch (tag){
1583 105 case 0x5001:
1584 105 return mxf_read_utf16be_string(pb, size, &tagged_value->name);
1585 105 case 0x5003:
1586 105 return mxf_read_indirect_value(tagged_value, pb, size);
1587 }
1588 22 return 0;
1589 }
1590
1591 /*
1592 * Match an uid independently of the version byte and up to len common bytes
1593 * Returns: boolean
1594 */
1595 44062 static int mxf_match_uid(const UID key, const uint8_t uid_prefix[], int len)
1596 {
1597 int i;
1598
2/2
✓ Branch 0 taken 237788 times.
✓ Branch 1 taken 851 times.
238639 for (i = 0; i < len; i++) {
1599
4/4
✓ Branch 0 taken 231855 times.
✓ Branch 1 taken 5933 times.
✓ Branch 2 taken 43211 times.
✓ Branch 3 taken 188644 times.
237788 if (i != 7 && key[i] != uid_prefix[i])
1600 43211 return 0;
1601 }
1602 851 return 1;
1603 }
1604
1605 1548 static const MXFCodecUL *mxf_get_codec_ul(const MXFCodecUL *uls, UID *uid)
1606 {
1607
2/2
✓ Branch 0 taken 17248 times.
✓ Branch 1 taken 699 times.
17947 while (uls->uid[0]) {
1608
2/2
✓ Branch 1 taken 849 times.
✓ Branch 2 taken 16399 times.
17248 if(mxf_match_uid(uls->uid, *uid, uls->matching_len))
1609 849 break;
1610 16399 uls++;
1611 }
1612 1548 return uls;
1613 }
1614
1615 5187 static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMetadataSetType type)
1616 {
1617 5187 MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[type];
1618
1619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5187 times.
5187 if (!strong_ref)
1620 return NULL;
1621
2/2
✓ Branch 0 taken 13157 times.
✓ Branch 1 taken 1675 times.
14832 for (int i = mg->metadata_sets_count - 1; i >= 0; i--)
1622
2/2
✓ Branch 0 taken 3512 times.
✓ Branch 1 taken 9645 times.
13157 if (!memcmp(*strong_ref, mg->metadata_sets[i]->uid, 16))
1623 3512 return mg->metadata_sets[i];
1624
1625 1675 return NULL;
1626 }
1627
1628 static const MXFCodecUL mxf_picture_essence_container_uls[] = {
1629 // video essence container uls
1630 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000, NULL, 14, J2KWrap },
1631 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x10,0x60,0x01 }, 14, AV_CODEC_ID_H264, NULL, 15 }, /* H.264 */
1632 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, 14, AV_CODEC_ID_DNXHD, NULL, 14 }, /* VC-3 */
1633 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x1e,0x01,0x00 }, 14, AV_CODEC_ID_DNXUC, NULL, 14 }, /* DNxUncompressed / SMPTE RDD 50 */
1634 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x12,0x01,0x00 }, 14, AV_CODEC_ID_VC1, NULL, 14 }, /* VC-1 */
1635 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x14,0x01,0x00 }, 14, AV_CODEC_ID_TIFF, NULL, 14 }, /* TIFF */
1636 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x15,0x01,0x00 }, 14, AV_CODEC_ID_DIRAC, NULL, 14 }, /* VC-2 */
1637 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x1b,0x01,0x00 }, 14, AV_CODEC_ID_CFHD, NULL, 14 }, /* VC-5 */
1638 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x1c,0x01,0x00 }, 14, AV_CODEC_ID_PRORES, NULL, 14 }, /* ProRes */
1639 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO, NULL, 15 }, /* MPEG-ES */
1640 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x04,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO, NULL, 15, D10D11Wrap }, /* SMPTE D-10 mapping */
1641 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x23,0x01,0x00 }, 14, AV_CODEC_ID_FFV1, NULL, 14 },
1642 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14, AV_CODEC_ID_DVVIDEO, NULL, 15 }, /* DV 625 25mbps */
1643 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14, AV_CODEC_ID_RAWVIDEO, NULL, 15, RawVWrap }, /* uncompressed picture */
1644 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x01,0x01 }, 15, AV_CODEC_ID_HQ_HQA },
1645 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x02,0x01 }, 15, AV_CODEC_ID_HQX },
1646 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x15,0x00,0x04,0x02,0x10,0x00,0x01 }, 16, AV_CODEC_ID_HEVC, NULL, 15 }, /* Canon XF-HEVC */
1647 { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4f }, 14, AV_CODEC_ID_RAWVIDEO }, /* Legacy ?? Uncompressed Picture */
1648 { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
1649 };
1650
1651 /* EC ULs for intra-only formats */
1652 static const MXFCodecUL mxf_intra_only_essence_container_uls[] = {
1653 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 mappings */
1654 { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
1655 };
1656
1657 /* intra-only PictureEssenceCoding ULs, where no corresponding EC UL exists */
1658 static const MXFCodecUL mxf_intra_only_picture_essence_coding_uls[] = {
1659 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra Profiles */
1660 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG 2000 code stream */
1661 { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
1662 };
1663
1664 /* actual coded width for AVC-Intra to allow selecting correct SPS/PPS */
1665 static const MXFCodecUL mxf_intra_only_picture_coded_width[] = {
1666 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 16, 1440 },
1667 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 16, 1440 },
1668 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 16, 1440 },
1669 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, 16, 1440 },
1670 { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, 0 },
1671 };
1672
1673 static const MXFCodecUL mxf_sound_essence_container_uls[] = {
1674 // sound essence container uls
1675 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, AV_CODEC_ID_PCM_S16LE, NULL, 14, RawAWrap }, /* BWF */
1676 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14, AV_CODEC_ID_MP2, NULL, 15 }, /* MPEG-ES */
1677 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE, NULL, 13 }, /* D-10 Mapping 50Mbps PAL Extended Template */
1678 { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4F }, 14, AV_CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */
1679 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG-2 AAC ADTS (legacy) */
1680 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x16,0x00,0x00 }, 14, AV_CODEC_ID_AAC, NULL, 14 }, /* AAC ADIF (SMPTE 381-4) */
1681 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x17,0x00,0x00 }, 14, AV_CODEC_ID_AAC, NULL, 14 }, /* AAC ADTS (SMPTE 381-4) */
1682 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x0d,0x01,0x03,0x01,0x02,0x18,0x00,0x00 }, 14, AV_CODEC_ID_AAC, NULL, 14 }, /* AAC LATM/LOAS (SMPTE 381-4) */
1683 { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
1684 };
1685
1686 static const MXFCodecUL mxf_data_essence_container_uls[] = {
1687 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0d,0x00,0x00 }, 16, AV_CODEC_ID_NONE, "vbi_smpte_436M", 11 },
1688 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 }, 16, AV_CODEC_ID_SMPTE_436M_ANC, "vbi_vanc_smpte_436M", 11 },
1689 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x13,0x01,0x01 }, 16, AV_CODEC_ID_TTML },
1690 { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE },
1691 };
1692
1693 typedef struct MXFChannelOrderingUL {
1694 UID uid;
1695 enum AVChannel channel;
1696 enum AVAudioServiceType service_type;
1697 } MXFChannelOrderingUL;
1698
1699 static const MXFChannelOrderingUL mxf_channel_ordering[] = {
1700 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00 }, AV_CHAN_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left
1701 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x02,0x00,0x00,0x00,0x00 }, AV_CHAN_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right
1702 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x03,0x00,0x00,0x00,0x00 }, AV_CHAN_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center
1703 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x04,0x00,0x00,0x00,0x00 }, AV_CHAN_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Low Frequency Effects
1704 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x05,0x00,0x00,0x00,0x00 }, AV_CHAN_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround
1705 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x06,0x00,0x00,0x00,0x00 }, AV_CHAN_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround
1706 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x07,0x00,0x00,0x00,0x00 }, AV_CHAN_SIDE_SURROUND_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround
1707 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x08,0x00,0x00,0x00,0x00 }, AV_CHAN_SIDE_SURROUND_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround
1708 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x09,0x00,0x00,0x00,0x00 }, AV_CHAN_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround
1709 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0a,0x00,0x00,0x00,0x00 }, AV_CHAN_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround
1710 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0b,0x00,0x00,0x00,0x00 }, AV_CHAN_FRONT_LEFT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Center
1711 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0c,0x00,0x00,0x00,0x00 }, AV_CHAN_FRONT_RIGHT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Center
1712 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0d,0x00,0x00,0x00,0x00 }, AV_CHAN_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Surround
1713 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0e,0x00,0x00,0x00,0x00 }, AV_CHAN_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, // Hearing impaired audio channel
1714 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0f,0x00,0x00,0x00,0x00 }, AV_CHAN_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED }, // Visually impaired narrative audio channel
1715 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x20,0x03,0x00,0x00,0x00 }, AV_CHAN_STEREO_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Total
1716 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x20,0x04,0x00,0x00,0x00 }, AV_CHAN_STEREO_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Total
1717 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x01,0x00,0x00 }, AV_CHAN_TOP_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Height
1718 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x02,0x00,0x00 }, AV_CHAN_TOP_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Height
1719 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x03,0x00,0x00 }, AV_CHAN_TOP_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Height
1720 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x04,0x00,0x00 }, AV_CHAN_TOP_SURROUND_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround Height
1721 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x05,0x00,0x00 }, AV_CHAN_TOP_SURROUND_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround Height
1722 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x06,0x00,0x00 }, AV_CHAN_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround Height
1723 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x07,0x00,0x00 }, AV_CHAN_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround Height
1724 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x08,0x00,0x00 }, AV_CHAN_TOP_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround Height
1725 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x09,0x00,0x00 }, AV_CHAN_TOP_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround Height
1726 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0a,0x00,0x00 }, AV_CHAN_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Top Surround
1727 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0b,0x00,0x00 }, AV_CHAN_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Top Surround
1728 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0c,0x00,0x00 }, AV_CHAN_TOP_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Top Surround
1729 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0d,0x00,0x00 }, AV_CHAN_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Front Subwoofer
1730 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0e,0x00,0x00 }, AV_CHAN_LOW_FREQUENCY_2, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Front Subwoofer
1731 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0f,0x00,0x00 }, AV_CHAN_TOP_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear Height
1732 { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x10,0x00,0x00 }, AV_CHAN_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear
1733 { { 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
1734 { { 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
1735 { { 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
1736 { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB },
1737 };
1738
1739 210 static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul)
1740 {
1741 int val;
1742 const MXFCodecUL *codec_ul;
1743
1744 210 codec_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul);
1745
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 137 times.
210 if (!codec_ul->uid[0])
1746 73 codec_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
1747
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 205 times.
210 if (!codec_ul->uid[0])
1748 5 codec_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul);
1749
3/4
✓ Branch 0 taken 206 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 206 times.
210 if (!codec_ul->uid[0] || !codec_ul->wrapping_indicator_pos)
1750 4 return UnknownWrapped;
1751
1752 206 val = (*essence_container_ul)[codec_ul->wrapping_indicator_pos];
1753
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 54 times.
206 switch (codec_ul->wrapping_indicator_type) {
1754 case RawVWrap:
1755 val = val % 4;
1756 break;
1757 68 case RawAWrap:
1758
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
68 if (val == 0x03 || val == 0x04)
1759 68 val -= 0x02;
1760 68 break;
1761 82 case D10D11Wrap:
1762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if (val == 0x02)
1763 val = 0x01;
1764 82 break;
1765 2 case J2KWrap:
1766
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (val != 0x02)
1767 2 val = 0x01;
1768 2 break;
1769 }
1770
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 1 times.
206 if (val == 0x01)
1771 205 return FrameWrapped;
1772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (val == 0x02)
1773 return ClipWrapped;
1774 1 return UnknownWrapped;
1775 }
1776
1777 108 static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments)
1778 {
1779 108 int i, j, nb_segments = 0;
1780 MXFIndexTableSegment **unsorted_segments;
1781 108 int last_body_sid = -1, last_index_sid = -1, last_index_start = -1;
1782 108 MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[IndexTableSegment];
1783
1784 /* count number of segments, allocate arrays and copy unsorted segments */
1785 108 nb_segments = mg->metadata_sets_count;
1786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!nb_segments)
1787 return AVERROR_INVALIDDATA;
1788
1789
1/2
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
108 if (!(unsorted_segments = av_calloc(nb_segments, sizeof(*unsorted_segments))) ||
1790
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 !(*sorted_segments = av_calloc(nb_segments, sizeof(**sorted_segments)))) {
1791 av_freep(sorted_segments);
1792 av_free(unsorted_segments);
1793 return AVERROR(ENOMEM);
1794 }
1795
1796
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 108 times.
220 for (i = nb_segments = 0; i < mg->metadata_sets_count; i++) {
1797 112 MXFIndexTableSegment *s = (MXFIndexTableSegment*)mg->metadata_sets[i];
1798
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
112 if (s->edit_unit_byte_count || s->nb_index_entries)
1799 112 unsorted_segments[nb_segments++] = s;
1800 else
1801 av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i segment at %"PRId64" missing EditUnitByteCount and IndexEntryArray\n",
1802 s->index_sid, s->index_start_position);
1803 }
1804
1805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!nb_segments) {
1806 av_freep(sorted_segments);
1807 av_free(unsorted_segments);
1808 return AVERROR_INVALIDDATA;
1809 }
1810
1811 108 *nb_sorted_segments = 0;
1812
1813 /* sort segments by {BodySID, IndexSID, IndexStartPosition}, remove duplicates while we're at it */
1814
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 105 times.
217 for (i = 0; i < nb_segments; i++) {
1815 112 int best = -1, best_body_sid = -1, best_index_sid = -1, best_index_start = -1;
1816 112 uint64_t best_index_duration = 0;
1817
1818
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 112 times.
232 for (j = 0; j < nb_segments; j++) {
1819 120 MXFIndexTableSegment *s = unsorted_segments[j];
1820
1821 /* Require larger BosySID, IndexSID or IndexStartPosition then the previous entry. This removes duplicates.
1822 * We want the smallest values for the keys than what we currently have, unless this is the first such entry this time around.
1823 * If we come across an entry with the same IndexStartPosition but larger IndexDuration, then we'll prefer it over the one we currently have.
1824 */
1825
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 112 times.
120 if ((i == 0 ||
1826
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 s->body_sid > last_body_sid ||
1827
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 s->body_sid == last_body_sid && s->index_sid > last_index_sid ||
1828
6/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 109 times.
120 s->body_sid == last_body_sid && s->index_sid == last_index_sid && s->index_start_position > last_index_start) &&
1829 4 (best == -1 ||
1830
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 s->body_sid < best_body_sid ||
1831
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 s->body_sid == best_body_sid && s->index_sid < best_index_sid ||
1832
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 s->body_sid == best_body_sid && s->index_sid == best_index_sid && s->index_start_position < best_index_start ||
1833
5/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
4 s->body_sid == best_body_sid && s->index_sid == best_index_sid && s->index_start_position == best_index_start && s->index_duration > best_index_duration)) {
1834 109 best = j;
1835 109 best_body_sid = s->body_sid;
1836 109 best_index_sid = s->index_sid;
1837 109 best_index_start = s->index_start_position;
1838 109 best_index_duration = s->index_duration;
1839 }
1840 }
1841
1842 /* no suitable entry found -> we're done */
1843
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 109 times.
112 if (best == -1)
1844 3 break;
1845
1846 109 (*sorted_segments)[(*nb_sorted_segments)++] = unsorted_segments[best];
1847 109 last_body_sid = best_body_sid;
1848 109 last_index_sid = best_index_sid;
1849 109 last_index_start = best_index_start;
1850 }
1851
1852 108 av_free(unsorted_segments);
1853
1854 108 return 0;
1855 }
1856
1857 /**
1858 * Computes the absolute file offset of the given essence container offset
1859 */
1860 5798 static int mxf_absolute_bodysid_offset(MXFContext *mxf, int body_sid, int64_t offset, int64_t *offset_out, MXFPartition **partition_out)
1861 {
1862 5798 MXFPartition *last_p = NULL;
1863 int a, b, m, m0;
1864
1865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5798 times.
5798 if (offset < 0)
1866 return AVERROR(EINVAL);
1867
1868 5798 a = -1;
1869 5798 b = mxf->partitions_count;
1870
1871
2/2
✓ Branch 0 taken 11559 times.
✓ Branch 1 taken 5798 times.
17357 while (b - a > 1) {
1872 11559 m0 = m = (a + b) >> 1;
1873
1874
4/4
✓ Branch 0 taken 11587 times.
✓ Branch 1 taken 5761 times.
✓ Branch 2 taken 5789 times.
✓ Branch 3 taken 5798 times.
17348 while (m < b && mxf->partitions[m].body_sid != body_sid)
1875 5789 m++;
1876
1877
3/4
✓ Branch 0 taken 5798 times.
✓ Branch 1 taken 5761 times.
✓ Branch 2 taken 5798 times.
✗ Branch 3 not taken.
11559 if (m < b && mxf->partitions[m].body_offset <= offset)
1878 5798 a = m;
1879 else
1880 5761 b = m0;
1881 }
1882
1883
1/2
✓ Branch 0 taken 5798 times.
✗ Branch 1 not taken.
5798 if (a >= 0)
1884 5798 last_p = &mxf->partitions[a];
1885
1886
5/6
✓ Branch 0 taken 5798 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5761 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 5760 times.
✓ Branch 5 taken 1 times.
5798 if (last_p && (!last_p->essence_length || last_p->essence_length > (offset - last_p->body_offset))) {
1887 5797 *offset_out = last_p->essence_offset + (offset - last_p->body_offset);
1888
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 5590 times.
5797 if (partition_out)
1889 207 *partition_out = last_p;
1890 5797 return 0;
1891 }
1892
1893 1 av_log(mxf->fc, AV_LOG_ERROR,
1894 "failed to find absolute offset of %"PRIX64" in BodySID %i - partial file?\n",
1895 offset, body_sid);
1896
1897 1 return AVERROR_INVALIDDATA;
1898 }
1899
1900 /**
1901 * Returns the end position of the essence container with given BodySID, or zero if unknown
1902 */
1903 299 static int64_t mxf_essence_container_end(MXFContext *mxf, int body_sid)
1904 {
1905
1/2
✓ Branch 0 taken 556 times.
✗ Branch 1 not taken.
556 for (int x = mxf->partitions_count - 1; x >= 0; x--) {
1906 556 MXFPartition *p = &mxf->partitions[x];
1907
1908
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 299 times.
556 if (p->body_sid != body_sid)
1909 257 continue;
1910
1911
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 251 times.
299 if (!p->essence_length)
1912 48 return 0;
1913
1914 251 return p->essence_offset + p->essence_length;
1915 }
1916
1917 return 0;
1918 }
1919
1920 /* EditUnit -> absolute offset */
1921 6096 static int mxf_edit_unit_absolute_offset(MXFContext *mxf, MXFIndexTable *index_table, int64_t edit_unit, AVRational edit_rate, int64_t *edit_unit_out, int64_t *offset_out, MXFPartition **partition_out, int nag)
1922 {
1923 6096 int i = 0, dir = 0;
1924 int64_t index_duration, index_end;
1925 MXFIndexTableSegment *first_segment, *last_segment;
1926
1927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6096 times.
6096 if (!index_table->nb_segments) {
1928 av_log(mxf->fc, AV_LOG_ERROR, "no index table segments\n");
1929 return AVERROR_INVALIDDATA;
1930 }
1931
1932 6096 edit_unit = av_rescale_q(edit_unit, index_table->segments[0]->index_edit_rate, edit_rate);
1933
1934 6096 first_segment = index_table->segments[0];
1935 6096 last_segment = index_table->segments[index_table->nb_segments - 1];
1936
1937 // clamp to actual range of index
1938 6096 index_end = av_sat_add64(last_segment->index_start_position, last_segment->index_duration);
1939 6096 edit_unit = FFMAX(FFMIN(edit_unit, index_end), first_segment->index_start_position);
1940
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 6048 times.
6096 if (edit_unit < 0)
1941 48 return AVERROR_PATCHWELCOME;
1942
1943 // guess which table segment this edit unit is in
1944 // saturation is fine since it's just a guess
1945 // if the guess is wrong we revert to a linear search
1946 6048 index_duration = av_sat_sub64(index_end, first_segment->index_start_position);
1947
1948 // compute the guess, taking care not to cause overflow or division by zero
1949
2/4
✓ Branch 0 taken 6048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6048 times.
✗ Branch 3 not taken.
6048 if (index_duration > 0 && edit_unit <= INT64_MAX / index_table->nb_segments) {
1950 // a simple linear guesstimate
1951 // this is accurate to within +-1 when partitions are generated at a constant rate like mxfenc does
1952 6048 int64_t i64 = index_table->nb_segments * edit_unit / index_duration;
1953 // clamp and downcast to 32-bit
1954 6048 i = FFMAX(0, FFMIN(index_table->nb_segments - 1, i64));
1955 }
1956
1957
3/4
✓ Branch 0 taken 6298 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6048 times.
✓ Branch 3 taken 250 times.
6298 for (; i >= 0 && i < index_table->nb_segments; i += dir) {
1958 6048 MXFIndexTableSegment *s = index_table->segments[i];
1959
1960
3/4
✓ Branch 0 taken 6048 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5798 times.
✓ Branch 3 taken 250 times.
6048 if (s->index_start_position <= edit_unit && edit_unit < s->index_start_position + s->index_duration) {
1961 5798 int64_t index = edit_unit - s->index_start_position;
1962 5798 int64_t offset_temp = s->offset;
1963
1964
2/2
✓ Branch 0 taken 2970 times.
✓ Branch 1 taken 2828 times.
5798 if (s->edit_unit_byte_count) {
1965
1/2
✓ Branch 0 taken 2970 times.
✗ Branch 1 not taken.
2970 if (index > INT64_MAX / s->edit_unit_byte_count ||
1966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2970 times.
2970 s->edit_unit_byte_count * index > INT64_MAX - offset_temp)
1967 return AVERROR_INVALIDDATA;
1968
1969 2970 offset_temp += s->edit_unit_byte_count * index;
1970 } else {
1971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2828 times.
2828 if (s->nb_index_entries == 2 * s->index_duration + 1)
1972 index *= 2; /* Avid index */
1973
1974
2/4
✓ Branch 0 taken 2828 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2828 times.
2828 if (index < 0 || index >= s->nb_index_entries) {
1975 av_log(mxf->fc, AV_LOG_ERROR, "IndexSID %i segment at %"PRId64" IndexEntryArray too small\n",
1976 index_table->index_sid, s->index_start_position);
1977 return AVERROR_INVALIDDATA;
1978 }
1979
1980 2828 offset_temp = s->stream_offset_entries[index];
1981 }
1982
1983
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 5591 times.
5798 if (edit_unit_out)
1984 207 *edit_unit_out = av_rescale_q(edit_unit, edit_rate, s->index_edit_rate);
1985
1986 5798 return mxf_absolute_bodysid_offset(mxf, index_table->body_sid, offset_temp, offset_out, partition_out);
1987
1/2
✓ Branch 0 taken 250 times.
✗ Branch 1 not taken.
250 } else if (dir == 0) {
1988 // scan backwards if the segment is earlier than the current IndexStartPosition
1989 // else scan forwards
1990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250 times.
250 if (edit_unit < s->index_start_position) {
1991 dir = -1;
1992 } else {
1993 250 dir = 1;
1994 }
1995 }
1996 }
1997
1998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 250 times.
250 if (nag)
1999 av_log(mxf->fc, AV_LOG_ERROR, "failed to map EditUnit %"PRId64" in IndexSID %i to an offset\n", edit_unit, index_table->index_sid);
2000
2001 250 return AVERROR_INVALIDDATA;
2002 }
2003
2004 108 static int mxf_compute_ptses_fake_index(MXFContext *mxf, MXFIndexTable *index_table)
2005 {
2006 int i, j, x;
2007 108 int8_t max_temporal_offset = -128;
2008 uint8_t *flags;
2009
2010 /* first compute how many entries we have */
2011
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 50 times.
159 for (i = 0; i < index_table->nb_segments; i++) {
2012 109 MXFIndexTableSegment *s = index_table->segments[i];
2013
2014
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 51 times.
109 if (!s->nb_index_entries) {
2015 58 index_table->nb_ptses = 0;
2016 58 return 0; /* no TemporalOffsets */
2017 }
2018
2019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (s->index_duration > INT_MAX - index_table->nb_ptses) {
2020 index_table->nb_ptses = 0;
2021 av_log(mxf->fc, AV_LOG_ERROR, "ignoring IndexSID %d, duration is too large\n", s->index_sid);
2022 return 0;
2023 }
2024
2025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (s->nb_index_entries != s->index_duration &&
2026 s->nb_index_entries != s->index_duration + 1 && /* Avid index */
2027 s->nb_index_entries != s->index_duration * 2 + 1) {
2028 index_table->nb_ptses = 0;
2029 av_log(mxf->fc, AV_LOG_ERROR, "ignoring IndexSID %d, duration does not match nb_index_entries\n", s->index_sid);
2030 return 0;
2031 }
2032
2033 51 index_table->nb_ptses += s->index_duration;
2034 }
2035
2036 /* paranoid check */
2037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (index_table->nb_ptses <= 0)
2038 return 0;
2039
2040
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
50 if (!(index_table->ptses = av_malloc_array(index_table->nb_ptses, sizeof(int64_t))) ||
2041
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
50 !(index_table->fake_index = av_calloc(index_table->nb_ptses, sizeof(AVIndexEntry))) ||
2042
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
50 !(index_table->offsets = av_malloc_array(index_table->nb_ptses, sizeof(int8_t))) ||
2043
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 !(flags = av_malloc_array(index_table->nb_ptses, sizeof(uint8_t)))) {
2044 av_freep(&index_table->ptses);
2045 av_freep(&index_table->fake_index);
2046 av_freep(&index_table->offsets);
2047 return AVERROR(ENOMEM);
2048 }
2049
2050 /* we may have a few bad TemporalOffsets
2051 * make sure the corresponding PTSes don't have the bogus value 0 */
2052
2/2
✓ Branch 0 taken 1378 times.
✓ Branch 1 taken 50 times.
1428 for (x = 0; x < index_table->nb_ptses; x++)
2053 1378 index_table->ptses[x] = AV_NOPTS_VALUE;
2054
2055 /**
2056 * We have this:
2057 *
2058 * x TemporalOffset
2059 * 0: 0
2060 * 1: 1
2061 * 2: 1
2062 * 3: -2
2063 * 4: 1
2064 * 5: 1
2065 * 6: -2
2066 *
2067 * We want to transform it into this:
2068 *
2069 * x DTS PTS
2070 * 0: -1 0
2071 * 1: 0 3
2072 * 2: 1 1
2073 * 3: 2 2
2074 * 4: 3 6
2075 * 5: 4 4
2076 * 6: 5 5
2077 *
2078 * We do this by bucket sorting x by x+TemporalOffset[x] into mxf->ptses,
2079 * then settings ffstream(mxf)->first_dts = -max(TemporalOffset[x]).
2080 * The latter makes DTS <= PTS.
2081 */
2082
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 50 times.
101 for (i = x = 0; i < index_table->nb_segments; i++) {
2083 51 MXFIndexTableSegment *s = index_table->segments[i];
2084 51 int index_delta = 1;
2085 51 int n = s->nb_index_entries;
2086
2087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (s->nb_index_entries == 2 * s->index_duration + 1)
2088 index_delta = 2; /* Avid index */
2089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (s->nb_index_entries == index_delta * s->index_duration + 1)
2090 /* ignore the last entry - it's the size of the essence container in Avid */
2091 n--;
2092
2093
2/2
✓ Branch 0 taken 1378 times.
✓ Branch 1 taken 51 times.
1429 for (j = 0; j < n; j += index_delta, x++) {
2094 1378 int offset = s->temporal_offset_entries[j] / index_delta;
2095 1378 int index = x + offset;
2096
2097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1378 times.
1378 if (x >= index_table->nb_ptses) {
2098 av_log(mxf->fc, AV_LOG_ERROR,
2099 "x >= nb_ptses - IndexEntryCount %i < IndexDuration %"PRId64"?\n",
2100 s->nb_index_entries, s->index_duration);
2101 break;
2102 }
2103
2104 1378 flags[x] = !(s->flag_entries[j] & 0x30) ? AVINDEX_KEYFRAME : 0;
2105
2106
2/4
✓ Branch 0 taken 1378 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1378 times.
1378 if (index < 0 || index >= index_table->nb_ptses) {
2107 av_log(mxf->fc, AV_LOG_ERROR,
2108 "index entry %i + TemporalOffset %i = %i, which is out of bounds\n",
2109 x, offset, index);
2110 continue;
2111 }
2112
2113 1378 index_table->offsets[x] = offset;
2114 1378 index_table->ptses[index] = x;
2115 1378 max_temporal_offset = FFMAX(max_temporal_offset, offset);
2116 }
2117 }
2118
2119 /* calculate the fake index table in display order */
2120
2/2
✓ Branch 0 taken 1378 times.
✓ Branch 1 taken 50 times.
1428 for (x = 0; x < index_table->nb_ptses; x++) {
2121 1378 index_table->fake_index[x].timestamp = x;
2122
1/2
✓ Branch 0 taken 1378 times.
✗ Branch 1 not taken.
1378 if (index_table->ptses[x] != AV_NOPTS_VALUE)
2123 1378 index_table->fake_index[index_table->ptses[x]].flags = flags[x];
2124 }
2125 50 av_freep(&flags);
2126
2127 50 index_table->first_dts = -max_temporal_offset;
2128
2129 50 return 0;
2130 }
2131
2132 /**
2133 * Sorts and collects index table segments into index tables.
2134 * Also computes PTSes if possible.
2135 */
2136 108 static int mxf_compute_index_tables(MXFContext *mxf)
2137 {
2138 int ret, nb_sorted_segments;
2139 108 MXFIndexTableSegment **sorted_segments = NULL;
2140
2141
1/2
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
108 if ((ret = mxf_get_sorted_table_segments(mxf, &nb_sorted_segments, &sorted_segments)) ||
2142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 nb_sorted_segments <= 0) {
2143 av_log(mxf->fc, AV_LOG_WARNING, "broken or empty index\n");
2144 return 0;
2145 }
2146
2147 /* sanity check and count unique BodySIDs/IndexSIDs */
2148
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 108 times.
217 for (int i = 0; i < nb_sorted_segments; i++) {
2149
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
109 if (i == 0 || sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid)
2150 108 mxf->nb_index_tables++;
2151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if (sorted_segments[i-1]->body_sid != sorted_segments[i]->body_sid) {
2152 av_log(mxf->fc, AV_LOG_ERROR, "found inconsistent BodySID\n");
2153 ret = AVERROR_INVALIDDATA;
2154 goto finish_decoding_index;
2155 }
2156 }
2157
2158 108 mxf->index_tables = av_calloc(mxf->nb_index_tables,
2159 sizeof(*mxf->index_tables));
2160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!mxf->index_tables) {
2161 av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate index tables\n");
2162 ret = AVERROR(ENOMEM);
2163 goto finish_decoding_index;
2164 }
2165
2166 /* distribute sorted segments to index tables */
2167
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 108 times.
217 for (int i = 0, j = 0; i < nb_sorted_segments; i++) {
2168
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
109 if (i != 0 && sorted_segments[i-1]->index_sid != sorted_segments[i]->index_sid) {
2169 /* next IndexSID */
2170 j++;
2171 }
2172
2173 109 mxf->index_tables[j].nb_segments++;
2174 }
2175
2176
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 108 times.
216 for (int i = 0, j = 0; j < mxf->nb_index_tables; i += mxf->index_tables[j++].nb_segments) {
2177 108 MXFIndexTable *t = &mxf->index_tables[j];
2178 108 MXFTrack *mxf_track = NULL;
2179 108 int64_t offset_temp = 0;
2180
2181 108 t->segments = av_calloc(t->nb_segments, sizeof(*t->segments));
2182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!t->segments) {
2183 av_log(mxf->fc, AV_LOG_ERROR, "failed to allocate IndexTableSegment"
2184 " pointer array\n");
2185 ret = AVERROR(ENOMEM);
2186 goto finish_decoding_index;
2187 }
2188
2189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (sorted_segments[i]->index_start_position)
2190 av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i starts at EditUnit %"PRId64" - seeking may not work as expected\n",
2191 sorted_segments[i]->index_sid, sorted_segments[i]->index_start_position);
2192
2193 108 memcpy(t->segments, &sorted_segments[i], t->nb_segments * sizeof(MXFIndexTableSegment*));
2194 108 t->index_sid = sorted_segments[i]->index_sid;
2195 108 t->body_sid = sorted_segments[i]->body_sid;
2196
2197
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 if ((ret = mxf_compute_ptses_fake_index(mxf, t)) < 0)
2198 goto finish_decoding_index;
2199
2200
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 for (int k = 0; k < mxf->fc->nb_streams; k++) {
2201 117 MXFTrack *track = mxf->fc->streams[k]->priv_data;
2202
3/4
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 108 times.
✗ Branch 3 not taken.
117 if (track && track->index_sid == t->index_sid) {
2203 108 mxf_track = track;
2204 108 break;
2205 }
2206 }
2207
2208 /* fix zero IndexDurations and compute segment offsets */
2209
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 54 times.
163 for (int k = 0; k < t->nb_segments; k++) {
2210 109 MXFIndexTableSegment *s = t->segments[k];
2211
2212
2/4
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 109 times.
109 if (!t->segments[k]->index_edit_rate.num || !t->segments[k]->index_edit_rate.den) {
2213 av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i segment %i has invalid IndexEditRate\n",
2214 t->index_sid, k);
2215 if (mxf_track)
2216 t->segments[k]->index_edit_rate = mxf_track->edit_rate;
2217 }
2218
2219 109 s->offset = offset_temp;
2220
2221 /* EditUnitByteCount == 0 for VBR indexes, which is fine since they use explicit StreamOffsets */
2222
3/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
109 if (s->edit_unit_byte_count && (s->index_duration > INT64_MAX / s->edit_unit_byte_count ||
2223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 s->edit_unit_byte_count * s->index_duration > INT64_MAX - offset_temp)) {
2224 ret = AVERROR_INVALIDDATA;
2225 goto finish_decoding_index;
2226 }
2227
2228 109 offset_temp += t->segments[k]->edit_unit_byte_count * t->segments[k]->index_duration;
2229
2230
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 54 times.
109 if (t->segments[k]->index_duration)
2231 55 continue;
2232
2233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (t->nb_segments > 1)
2234 av_log(mxf->fc, AV_LOG_WARNING, "IndexSID %i segment %i has zero IndexDuration and there's more than one segment\n",
2235 t->index_sid, k);
2236
2237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!mxf_track) {
2238 av_log(mxf->fc, AV_LOG_WARNING, "no streams?\n");
2239 break;
2240 }
2241
2242 /* assume the first stream's duration is reasonable
2243 * leave index_duration = 0 on further segments in case we have any (unlikely)
2244 */
2245 54 t->segments[k]->index_duration = mxf_track->original_duration;
2246 54 break;
2247 }
2248 }
2249
2250 108 ret = 0;
2251 108 finish_decoding_index:
2252 108 av_free(sorted_segments);
2253 108 return ret;
2254 }
2255
2256 103 static int mxf_is_st_422(const UID *essence_container_ul) {
2257 static const uint8_t st_422_essence_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c };
2258
2259
3/4
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 101 times.
103 return essence_container_ul && mxf_match_uid(*essence_container_ul, st_422_essence_container_ul,
2260 sizeof(st_422_essence_container_ul));
2261 }
2262
2263 103 static int mxf_is_intra_only(MXFDescriptor *descriptor)
2264 {
2265 103 return mxf_get_codec_ul(mxf_intra_only_essence_container_uls,
2266
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 42 times.
164 &descriptor->essence_container_ul)->id != AV_CODEC_ID_NONE ||
2267 61 mxf_get_codec_ul(mxf_intra_only_picture_essence_coding_uls,
2268
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 59 times.
61 &descriptor->essence_codec_ul)->id != AV_CODEC_ID_NONE;
2269 }
2270
2271 348 static void mxf_umid_to_str(const UID ul, const UID uid,
2272 char str[2 + sizeof(UID) * 4 + 1])
2273 {
2274 348 snprintf(str, 2 + sizeof(UID) * 4 + 1, "0x");
2275 348 ff_data_to_hex(str + 2, ul, sizeof(UID), 0);
2276 348 ff_data_to_hex(str + 2 + 2 * sizeof(UID), uid, sizeof(UID), 0);
2277 348 }
2278
2279 189 static int mxf_version_to_str(uint16_t major, uint16_t minor, uint16_t tertiary,
2280 uint16_t patch, uint16_t release, char **str)
2281 {
2282 189 *str = av_asprintf("%d.%d.%d.%d.%d", major, minor, tertiary, patch, release);
2283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 189 times.
189 if (!*str)
2284 return AVERROR(ENOMEM);
2285 189 return 0;
2286 }
2287
2288 348 static int mxf_add_umid_metadata(AVDictionary **pm, const char *key, MXFPackage* package)
2289 {
2290 char str[2 + 4 * sizeof(UID) + 1];
2291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348 times.
348 if (!package)
2292 return 0;
2293 348 mxf_umid_to_str(package->package_ul, package->package_uid, str);
2294 348 av_dict_set(pm, key, str, 0);
2295 348 return 0;
2296 }
2297
2298 107 static int mxf_add_timecode_metadata(AVDictionary **pm, const char *key, AVTimecode *tc)
2299 {
2300 char buf[AV_TIMECODE_STR_SIZE];
2301 107 av_dict_set(pm, key, av_timecode_make_string(tc, buf, 0), 0);
2302
2303 107 return 0;
2304 }
2305
2306 14 static MXFTimecodeComponent* mxf_resolve_timecode_component(MXFContext *mxf, UID *strong_ref)
2307 {
2308 MXFTimecodeComponent *timecode;
2309 MXFPulldownComponent *pulldown;
2310
2311 14 timecode = mxf_resolve_strong_ref(mxf, strong_ref, TimecodeComponent);
2312
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
14 if (timecode)
2313 6 return timecode;
2314
2315 8 pulldown = mxf_resolve_strong_ref(mxf, strong_ref, PulldownComponent);
2316
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (pulldown)
2317 1 return mxf_resolve_strong_ref(mxf, &pulldown->input_segment_ref, TimecodeComponent);
2318
2319 7 return NULL;
2320 }
2321
2322 458 static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_ul, UID package_uid)
2323 {
2324 458 MXFPackage *package = NULL;
2325 int i;
2326
2327
2/2
✓ Branch 0 taken 935 times.
✓ Branch 1 taken 229 times.
1164 for (i = 0; i < mxf->packages_count; i++) {
2328 935 package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], SourcePackage);
2329
2/2
✓ Branch 0 taken 455 times.
✓ Branch 1 taken 480 times.
935 if (!package)
2330 455 continue;
2331
2332
4/4
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 229 times.
✓ Branch 3 taken 37 times.
480 if (!memcmp(package->package_ul, package_ul, 16) && !memcmp(package->package_uid, package_uid, 16))
2333 229 return package;
2334 }
2335 229 return NULL;
2336 }
2337
2338 221 static MXFDescriptor* mxf_resolve_descriptor(MXFContext *mxf, UID *strong_ref, int track_id)
2339 {
2340 221 MXFDescriptor *descriptor = mxf_resolve_strong_ref(mxf, strong_ref, Descriptor);
2341
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 205 times.
221 if (descriptor)
2342 16 return descriptor;
2343
2344 205 descriptor = mxf_resolve_strong_ref(mxf, strong_ref, MultipleDescriptor);
2345
1/2
✓ Branch 0 taken 205 times.
✗ Branch 1 not taken.
205 if (descriptor) {
2346
1/2
✓ Branch 0 taken 369 times.
✗ Branch 1 not taken.
369 for (int i = 0; i < descriptor->file_descriptors_count; i++) {
2347 369 MXFDescriptor *file_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->file_descriptors_refs[i], Descriptor);
2348
2349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
369 if (!file_descriptor) {
2350 av_log(mxf->fc, AV_LOG_ERROR, "could not resolve file descriptor strong ref\n");
2351 continue;
2352 }
2353
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 164 times.
369 if (file_descriptor->linked_track_id == track_id) {
2354 205 return file_descriptor;
2355 }
2356 }
2357 }
2358
2359 return NULL;
2360 }
2361
2362 454 static MXFStructuralComponent* mxf_resolve_sourceclip(MXFContext *mxf, UID *strong_ref)
2363 {
2364 454 MXFStructuralComponent *component = NULL;
2365 454 MXFPackage *package = NULL;
2366 454 MXFDescriptor *descriptor = NULL;
2367 MXFEssenceGroup *essence_group;
2368 int i;
2369
2370 454 component = mxf_resolve_strong_ref(mxf, strong_ref, SourceClip);
2371
2/2
✓ Branch 0 taken 244 times.
✓ Branch 1 taken 210 times.
454 if (component)
2372 244 return component;
2373
2374 210 essence_group = mxf_resolve_strong_ref(mxf, strong_ref, EssenceGroup);
2375
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 3 times.
210 if (!essence_group)
2376 207 return NULL;
2377
2378 /* essence groups contains multiple representations of the same media,
2379 this return the first components with a valid Descriptor typically index 0 */
2380
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (i =0; i < essence_group->structural_components_count; i++){
2381 4 component = mxf_resolve_strong_ref(mxf, &essence_group->structural_components_refs[i], SourceClip);
2382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!component)
2383 continue;
2384
2385
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 if (!(package = mxf_resolve_source_package(mxf, component->source_package_ul, component->source_package_uid)))
2386 3 continue;
2387
2388 1 descriptor = mxf_resolve_strong_ref(mxf, &package->descriptor_ref, Descriptor);
2389
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (descriptor)
2390 1 return component;
2391 }
2392
2393 2 return NULL;
2394 }
2395
2396 108 static int mxf_parse_package_comments(MXFContext *mxf, AVDictionary **pm, MXFPackage *package)
2397 {
2398 MXFTaggedValue *tag;
2399 int i;
2400 108 char *key = NULL;
2401
2402
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 108 times.
122 for (i = 0; i < package->comment_count; i++) {
2403 14 tag = mxf_resolve_strong_ref(mxf, &package->comment_refs[i], TaggedValue);
2404
3/6
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
14 if (!tag || !tag->name || !tag->value)
2405 continue;
2406
2407 14 key = av_asprintf("comment_%s", tag->name);
2408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!key)
2409 return AVERROR(ENOMEM);
2410
2411 14 av_dict_set(pm, key, tag->value, AV_DICT_DONT_STRDUP_KEY);
2412 }
2413 108 return 0;
2414 }
2415
2416 221 static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_track, AVStream *st)
2417 {
2418 221 MXFPackage *physical_package = NULL;
2419 221 MXFTrack *physical_track = NULL;
2420 221 MXFStructuralComponent *sourceclip = NULL;
2421 221 MXFTimecodeComponent *mxf_tc = NULL;
2422 int i, j, k;
2423 AVTimecode tc;
2424 int flags;
2425 int64_t start_position;
2426
2427
1/2
✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
221 for (i = 0; i < source_track->sequence->structural_components_count; i++) {
2428 221 sourceclip = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip);
2429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if (!sourceclip)
2430 continue;
2431
2432
2/2
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 7 times.
221 if (!(physical_package = mxf_resolve_source_package(mxf, sourceclip->source_package_ul, sourceclip->source_package_uid)))
2433 214 break;
2434
2435 7 mxf_add_umid_metadata(&st->metadata, "reel_umid", physical_package);
2436
2437 /* the name of physical source package is name of the reel or tape */
2438
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 if (physical_package->name && physical_package->name[0])
2439 7 av_dict_set(&st->metadata, "reel_name", physical_package->name, 0);
2440
2441 /* the source timecode is calculated by adding the start_position of the sourceclip from the file source package track
2442 * to the start_frame of the timecode component located on one of the tracks of the physical source package.
2443 */
2444
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 for (j = 0; j < physical_package->tracks_count; j++) {
2445
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (!(physical_track = mxf_resolve_strong_ref(mxf, &physical_package->tracks_refs[j], Track))) {
2446 av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
2447 continue;
2448 }
2449
2450
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (!(physical_track->sequence = mxf_resolve_strong_ref(mxf, &physical_track->sequence_ref, Sequence))) {
2451 av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n");
2452 continue;
2453 }
2454
2455
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (physical_track->edit_rate.num <= 0 ||
2456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 physical_track->edit_rate.den <= 0) {
2457 av_log(mxf->fc, AV_LOG_WARNING,
2458 "Invalid edit rate (%d/%d) found on structural"
2459 " component #%d, defaulting to 25/1\n",
2460 physical_track->edit_rate.num,
2461 physical_track->edit_rate.den, i);
2462 physical_track->edit_rate = (AVRational){25, 1};
2463 }
2464
2465
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 7 times.
21 for (k = 0; k < physical_track->sequence->structural_components_count; k++) {
2466
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7 times.
14 if (!(mxf_tc = mxf_resolve_timecode_component(mxf, &physical_track->sequence->structural_components_refs[k])))
2467 7 continue;
2468
2469 7 flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
2470 /* scale sourceclip start_position to match physical track edit rate */
2471 7 start_position = av_rescale_q(sourceclip->start_position,
2472 physical_track->edit_rate,
2473 source_track->edit_rate);
2474
2475
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (av_sat_add64(start_position, mxf_tc->start_frame) != start_position + (uint64_t)mxf_tc->start_frame)
2476 return AVERROR_INVALIDDATA;
2477
2478
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if (av_timecode_init(&tc, mxf_tc->rate, flags, start_position + mxf_tc->start_frame, mxf->fc) == 0) {
2479 7 mxf_add_timecode_metadata(&st->metadata, "timecode", &tc);
2480 7 return 0;
2481 }
2482 }
2483 }
2484 }
2485
2486 214 return 0;
2487 }
2488
2489 114 static int mxf_add_metadata_stream(MXFContext *mxf, MXFTrack *track)
2490 {
2491 114 MXFStructuralComponent *component = NULL;
2492 114 const MXFCodecUL *codec_ul = NULL;
2493 MXFPackage tmp_package;
2494 AVStream *st;
2495 int j;
2496
2497
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 102 times.
216 for (j = 0; j < track->sequence->structural_components_count; j++) {
2498 114 component = mxf_resolve_sourceclip(mxf, &track->sequence->structural_components_refs[j]);
2499
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 12 times.
114 if (!component)
2500 102 continue;
2501 12 break;
2502 }
2503
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 12 times.
114 if (!component)
2504 102 return 0;
2505
2506 12 st = avformat_new_stream(mxf->fc, NULL);
2507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!st) {
2508 av_log(mxf->fc, AV_LOG_ERROR, "could not allocate metadata stream\n");
2509 return AVERROR(ENOMEM);
2510 }
2511
2512 12 st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
2513 12 st->codecpar->codec_id = AV_CODEC_ID_NONE;
2514 12 st->id = track->track_id;
2515
2516 12 memcpy(&tmp_package.package_ul, component->source_package_ul, 16);
2517 12 memcpy(&tmp_package.package_uid, component->source_package_uid, 16);
2518 12 mxf_add_umid_metadata(&st->metadata, "file_package_umid", &tmp_package);
2519
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
12 if (track->name && track->name[0])
2520 6 av_dict_set(&st->metadata, "track_name", track->name, 0);
2521
2522 12 codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &track->sequence->data_definition_ul);
2523 12 av_dict_set(&st->metadata, "data_type", av_get_media_type_string(codec_ul->id), 0);
2524 12 return 0;
2525 }
2526
2527 103 static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *descriptor)
2528 {
2529
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
103 if (descriptor->black_ref_level || descriptor->white_ref_level || descriptor->color_range) {
2530 /* CDCI range metadata */
2531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
99 if (!descriptor->component_depth)
2532 return AVCOL_RANGE_UNSPECIFIED;
2533
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
99 if (descriptor->black_ref_level == 0 && descriptor->component_depth < 31 &&
2534 descriptor->white_ref_level == ((1<<descriptor->component_depth) - 1) &&
2535 (descriptor->color_range == (1<<descriptor->component_depth) ||
2536 descriptor->color_range == ((1<<descriptor->component_depth) - 1)))
2537 return AVCOL_RANGE_JPEG;
2538
2/4
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
✗ Branch 3 not taken.
99 if (descriptor->component_depth >= 8 && descriptor->component_depth < 31 &&
2539
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
99 descriptor->black_ref_level == (1 <<(descriptor->component_depth - 4)) &&
2540
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
99 descriptor->white_ref_level == (235<<(descriptor->component_depth - 8)) &&
2541
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
99 descriptor->color_range == ((14<<(descriptor->component_depth - 4)) + 1))
2542 99 return AVCOL_RANGE_MPEG;
2543 avpriv_request_sample(mxf->fc, "Unrecognized CDCI color range (color diff range %d, b %d, w %d, depth %d)",
2544 descriptor->color_range, descriptor->black_ref_level,
2545 descriptor->white_ref_level, descriptor->component_depth);
2546 }
2547
2548 4 return AVCOL_RANGE_UNSPECIFIED;
2549 }
2550
2551 7 static int is_pcm(enum AVCodecID codec_id)
2552 {
2553 /* we only care about "normal" PCM codecs until we get samples */
2554
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 return codec_id >= AV_CODEC_ID_PCM_S16LE && codec_id < AV_CODEC_ID_PCM_S24DAUD;
2555 }
2556
2557 static int set_language(AVFormatContext *s, const char *rfc5646, AVDictionary **met)
2558 {
2559 // language abbr should contain at least 2 chars
2560 if (rfc5646 && strlen(rfc5646) > 1) {
2561 char primary_tag[4] =
2562 {rfc5646[0], rfc5646[1], rfc5646[2] != '-' ? rfc5646[2] : '\0', '\0'};
2563
2564 const char *iso6392 = ff_convert_lang_to(primary_tag,
2565 AV_LANG_ISO639_2_BIBL);
2566 if (iso6392)
2567 return(av_dict_set(met, "language", iso6392, 0));
2568 }
2569 return 0;
2570 }
2571
2572 static MXFMCASubDescriptor *find_mca_link_id(MXFContext *mxf, enum MXFMetadataSetType type, UID *mca_link_id)
2573 {
2574 MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[type];
2575 for (int k = 0; k < mg->metadata_sets_count; k++) {
2576 MXFMCASubDescriptor *group = (MXFMCASubDescriptor*)mg->metadata_sets[k];
2577 if (!memcmp(&group->mca_link_id, mca_link_id, 16))
2578 return group;
2579 }
2580 return NULL;
2581 }
2582
2583 220 static void parse_ffv1_sub_descriptor(MXFContext *mxf, MXFTrack *source_track, MXFDescriptor *descriptor, AVStream *st)
2584 {
2585
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 219 times.
223 for (int i = 0; i < descriptor->sub_descriptors_count; i++) {
2586 4 MXFFFV1SubDescriptor *ffv1_sub_descriptor = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], FFV1SubDescriptor);
2587
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (ffv1_sub_descriptor == NULL)
2588 3 continue;
2589
2590 1 descriptor->extradata = ffv1_sub_descriptor->extradata;
2591 1 descriptor->extradata_size = ffv1_sub_descriptor->extradata_size;
2592 1 ffv1_sub_descriptor->extradata = NULL;
2593 1 ffv1_sub_descriptor->extradata_size = 0;
2594 1 break;
2595 }
2596 220 }
2597
2598 117 static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescriptor *descriptor, AVStream *st)
2599 {
2600 117 AVChannelLayout *ch_layout = &st->codecpar->ch_layout;
2601 117 char *language = NULL;
2602 117 int ambigous_language = 0;
2603 117 enum AVAudioServiceType service_type = AV_AUDIO_SERVICE_TYPE_NB;
2604 117 int ambigous_service_type = 0;
2605 int ret;
2606
2607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 for (int i = 0; i < descriptor->sub_descriptors_count; i++) {
2608 char *channel_language;
2609
2610 MXFMCASubDescriptor *label = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], AudioChannelLabelSubDescriptor);
2611 if (label == NULL)
2612 continue;
2613
2614 if (ch_layout->order == AV_CHANNEL_ORDER_UNSPEC) {
2615 av_channel_layout_uninit(ch_layout);
2616 ret = av_channel_layout_custom_init(ch_layout, descriptor->channels);
2617 if (ret < 0)
2618 return ret;
2619 }
2620
2621 for (const MXFChannelOrderingUL* channel_ordering = mxf_channel_ordering; channel_ordering->uid[0]; channel_ordering++) {
2622 if (IS_KLV_KEY(channel_ordering->uid, label->mca_label_dictionary_id)) {
2623 int target_channel = label->mca_channel_id;
2624 if (target_channel == 0 && descriptor->channels == 1)
2625 target_channel = 1;
2626 if (target_channel <= 0 || target_channel > descriptor->channels) {
2627 av_log(mxf->fc, AV_LOG_ERROR, "AudioChannelLabelSubDescriptor has invalid MCA channel ID %d\n", target_channel);
2628 return AVERROR_INVALIDDATA;
2629 }
2630 ch_layout->u.map[target_channel - 1].id = channel_ordering->channel;
2631 if (service_type == AV_AUDIO_SERVICE_TYPE_NB)
2632 service_type = channel_ordering->service_type;
2633 else if (service_type != channel_ordering->service_type)
2634 ambigous_service_type = 1;
2635 break;
2636 }
2637 }
2638
2639 channel_language = label->language;
2640 if (!channel_language) {
2641 MXFMCASubDescriptor *group = find_mca_link_id(mxf, SoundfieldGroupLabelSubDescriptor, &label->soundfield_group_link_id);
2642 if (group) {
2643 channel_language = group->language;
2644 if (!channel_language && group->group_of_soundfield_groups_link_id_count) {
2645 MXFMCASubDescriptor *supergroup = find_mca_link_id(mxf, GroupOfSoundfieldGroupsLabelSubDescriptor,
2646 group->group_of_soundfield_groups_link_id_refs);
2647 if (supergroup)
2648 channel_language = supergroup->language;
2649 }
2650 }
2651 }
2652 if (channel_language) {
2653 if (language && strcmp(language, channel_language))
2654 ambigous_language = 1;
2655 else
2656 language = channel_language;
2657 }
2658 }
2659
2660
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
117 if (language && !ambigous_language) {
2661 ret = set_language(mxf->fc, language, &st->metadata);
2662 if (ret < 0)
2663 return ret;
2664 }
2665
2666
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
117 if (service_type != AV_AUDIO_SERVICE_TYPE_NB && service_type != AV_AUDIO_SERVICE_TYPE_MAIN && !ambigous_service_type) {
2667 enum AVAudioServiceType *ast;
2668 AVPacketSideData *side_data = av_packet_side_data_new(&st->codecpar->coded_side_data,
2669 &st->codecpar->nb_coded_side_data,
2670 AV_PKT_DATA_AUDIO_SERVICE_TYPE,
2671 sizeof(*ast), 0);
2672 if (!side_data)
2673 return AVERROR(ENOMEM);
2674 ast = (enum AVAudioServiceType*)side_data->data;
2675 *ast = service_type;
2676 }
2677
2678 117 ret = av_channel_layout_retype(ch_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
2679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 if (ret < 0)
2680 return ret;
2681
2682 117 return 0;
2683 }
2684
2685 108 static int mxf_parse_structural_metadata(MXFContext *mxf)
2686 {
2687 108 MXFPackage *material_package = NULL;
2688 int k, ret;
2689
2690 /* TODO: handle multiple material packages (OP3x) */
2691
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
110 for (int i = 0; i < mxf->packages_count; i++) {
2692 110 material_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], MaterialPackage);
2693
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 2 times.
110 if (material_package) break;
2694 }
2695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!material_package) {
2696 av_log(mxf->fc, AV_LOG_ERROR, "no material package found\n");
2697 return AVERROR_INVALIDDATA;
2698 }
2699
2700 108 mxf_add_umid_metadata(&mxf->fc->metadata, "material_package_umid", material_package);
2701
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
108 if (material_package->name && material_package->name[0])
2702 9 av_dict_set(&mxf->fc->metadata, "material_package_name", material_package->name, 0);
2703 108 mxf_parse_package_comments(mxf, &mxf->fc->metadata, material_package);
2704
2705
2/2
✓ Branch 0 taken 335 times.
✓ Branch 1 taken 108 times.
443 for (int i = 0; i < material_package->tracks_count; i++) {
2706 335 MXFPackage *source_package = NULL;
2707 335 MXFTrack *material_track = NULL;
2708 335 MXFTrack *source_track = NULL;
2709 335 MXFTrack *temp_track = NULL;
2710 335 MXFDescriptor *descriptor = NULL;
2711 335 MXFStructuralComponent *component = NULL;
2712 335 MXFTimecodeComponent *mxf_tc = NULL;
2713 335 UID *essence_container_ul = NULL;
2714 335 const MXFCodecUL *codec_ul = NULL;
2715 335 const MXFCodecUL *container_ul = NULL;
2716 335 const MXFCodecUL *pix_fmt_ul = NULL;
2717 AVStream *st;
2718 FFStream *sti;
2719 AVTimecode tc;
2720 int flags;
2721
2722
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 335 times.
335 if (!(material_track = mxf_resolve_strong_ref(mxf, &material_package->tracks_refs[i], Track))) {
2723 av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track strong ref\n");
2724 114 continue;
2725 }
2726
2727
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 335 times.
335 if ((component = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, TimecodeComponent))) {
2728 mxf_tc = (MXFTimecodeComponent*)component;
2729 flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
2730 if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf->fc) == 0) {
2731 mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
2732 }
2733 }
2734
2735
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 335 times.
335 if (!(material_track->sequence = mxf_resolve_strong_ref(mxf, &material_track->sequence_ref, Sequence))) {
2736 av_log(mxf->fc, AV_LOG_ERROR, "could not resolve material track sequence strong ref\n");
2737 continue;
2738 }
2739
2740
2/2
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 235 times.
578 for (int j = 0; j < material_track->sequence->structural_components_count; j++) {
2741 343 component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], TimecodeComponent);
2742
2/2
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 100 times.
343 if (!component)
2743 243 continue;
2744
2745 100 mxf_tc = (MXFTimecodeComponent*)component;
2746 100 flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
2747
1/2
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
100 if (av_timecode_init(&tc, mxf_tc->rate, flags, mxf_tc->start_frame, mxf->fc) == 0) {
2748 100 mxf_add_timecode_metadata(&mxf->fc->metadata, "timecode", &tc);
2749 100 break;
2750 }
2751 }
2752
2753 /* TODO: handle multiple source clips, only finds first valid source clip */
2754
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 327 times.
335 if(material_track->sequence->structural_components_count > 1)
2755 8 av_log(mxf->fc, AV_LOG_WARNING, "material track %d: has %d components\n",
2756 8 material_track->track_id, material_track->sequence->structural_components_count);
2757
2758
2/2
✓ Branch 0 taken 340 times.
✓ Branch 1 taken 114 times.
454 for (int j = 0; j < material_track->sequence->structural_components_count; j++) {
2759 340 component = mxf_resolve_sourceclip(mxf, &material_track->sequence->structural_components_refs[j]);
2760
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 233 times.
340 if (!component)
2761 107 continue;
2762
2763 233 source_package = mxf_resolve_source_package(mxf, component->source_package_ul, component->source_package_uid);
2764
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 221 times.
233 if (!source_package) {
2765 12 av_log(mxf->fc, AV_LOG_TRACE, "material track %d: no corresponding source package found\n", material_track->track_id);
2766 12 continue;
2767 }
2768
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 for (k = 0; k < source_package->tracks_count; k++) {
2769
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 598 times.
598 if (!(temp_track = mxf_resolve_strong_ref(mxf, &source_package->tracks_refs[k], Track))) {
2770 av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track strong ref\n");
2771 ret = AVERROR_INVALIDDATA;
2772 goto fail_and_free;
2773 }
2774
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 377 times.
598 if (temp_track->track_id == component->source_track_id) {
2775 221 source_track = temp_track;
2776 221 break;
2777 }
2778 }
2779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if (!source_track) {
2780 av_log(mxf->fc, AV_LOG_ERROR, "material track %d: no corresponding source track found\n", material_track->track_id);
2781 break;
2782 }
2783
2784
1/2
✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
221 for (k = 0; k < mxf->essence_container_data_count; k++) {
2785 MXFEssenceContainerData *essence_data;
2786
2787
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 221 times.
221 if (!(essence_data = mxf_resolve_strong_ref(mxf, &mxf->essence_container_data_refs[k], EssenceContainerData))) {
2788 av_log(mxf->fc, AV_LOG_TRACE, "could not resolve essence container data strong ref\n");
2789 continue;
2790 }
2791
2/4
✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 221 times.
✗ Branch 3 not taken.
221 if (!memcmp(component->source_package_ul, essence_data->package_ul, sizeof(UID)) && !memcmp(component->source_package_uid, essence_data->package_uid, sizeof(UID))) {
2792 221 source_track->body_sid = essence_data->body_sid;
2793 221 source_track->index_sid = essence_data->index_sid;
2794 221 break;
2795 }
2796 }
2797
2798
2/4
✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 221 times.
✗ Branch 3 not taken.
221 if(source_track && component)
2799 221 break;
2800 }
2801
4/6
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 221 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 221 times.
335 if (!source_track || !component || !source_package) {
2802
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 114 times.
114 if((ret = mxf_add_metadata_stream(mxf, material_track)))
2803 goto fail_and_free;
2804 114 continue;
2805 }
2806
2807
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 221 times.
221 if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref, Sequence))) {
2808 av_log(mxf->fc, AV_LOG_ERROR, "could not resolve source track sequence strong ref\n");
2809 ret = AVERROR_INVALIDDATA;
2810 goto fail_and_free;
2811 }
2812
2813 /* 0001GL00.MXF.A1.mxf_opatom.mxf has the same SourcePackageID as 0001GL.MXF.V1.mxf_opatom.mxf
2814 * This would result in both files appearing to have two streams. Work around this by sanity checking DataDefinition */
2815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if (memcmp(material_track->sequence->data_definition_ul, source_track->sequence->data_definition_ul, 16)) {
2816 av_log(mxf->fc, AV_LOG_ERROR, "material track %d: DataDefinition mismatch\n", material_track->track_id);
2817 continue;
2818 }
2819
2820 221 st = avformat_new_stream(mxf->fc, NULL);
2821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if (!st) {
2822 av_log(mxf->fc, AV_LOG_ERROR, "could not allocate stream\n");
2823 ret = AVERROR(ENOMEM);
2824 goto fail_and_free;
2825 }
2826 221 sti = ffstream(st);
2827 221 st->id = material_track->track_id;
2828 221 st->priv_data = source_track;
2829
2830 221 descriptor = mxf_resolve_descriptor(mxf, &source_package->descriptor_ref, source_track->track_id);
2831
2832 /* A SourceClip from a EssenceGroup may only be a single frame of essence data. The clips duration is then how many
2833 * frames its suppose to repeat for. Descriptor->duration, if present, contains the real duration of the essence data */
2834
3/4
✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 200 times.
221 if (descriptor && descriptor->duration != AV_NOPTS_VALUE)
2835 21 source_track->original_duration = st->duration = FFMIN(descriptor->duration, component->duration);
2836 else
2837 200 source_track->original_duration = st->duration = component->duration;
2838
2839
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 209 times.
221 if (st->duration == -1)
2840 12 st->duration = AV_NOPTS_VALUE;
2841 221 st->start_time = component->start_position;
2842
1/2
✓ Branch 0 taken 221 times.
✗ Branch 1 not taken.
221 if (material_track->edit_rate.num <= 0 ||
2843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 material_track->edit_rate.den <= 0) {
2844 av_log(mxf->fc, AV_LOG_WARNING,
2845 "Invalid edit rate (%d/%d) found on stream #%d, "
2846 "defaulting to 25/1\n",
2847 material_track->edit_rate.num,
2848 material_track->edit_rate.den, st->index);
2849 material_track->edit_rate = (AVRational){25, 1};
2850 }
2851 221 avpriv_set_pts_info(st, 64, material_track->edit_rate.den, material_track->edit_rate.num);
2852
2853 /* ensure SourceTrack EditRate == MaterialTrack EditRate since only
2854 * the former is accessible via st->priv_data */
2855 221 source_track->edit_rate = material_track->edit_rate;
2856
2857 PRINT_KEY(mxf->fc, "data definition ul", source_track->sequence->data_definition_ul);
2858 221 codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul);
2859 221 st->codecpar->codec_type = codec_ul->id;
2860
2861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if (!descriptor) {
2862 av_log(mxf->fc, AV_LOG_INFO, "source track %d: stream %d, no descriptor found\n", source_track->track_id, st->index);
2863 continue;
2864 }
2865 PRINT_KEY(mxf->fc, "essence codec ul", descriptor->essence_codec_ul);
2866 PRINT_KEY(mxf->fc, "essence container ul", descriptor->essence_container_ul);
2867 221 essence_container_ul = &descriptor->essence_container_ul;
2868
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 11 times.
221 source_track->wrapping = (mxf->op == OPAtom) ? ClipWrapped : mxf_get_wrapping_kind(essence_container_ul);
2869
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 216 times.
221 if (source_track->wrapping == UnknownWrapped)
2870 5 av_log(mxf->fc, AV_LOG_INFO, "wrapping of stream %d is unknown\n", st->index);
2871 /* HACK: replacing the original key with mxf_encrypted_essence_container
2872 * is not allowed according to s429-6, try to find correct information anyway */
2873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 221 times.
221 if (IS_KLV_KEY(essence_container_ul, mxf_encrypted_essence_container)) {
2874 MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[CryptoContext];
2875 av_log(mxf->fc, AV_LOG_INFO, "broken encrypted mxf file\n");
2876 if (mg->metadata_sets_count) {
2877 MXFMetadataSet *metadata = mg->metadata_sets[0];
2878 essence_container_ul = &((MXFCryptoContext *)metadata)->source_container_ul;
2879 }
2880 }
2881
2882 /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */
2883 221 codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul);
2884 221 st->codecpar->codec_id = (enum AVCodecID)codec_ul->id;
2885
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 110 times.
221 if (st->codecpar->codec_id == AV_CODEC_ID_NONE) {
2886 111 codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->codec_ul);
2887 111 st->codecpar->codec_id = (enum AVCodecID)codec_ul->id;
2888 }
2889
2890 221 av_log(mxf->fc, AV_LOG_VERBOSE, "%s: Universal Label: ",
2891 221 avcodec_get_name(st->codecpar->codec_id));
2892
2/2
✓ Branch 0 taken 3536 times.
✓ Branch 1 taken 221 times.
3757 for (k = 0; k < 16; k++) {
2893 3536 av_log(mxf->fc, AV_LOG_VERBOSE, "%.2x",
2894 3536 descriptor->essence_codec_ul[k]);
2895
4/4
✓ Branch 0 taken 2873 times.
✓ Branch 1 taken 663 times.
✓ Branch 2 taken 221 times.
✓ Branch 3 taken 2652 times.
3536 if (!(k+1 & 19) || k == 5)
2896 884 av_log(mxf->fc, AV_LOG_VERBOSE, ".");
2897 }
2898 221 av_log(mxf->fc, AV_LOG_VERBOSE, "\n");
2899
2900 221 mxf_add_umid_metadata(&st->metadata, "file_package_umid", source_package);
2901
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
221 if (source_package->name && source_package->name[0])
2902 9 av_dict_set(&st->metadata, "file_package_name", source_package->name, 0);
2903
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 212 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
221 if (material_track->name && material_track->name[0])
2904 6 av_dict_set(&st->metadata, "track_name", material_track->name, 0);
2905
2906 221 mxf_parse_physical_source_package(mxf, source_track, st);
2907
2908
2/2
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 118 times.
221 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
2909 103 source_track->intra_only = mxf_is_intra_only(descriptor);
2910 103 container_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul);
2911
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 100 times.
103 if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
2912 3 st->codecpar->codec_id = container_ul->id;
2913 103 st->codecpar->width = descriptor->width;
2914 103 st->codecpar->height = descriptor->height; /* Field height, not frame height */
2915
2/6
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 5 not taken.
103 switch (descriptor->frame_layout) {
2916 54 case FullFrame:
2917 54 st->codecpar->field_order = AV_FIELD_PROGRESSIVE;
2918 54 break;
2919 case OneField:
2920 /* Every other line is stored and needs to be duplicated. */
2921 av_log(mxf->fc, AV_LOG_INFO, "OneField frame layout isn't currently supported\n");
2922 break; /* The correct thing to do here is fall through, but by breaking we might be
2923 able to decode some streams at half the vertical resolution, rather than not al all.
2924 It's also for compatibility with the old behavior. */
2925 case MixedFields:
2926 break;
2927 case SegmentedFrame:
2928 st->codecpar->field_order = AV_FIELD_PROGRESSIVE;
2929 49 case SeparateFields:
2930 49 av_log(mxf->fc, AV_LOG_DEBUG, "video_line_map: (%d, %d), field_dominance: %d\n",
2931 descriptor->video_line_map[0], descriptor->video_line_map[1],
2932 descriptor->field_dominance);
2933
2/4
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
✗ Branch 3 not taken.
49 if ((descriptor->video_line_map[0] > 0) && (descriptor->video_line_map[1] > 0)) {
2934 /* Detect coded field order from VideoLineMap:
2935 * (even, even) => bottom field coded first
2936 * (even, odd) => top field coded first
2937 * (odd, even) => top field coded first
2938 * (odd, odd) => bottom field coded first
2939 */
2940
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 6 times.
49 if ((descriptor->video_line_map[0] + descriptor->video_line_map[1]) % 2) {
2941
1/3
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
43 switch (descriptor->field_dominance) {
2942 43 case MXF_FIELD_DOMINANCE_DEFAULT:
2943 case MXF_FIELD_DOMINANCE_FF:
2944 43 st->codecpar->field_order = AV_FIELD_TT;
2945 43 break;
2946 case MXF_FIELD_DOMINANCE_FL:
2947 st->codecpar->field_order = AV_FIELD_TB;
2948 break;
2949 default:
2950 avpriv_request_sample(mxf->fc,
2951 "Field dominance %d support",
2952 descriptor->field_dominance);
2953 }
2954 } else {
2955
1/3
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
6 switch (descriptor->field_dominance) {
2956 6 case MXF_FIELD_DOMINANCE_DEFAULT:
2957 case MXF_FIELD_DOMINANCE_FF:
2958 6 st->codecpar->field_order = AV_FIELD_BB;
2959 6 break;
2960 case MXF_FIELD_DOMINANCE_FL:
2961 st->codecpar->field_order = AV_FIELD_BT;
2962 break;
2963 default:
2964 avpriv_request_sample(mxf->fc,
2965 "Field dominance %d support",
2966 descriptor->field_dominance);
2967 }
2968 }
2969 }
2970 /* Turn field height into frame height. */
2971 49 st->codecpar->height *= 2;
2972 49 break;
2973 default:
2974 av_log(mxf->fc, AV_LOG_INFO, "Unknown frame layout type: %d\n", descriptor->frame_layout);
2975 }
2976
2977
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 101 times.
103 if (mxf_is_st_422(essence_container_ul)) {
2978
2/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
2 switch ((*essence_container_ul)[14]) {
2979 1 case 2: /* Cn: Clip- wrapped Picture Element */
2980 case 3: /* I1: Interlaced Frame, 1 field/KLV */
2981 case 4: /* I2: Interlaced Frame, 2 fields/KLV */
2982 case 6: /* P1: Frame- wrapped Picture Element */
2983 1 st->avg_frame_rate = source_track->edit_rate;
2984 1 st->r_frame_rate = st->avg_frame_rate;
2985 1 break;
2986 case 5: /* F1: Field-wrapped Picture Element */
2987 st->avg_frame_rate = av_mul_q(av_make_q(2, 1), source_track->edit_rate);
2988 st->r_frame_rate = st->avg_frame_rate;
2989 break;
2990 1 default:
2991 1 break;
2992 }
2993 }
2994
2995
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 98 times.
103 if (st->codecpar->codec_id == AV_CODEC_ID_PRORES) {
2996
1/7
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
5 switch (descriptor->essence_codec_ul[14]) {
2997 5 case 1: st->codecpar->codec_tag = MKTAG('a','p','c','o'); break;
2998 case 2: st->codecpar->codec_tag = MKTAG('a','p','c','s'); break;
2999 case 3: st->codecpar->codec_tag = MKTAG('a','p','c','n'); break;
3000 case 4: st->codecpar->codec_tag = MKTAG('a','p','c','h'); break;
3001 case 5: st->codecpar->codec_tag = MKTAG('a','p','4','h'); break;
3002 case 6: st->codecpar->codec_tag = MKTAG('a','p','4','x'); break;
3003 }
3004 }
3005
3006
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 102 times.
103 if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) {
3007 1 st->codecpar->format = descriptor->pix_fmt;
3008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (st->codecpar->format == AV_PIX_FMT_NONE) {
3009 pix_fmt_ul = mxf_get_codec_ul(ff_mxf_pixel_format_uls,
3010 &descriptor->essence_codec_ul);
3011 st->codecpar->format = (enum AVPixelFormat)pix_fmt_ul->id;
3012 if (st->codecpar->format== AV_PIX_FMT_NONE) {
3013 st->codecpar->codec_tag = mxf_get_codec_ul(ff_mxf_codec_tag_uls,
3014 &descriptor->essence_codec_ul)->id;
3015 if (!st->codecpar->codec_tag) {
3016 /* support files created before RP224v10 by defaulting to UYVY422
3017 if subsampling is 4:2:2 and component depth is 8-bit */
3018 if (descriptor->horiz_subsampling == 2 &&
3019 descriptor->vert_subsampling == 1 &&
3020 descriptor->component_depth == 8) {
3021 st->codecpar->format = AV_PIX_FMT_UYVY422;
3022 }
3023 }
3024 }
3025 }
3026 }
3027 103 sti->need_parsing = AVSTREAM_PARSE_HEADERS;
3028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
103 if (material_track->sequence->origin) {
3029 av_dict_set_int(&st->metadata, "material_track_origin", material_track->sequence->origin, 0);
3030 }
3031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
103 if (source_track->sequence->origin) {
3032 av_dict_set_int(&st->metadata, "source_track_origin", source_track->sequence->origin, 0);
3033 }
3034
2/4
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 103 times.
✗ Branch 3 not taken.
103 if (descriptor->aspect_ratio.num && descriptor->aspect_ratio.den)
3035 103 sti->display_aspect_ratio = descriptor->aspect_ratio;
3036 103 st->codecpar->color_range = mxf_get_color_range(mxf, descriptor);
3037 103 st->codecpar->color_primaries = mxf_get_codec_ul(ff_mxf_color_primaries_uls, &descriptor->color_primaries_ul)->id;
3038 103 st->codecpar->color_trc = mxf_get_codec_ul(ff_mxf_color_trc_uls, &descriptor->color_trc_ul)->id;
3039 103 st->codecpar->color_space = mxf_get_codec_ul(ff_mxf_color_space_uls, &descriptor->color_space_ul)->id;
3040
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 98 times.
103 if (descriptor->mastering) {
3041
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
3042 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
3043 5 (uint8_t *)descriptor->mastering, descriptor->mastering_size, 0)) {
3044 ret = AVERROR(ENOMEM);
3045 goto fail_and_free;
3046 }
3047 5 descriptor->mastering = NULL;
3048 }
3049
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 100 times.
103 if (descriptor->coll) {
3050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
3051 AV_PKT_DATA_CONTENT_LIGHT_LEVEL,
3052 3 (uint8_t *)descriptor->coll, descriptor->coll_size, 0)) {
3053 ret = AVERROR(ENOMEM);
3054 goto fail_and_free;
3055 }
3056 3 descriptor->coll = NULL;
3057 }
3058
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 1 times.
118 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3059 117 container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
3060 /* Only overwrite existing codec ID if it is unset or A-law, which is the default according to SMPTE RP 224. */
3061
5/6
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 107 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
117 if (st->codecpar->codec_id == AV_CODEC_ID_NONE || (st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW && (enum AVCodecID)container_ul->id != AV_CODEC_ID_NONE))
3062 107 st->codecpar->codec_id = (enum AVCodecID)container_ul->id;
3063 117 st->codecpar->ch_layout.nb_channels = descriptor->channels;
3064
3065
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 if (descriptor->sample_rate.den > 0) {
3066 117 st->codecpar->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den;
3067 117 avpriv_set_pts_info(st, 64, descriptor->sample_rate.den, descriptor->sample_rate.num);
3068 } else {
3069 av_log(mxf->fc, AV_LOG_WARNING, "invalid sample rate (%d/%d) "
3070 "found for stream #%d, time base forced to 1/48000\n",
3071 descriptor->sample_rate.num, descriptor->sample_rate.den,
3072 st->index);
3073 avpriv_set_pts_info(st, 64, 1, 48000);
3074 }
3075
3076 /* if duration is set, rescale it from EditRate to SampleRate */
3077
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 6 times.
117 if (st->duration != AV_NOPTS_VALUE)
3078 111 st->duration = av_rescale_q(st->duration,
3079 av_inv_q(material_track->edit_rate),
3080 st->time_base);
3081
3082 /* TODO: implement AV_CODEC_ID_RAWAUDIO */
3083
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 4 times.
117 if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) {
3084
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
113 if (descriptor->bits_per_sample > 16 && descriptor->bits_per_sample <= 24)
3085 23 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
3086
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 else if (descriptor->bits_per_sample == 32)
3087 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
3088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) {
3089 if (descriptor->bits_per_sample > 16 && descriptor->bits_per_sample <= 24)
3090 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
3091 else if (descriptor->bits_per_sample == 32)
3092 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
3093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) {
3094 sti->need_parsing = AVSTREAM_PARSE_FULL;
3095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
3096 sti->need_parsing = AVSTREAM_PARSE_FULL;
3097 }
3098 117 st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
3099
3100
2/4
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 117 times.
117 if (descriptor->channels <= 0 || descriptor->channels >= FF_SANE_NB_CHANNELS) {
3101 av_log(mxf->fc, AV_LOG_ERROR, "Invalid number of channels %d, must be less than %d\n", descriptor->channels, FF_SANE_NB_CHANNELS);
3102 return AVERROR_INVALIDDATA;
3103 }
3104
3105 117 ret = parse_mca_labels(mxf, source_track, descriptor, st);
3106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 if (ret < 0)
3107 return ret;
3108
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
3109 enum AVMediaType type;
3110 1 container_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul);
3111
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
3112 1 st->codecpar->codec_id = container_ul->id;
3113 1 type = avcodec_get_type(st->codecpar->codec_id);
3114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (type == AVMEDIA_TYPE_SUBTITLE)
3115 st->codecpar->codec_type = type;
3116
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (container_ul->desc)
3117 1 av_dict_set(&st->metadata, "data_type", container_ul->desc, 0);
3118
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (mxf->eia608_extract && st->codecpar->codec_id == AV_CODEC_ID_SMPTE_436M_ANC) {
3119 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
3120 st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
3121 }
3122 }
3123
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 1 times.
221 if (!descriptor->extradata)
3124 220 parse_ffv1_sub_descriptor(mxf, source_track, descriptor, st);
3125
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 219 times.
221 if (descriptor->extradata) {
3126
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!ff_alloc_extradata(st->codecpar, descriptor->extradata_size)) {
3127 2 memcpy(st->codecpar->extradata, descriptor->extradata, descriptor->extradata_size);
3128 }
3129
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 218 times.
219 } else if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
3130 1 int coded_width = mxf_get_codec_ul(mxf_intra_only_picture_coded_width,
3131 &descriptor->essence_codec_ul)->id;
3132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (coded_width)
3133 st->codecpar->width = coded_width;
3134 1 ret = ff_generate_avci_extradata(st);
3135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3136 return ret;
3137 }
3138
4/4
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 204 times.
221 if (st->codecpar->codec_type != AVMEDIA_TYPE_DATA && source_track->wrapping != FrameWrapped) {
3139 /* TODO: decode timestamps */
3140 16 sti->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
3141 }
3142 }
3143
3144
2/2
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 108 times.
341 for (int i = 0; i < mxf->fc->nb_streams; i++) {
3145 233 MXFTrack *track1 = mxf->fc->streams[i]->priv_data;
3146
3/4
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 221 times.
✗ Branch 3 not taken.
233 if (track1 && track1->body_sid) {
3147
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 221 times.
388 for (int j = i + 1; j < mxf->fc->nb_streams; j++) {
3148 167 MXFTrack *track2 = mxf->fc->streams[j]->priv_data;
3149
4/6
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 164 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 164 times.
167 if (track2 && track1->body_sid == track2->body_sid && track1->wrapping != track2->wrapping) {
3150 if (track1->wrapping == UnknownWrapped)
3151 track1->wrapping = track2->wrapping;
3152 else if (track2->wrapping == UnknownWrapped)
3153 track2->wrapping = track1->wrapping;
3154 else
3155 av_log(mxf->fc, AV_LOG_ERROR, "stream %d and stream %d have the same BodySID (%d) "
3156 "with different wrapping\n", i, j, track1->body_sid);
3157 }
3158 }
3159 }
3160 }
3161
3162 108 ret = 0;
3163 108 fail_and_free:
3164 108 return ret;
3165 }
3166
3167 20 static int64_t mxf_timestamp_to_int64(uint64_t timestamp)
3168 {
3169 20 struct tm time = { 0 };
3170 int msecs;
3171 20 time.tm_year = (timestamp >> 48) - 1900;
3172 20 time.tm_mon = (timestamp >> 40 & 0xFF) - 1;
3173 20 time.tm_mday = (timestamp >> 32 & 0xFF);
3174 20 time.tm_hour = (timestamp >> 24 & 0xFF);
3175 20 time.tm_min = (timestamp >> 16 & 0xFF);
3176 20 time.tm_sec = (timestamp >> 8 & 0xFF);
3177 20 msecs = (timestamp & 0xFF) * 4;
3178
3179 /* Clip values for legacy reasons. Maybe we should return error instead? */
3180 20 time.tm_mon = av_clip(time.tm_mon, 0, 11);
3181 20 time.tm_mday = av_clip(time.tm_mday, 1, 31);
3182 20 time.tm_hour = av_clip(time.tm_hour, 0, 23);
3183 20 time.tm_min = av_clip(time.tm_min, 0, 59);
3184 20 time.tm_sec = av_clip(time.tm_sec, 0, 59);
3185 20 msecs = av_clip(msecs, 0, 999);
3186
3187 20 return (int64_t)av_timegm(&time) * 1000000 + msecs * 1000;
3188 }
3189
3190 #define SET_STR_METADATA(pb, name, str) do { \
3191 if ((ret = mxf_read_utf16be_string(pb, size, &str)) < 0) \
3192 return ret; \
3193 av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \
3194 } while (0)
3195
3196 #define SET_VERSION_METADATA(pb, name, major, minor, tertiary, patch, release, str) do { \
3197 major = avio_rb16(pb); \
3198 minor = avio_rb16(pb); \
3199 tertiary = avio_rb16(pb); \
3200 patch = avio_rb16(pb); \
3201 release = avio_rb16(pb); \
3202 if ((ret = mxf_version_to_str(major, minor, tertiary, patch, release, &str)) < 0) \
3203 return ret; \
3204 av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \
3205 } while (0)
3206
3207 #define SET_UID_METADATA(pb, name, var, str) do { \
3208 char uuid_str[2 * AV_UUID_LEN + 4 + 1]; \
3209 avio_read(pb, var, 16); \
3210 av_uuid_unparse(uid, uuid_str); \
3211 av_dict_set(&s->metadata, name, uuid_str, 0); \
3212 } while (0)
3213
3214 #define SET_TS_METADATA(pb, name, var, str) do { \
3215 var = avio_rb64(pb); \
3216 if (var && (ret = ff_dict_set_timestamp(&s->metadata, name, mxf_timestamp_to_int64(var))) < 0) \
3217 return ret; \
3218 } while (0)
3219
3220 1032 static int mxf_read_identification_metadata(void *arg, AVIOContext *pb, int tag, int size, UID _uid, int64_t klv_offset)
3221 {
3222 1032 MXFContext *mxf = arg;
3223 1032 AVFormatContext *s = mxf->fc;
3224 int ret;
3225 1032 UID uid = { 0 };
3226 1032 char *str = NULL;
3227 uint64_t ts;
3228 uint16_t major, minor, tertiary, patch, release;
3229
11/11
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 105 times.
✓ Branch 2 taken 92 times.
✓ Branch 3 taken 105 times.
✓ Branch 4 taken 105 times.
✓ Branch 5 taken 105 times.
✓ Branch 6 taken 97 times.
✓ Branch 7 taken 96 times.
✓ Branch 8 taken 109 times.
✓ Branch 9 taken 109 times.
✓ Branch 10 taken 4 times.
1032 switch (tag) {
3230 105 case 0x3C01:
3231
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 105 times.
105 SET_STR_METADATA(pb, "company_name", str);
3232 105 break;
3233 105 case 0x3C02:
3234
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 105 times.
105 SET_STR_METADATA(pb, "product_name", str);
3235 105 break;
3236 92 case 0x3C03:
3237
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 92 times.
92 SET_VERSION_METADATA(pb, "product_version_num", major, minor, tertiary, patch, release, str);
3238 92 break;
3239 105 case 0x3C04:
3240
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 105 times.
105 SET_STR_METADATA(pb, "product_version", str);
3241 105 break;
3242 105 case 0x3C05:
3243 105 SET_UID_METADATA(pb, "product_uid", uid, str);
3244 105 break;
3245 105 case 0x3C06:
3246
3/4
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 85 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
105 SET_TS_METADATA(pb, "modification_date", ts, str);
3247 105 break;
3248 97 case 0x3C07:
3249
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 97 times.
97 SET_VERSION_METADATA(pb, "toolkit_version_num", major, minor, tertiary, patch, release, str);
3250 97 break;
3251 96 case 0x3C08:
3252
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 96 times.
96 SET_STR_METADATA(pb, "application_platform", str);
3253 96 break;
3254 109 case 0x3C09:
3255 109 SET_UID_METADATA(pb, "generation_uid", uid, str);
3256 109 break;
3257 109 case 0x3C0A:
3258 109 SET_UID_METADATA(pb, "uid", uid, str);
3259 109 break;
3260 }
3261 1032 return 0;
3262 }
3263
3264 1013 static int mxf_read_preface_metadata(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
3265 {
3266 1013 MXFContext *mxf = arg;
3267 1013 AVFormatContext *s = mxf->fc;
3268 int ret;
3269 1013 char *str = NULL;
3270
3271
4/4
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 982 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 24 times.
1013 if (tag >= 0x8000 && (IS_KLV_KEY(uid, mxf_avid_project_name))) {
3272
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 SET_STR_METADATA(pb, "project_name", str);
3273 }
3274 1013 return 0;
3275 }
3276
3277 static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
3278 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack },
3279 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack },
3280 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x02,0x00 }, mxf_read_partition_pack },
3281 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x03,0x00 }, mxf_read_partition_pack },
3282 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x04,0x00 }, mxf_read_partition_pack },
3283 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x01,0x00 }, mxf_read_partition_pack },
3284 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x02,0x00 }, mxf_read_partition_pack },
3285 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x03,0x00 }, mxf_read_partition_pack },
3286 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }, mxf_read_partition_pack },
3287 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x02,0x00 }, mxf_read_partition_pack },
3288 { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack },
3289 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x2f,0x00 }, mxf_read_preface_metadata },
3290 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x30,0x00 }, mxf_read_identification_metadata },
3291 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage },
3292 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_package, sizeof(MXFPackage), SourcePackage },
3293 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_package, sizeof(MXFPackage), MaterialPackage },
3294 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0f,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence },
3295 { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x05,0x00 }, mxf_read_essence_group, sizeof(MXFEssenceGroup), EssenceGroup},
3296 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip },
3297 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3f,0x00 }, mxf_read_tagged_value, sizeof(MXFTaggedValue), TaggedValue },
3298 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor },
3299 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */
3300 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x28,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* CDCI */
3301 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x29,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* RGBA */
3302 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Wave */
3303 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* AES3 */
3304 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG2VideoDescriptor */
3305 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5b,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* VBI - SMPTE 436M */
3306 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* VANC/VBI - SMPTE 436M */
3307 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5e,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG2AudioDescriptor */
3308 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x64,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* DC Timed Text Descriptor */
3309 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6b,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), AudioChannelLabelSubDescriptor },
3310 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6c,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), SoundfieldGroupLabelSubDescriptor },
3311 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6d,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), GroupOfSoundfieldGroupsLabelSubDescriptor },
3312 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x03 }, mxf_read_ffv1_sub_descriptor, sizeof(MXFFFV1SubDescriptor), FFV1SubDescriptor },
3313 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */
3314 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */
3315 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent },
3316 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0c,0x00 }, mxf_read_pulldown_component, sizeof(MXFPulldownComponent), PulldownComponent },
3317 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x04,0x01,0x02,0x02,0x00,0x00 }, mxf_read_cryptographic_context, sizeof(MXFCryptoContext), CryptoContext },
3318 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x10,0x01,0x00 }, mxf_read_index_table_segment, sizeof(MXFIndexTableSegment), IndexTableSegment },
3319 { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x23,0x00 }, mxf_read_essence_container_data, sizeof(MXFEssenceContainerData), EssenceContainerData },
3320 { { 0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x01,0x02,0x10,0x01,0x00,0x00,0x00 } }, /* KLV fill, skip */
3321 };
3322
3323 2951 static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type, MXFPartition *partition)
3324 {
3325 2951 ctx->partition_score = partition_score(partition);
3326
2/2
✓ Branch 0 taken 323 times.
✓ Branch 1 taken 2628 times.
2951 switch (type){
3327 323 case MultipleDescriptor:
3328 case Descriptor:
3329 323 ((MXFDescriptor*)ctx)->pix_fmt = AV_PIX_FMT_NONE;
3330 323 ((MXFDescriptor*)ctx)->duration = AV_NOPTS_VALUE;
3331 323 break;
3332 2628 default:
3333 2628 break;
3334 }
3335 2951 return 0;
3336 }
3337
3338 3278 static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadFunc *read_child, int ctx_size, enum MXFMetadataSetType type)
3339 {
3340 3278 AVIOContext *pb = mxf->fc->pb;
3341 3278 uint64_t klv_end = avio_tell(pb) + klv->length;
3342 MXFMetadataSet *meta;
3343 void *ctx;
3344
3345
2/2
✓ Branch 0 taken 2951 times.
✓ Branch 1 taken 327 times.
3278 if (ctx_size) {
3346 2951 meta = av_mallocz(ctx_size);
3347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2951 times.
2951 if (!meta)
3348 return AVERROR(ENOMEM);
3349 2951 ctx = meta;
3350 2951 mxf_metadataset_init(meta, type, mxf->current_partition);
3351 } else {
3352 327 meta = NULL;
3353 327 ctx = mxf;
3354 }
3355
3/4
✓ Branch 1 taken 21600 times.
✓ Branch 2 taken 3278 times.
✓ Branch 4 taken 21600 times.
✗ Branch 5 not taken.
24878 while (avio_tell(pb) + 4ULL < klv_end && !avio_feof(pb)) {
3356 int ret;
3357 21600 int tag = avio_rb16(pb);
3358 21600 int size = avio_rb16(pb); /* KLV specified by 0x53 */
3359 21600 int64_t next = avio_tell(pb);
3360 21600 UID uid = {0};
3361
2/4
✓ Branch 0 taken 21600 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21600 times.
21600 if (next < 0 || next > INT64_MAX - size) {
3362 if (meta) {
3363 mxf_free_metadataset(&meta, type);
3364 }
3365 return next < 0 ? next : AVERROR_INVALIDDATA;
3366 }
3367 21600 next += size;
3368
3369 21600 av_log(mxf->fc, AV_LOG_TRACE, "local tag %#04x size %d\n", tag, size);
3370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21600 times.
21600 if (!size) { /* ignore empty tag, needed for some files with empty UMID tag */
3371 av_log(mxf->fc, AV_LOG_ERROR, "local tag %#04x with 0 size\n", tag);
3372 continue;
3373 }
3374
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 21215 times.
21600 if (tag > 0x7FFF) { /* dynamic tag */
3375 int i;
3376
2/2
✓ Branch 0 taken 56987 times.
✓ Branch 1 taken 385 times.
57372 for (i = 0; i < mxf->local_tags_count; i++) {
3377 56987 int local_tag = AV_RB16(mxf->local_tags+i*18);
3378
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 56602 times.
56987 if (local_tag == tag) {
3379 385 memcpy(uid, mxf->local_tags+i*18+2, 16);
3380 385 av_log(mxf->fc, AV_LOG_TRACE, "local tag %#04x\n", local_tag);
3381 PRINT_KEY(mxf->fc, "uid", uid);
3382 }
3383 }
3384 }
3385
4/4
✓ Branch 0 taken 19228 times.
✓ Branch 1 taken 2372 times.
✓ Branch 2 taken 2951 times.
✓ Branch 3 taken 16277 times.
21600 if (meta && tag == 0x3C0A) {
3386 2951 avio_read(pb, meta->uid, 16);
3387
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18649 times.
18649 } else if ((ret = read_child(ctx, pb, tag, size, uid, -1)) < 0) {
3388 if (meta) {
3389 mxf_free_metadataset(&meta, type);
3390 }
3391 return ret;
3392 }
3393
3394 /* Accept the 64k local set limit being exceeded (Avid). Don't accept
3395 * it extending past the end of the KLV though (zzuf5.mxf). */
3396
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21600 times.
21600 if (avio_tell(pb) > klv_end) {
3397 if (meta) {
3398 mxf_free_metadataset(&meta, type);
3399 }
3400
3401 av_log(mxf->fc, AV_LOG_ERROR,
3402 "local tag %#04x extends past end of local set @ %#"PRIx64"\n",
3403 tag, klv->offset);
3404 return AVERROR_INVALIDDATA;
3405
2/2
✓ Branch 1 taken 21596 times.
✓ Branch 2 taken 4 times.
21600 } else if (avio_tell(pb) <= next) /* only seek forward, else this can loop for a long time */
3406 21596 avio_seek(pb, next, SEEK_SET);
3407 }
3408
2/2
✓ Branch 0 taken 2951 times.
✓ Branch 1 taken 327 times.
3278 return meta ? mxf_add_metadata_set(mxf, &meta, type) : 0;
3409 }
3410
3411 /**
3412 * Matches any partition pack key, in other words:
3413 * - HeaderPartition
3414 * - BodyPartition
3415 * - FooterPartition
3416 * @return non-zero if the key is a partition pack key, zero otherwise
3417 */
3418 8709 static int mxf_is_partition_pack_key(UID key)
3419 {
3420 //NOTE: this is a little lax since it doesn't constraint key[14]
3421 9092 return !memcmp(key, mxf_header_partition_pack_key, 13) &&
3422
5/6
✓ Branch 0 taken 383 times.
✓ Branch 1 taken 8326 times.
✓ Branch 2 taken 383 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 274 times.
✓ Branch 5 taken 109 times.
8709 key[13] >= 2 && key[13] <= 4;
3423 }
3424
3425 /**
3426 * Parses a metadata KLV
3427 * @return <0 on error, 0 otherwise
3428 */
3429 3657 static int mxf_parse_klv(MXFContext *mxf, KLVPacket klv, MXFMetadataReadFunc *read,
3430 int ctx_size, enum MXFMetadataSetType type)
3431 {
3432 3657 AVFormatContext *s = mxf->fc;
3433 int res;
3434
2/2
✓ Branch 0 taken 3278 times.
✓ Branch 1 taken 379 times.
3657 if (klv.key[5] == 0x53) {
3435 3278 res = mxf_read_local_tags(mxf, &klv, read, ctx_size, type);
3436 } else {
3437 379 uint64_t next = avio_tell(s->pb) + klv.length;
3438 379 res = read(mxf, s->pb, 0, klv.length, klv.key, klv.offset);
3439
3440 /* only seek forward, else this can loop for a long time */
3441
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 379 times.
379 if (avio_tell(s->pb) > next) {
3442 av_log(s, AV_LOG_ERROR, "read past end of KLV @ %#"PRIx64"\n",
3443 klv.offset);
3444 return AVERROR_INVALIDDATA;
3445 }
3446
3447 379 avio_seek(s->pb, next, SEEK_SET);
3448 }
3449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3657 times.
3657 if (res < 0) {
3450 av_log(s, AV_LOG_ERROR, "error reading header metadata\n");
3451 return res;
3452 }
3453 3657 return 0;
3454 }
3455
3456 /**
3457 * Seeks to the previous partition and parses it, if possible
3458 * @return <= 0 if we should stop parsing, > 0 if we should keep going
3459 */
3460 106 static int mxf_seek_to_previous_partition(MXFContext *mxf)
3461 {
3462 106 AVIOContext *pb = mxf->fc->pb;
3463 KLVPacket klv;
3464 int64_t current_partition_ofs;
3465 int ret;
3466
3467
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 1 times.
106 if (!mxf->current_partition ||
3468
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 4 times.
105 mxf->run_in + mxf->current_partition->previous_partition <= mxf->last_forward_tell)
3469 102 return 0; /* we've parsed all partitions */
3470
3471 /* seek to previous partition */
3472 4 current_partition_ofs = mxf->current_partition->pack_ofs; //includes run-in
3473 4 avio_seek(pb, mxf->run_in + mxf->current_partition->previous_partition, SEEK_SET);
3474 4 mxf->current_partition = NULL;
3475
3476 4 av_log(mxf->fc, AV_LOG_TRACE, "seeking to previous partition\n");
3477
3478 /* Make sure this is actually a PartitionPack, and if so parse it.
3479 * See deadlock2.mxf
3480 */
3481
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = klv_read_packet(mxf, &klv, pb)) < 0) {
3482 av_log(mxf->fc, AV_LOG_ERROR, "failed to read PartitionPack KLV\n");
3483 return ret;
3484 }
3485
3486
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!mxf_is_partition_pack_key(klv.key)) {
3487 av_log(mxf->fc, AV_LOG_ERROR, "PreviousPartition @ %" PRIx64 " isn't a PartitionPack\n", klv.offset);
3488 return AVERROR_INVALIDDATA;
3489 }
3490
3491 /* We can't just check ofs >= current_partition_ofs because PreviousPartition
3492 * can point to just before the current partition, causing klv_read_packet()
3493 * to sync back up to it. See deadlock3.mxf
3494 */
3495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (klv.offset >= current_partition_ofs) {
3496 av_log(mxf->fc, AV_LOG_ERROR, "PreviousPartition for PartitionPack @ %"
3497 PRIx64 " indirectly points to itself\n", current_partition_ofs);
3498 return AVERROR_INVALIDDATA;
3499 }
3500
3501
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if ((ret = mxf_parse_klv(mxf, klv, mxf_read_partition_pack, 0, 0)) < 0)
3502 return ret;
3503
3504 4 return 1;
3505 }
3506
3507 /**
3508 * Called when essence is encountered
3509 * @return <= 0 if we should stop parsing, > 0 if we should keep going
3510 */
3511 108 static int mxf_parse_handle_essence(MXFContext *mxf)
3512 {
3513 108 AVIOContext *pb = mxf->fc->pb;
3514 int64_t ret;
3515
3516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (mxf->parsing_backward) {
3517 return mxf_seek_to_previous_partition(mxf);
3518 } else {
3519
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 102 times.
108 if (!mxf->footer_partition) {
3520 6 av_log(mxf->fc, AV_LOG_TRACE, "no FooterPartition\n");
3521 6 return 0;
3522 }
3523
3524 102 av_log(mxf->fc, AV_LOG_TRACE, "seeking to FooterPartition\n");
3525
3526 /* remember where we were so we don't end up seeking further back than this */
3527 102 mxf->last_forward_tell = avio_tell(pb);
3528
3529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) {
3530 av_log(mxf->fc, AV_LOG_INFO, "file is not seekable - not parsing FooterPartition\n");
3531 return -1;
3532 }
3533
3534 /* seek to FooterPartition and parse backward */
3535
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
102 if ((ret = avio_seek(pb, mxf->run_in + mxf->footer_partition, SEEK_SET)) < 0) {
3536 av_log(mxf->fc, AV_LOG_ERROR,
3537 "failed to seek to FooterPartition @ 0x%" PRIx64
3538 " (%"PRId64") - partial file?\n",
3539 mxf->run_in + mxf->footer_partition, ret);
3540 return ret;
3541 }
3542
3543 102 mxf->current_partition = NULL;
3544 102 mxf->parsing_backward = 1;
3545 }
3546
3547 102 return 1;
3548 }
3549
3550 /**
3551 * Called when the next partition or EOF is encountered
3552 * @return <= 0 if we should stop parsing, > 0 if we should keep going
3553 */
3554 163 static int mxf_parse_handle_partition_or_eof(MXFContext *mxf)
3555 {
3556
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 57 times.
163 return mxf->parsing_backward ? mxf_seek_to_previous_partition(mxf) : 1;
3557 }
3558
3559 97 static MXFWrappingScheme mxf_get_wrapping_by_body_sid(AVFormatContext *s, int body_sid)
3560 {
3561
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 1 times.
102 for (int i = 0; i < s->nb_streams; i++) {
3562 101 MXFTrack *track = s->streams[i]->priv_data;
3563
4/6
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 101 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 96 times.
✓ Branch 5 taken 5 times.
101 if (track && track->body_sid == body_sid && track->wrapping != UnknownWrapped)
3564 96 return track->wrapping;
3565 }
3566 1 return UnknownWrapped;
3567 }
3568
3569 /**
3570 * Figures out the proper offset and length of the essence container in each partition
3571 */
3572 108 static void mxf_compute_essence_containers(AVFormatContext *s)
3573 {
3574 108 MXFContext *mxf = s->priv_data;
3575 int x;
3576
3577
2/2
✓ Branch 0 taken 270 times.
✓ Branch 1 taken 108 times.
378 for (x = 0; x < mxf->partitions_count; x++) {
3578 270 MXFPartition *p = &mxf->partitions[x];
3579 MXFWrappingScheme wrapping;
3580
3581
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 108 times.
270 if (!p->body_sid)
3582 162 continue; /* BodySID == 0 -> no essence */
3583
3584 /* for clip wrapped essences we point essence_offset after the KL (usually klv.offset + 20 or 25)
3585 * otherwise we point essence_offset at the key of the first essence KLV.
3586 */
3587
3588
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 11 times.
108 wrapping = (mxf->op == OPAtom) ? ClipWrapped : mxf_get_wrapping_by_body_sid(s, p->body_sid);
3589
3590
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 97 times.
108 if (wrapping == ClipWrapped) {
3591 11 p->essence_offset = p->first_essence_klv.next_klv - p->first_essence_klv.length;
3592 11 p->essence_length = p->first_essence_klv.length;
3593 } else {
3594 97 p->essence_offset = p->first_essence_klv.offset;
3595
3596 /* essence container spans to the next partition */
3597
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 7 times.
97 if (x < mxf->partitions_count - 1)
3598 90 p->essence_length = mxf->partitions[x+1].pack_ofs - mxf->run_in - p->essence_offset;
3599
3600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
97 if (p->essence_length < 0) {
3601 /* next ThisPartition < essence_offset */
3602 p->essence_length = 0;
3603 av_log(mxf->fc, AV_LOG_ERROR,
3604 "partition %i: bad ThisPartition = %"PRIX64"\n",
3605 x+1, mxf->partitions[x+1].pack_ofs - mxf->run_in);
3606 }
3607 }
3608 }
3609 108 }
3610
3611 7945 static MXFIndexTable *mxf_find_index_table(MXFContext *mxf, int index_sid)
3612 {
3613 int i;
3614
1/2
✓ Branch 0 taken 7945 times.
✗ Branch 1 not taken.
7945 for (i = 0; i < mxf->nb_index_tables; i++)
3615
1/2
✓ Branch 0 taken 7945 times.
✗ Branch 1 not taken.
7945 if (mxf->index_tables[i].index_sid == index_sid)
3616 7945 return &mxf->index_tables[i];
3617 return NULL;
3618 }
3619
3620 /**
3621 * Deal with the case where for some audio atoms EditUnitByteCount is
3622 * very small (2, 4..). In those cases we should read more than one
3623 * sample per call to mxf_read_packet().
3624 */
3625 233 static void mxf_compute_edit_units_per_packet(MXFContext *mxf, AVStream *st)
3626 {
3627 233 MXFTrack *track = st->priv_data;
3628 MXFIndexTable *t;
3629
3630
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 221 times.
233 if (!track)
3631 12 return;
3632 221 track->edit_units_per_packet = 1;
3633
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 11 times.
221 if (track->wrapping != ClipWrapped)
3634 210 return;
3635
3636 11 t = mxf_find_index_table(mxf, track->index_sid);
3637
3638 /* expect PCM with exactly one index table segment and a small (< 32) EUBC */
3639
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
16 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
3640
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
10 !is_pcm(st->codecpar->codec_id) ||
3641 5 !t ||
3642
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 t->nb_segments != 1 ||
3643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 t->segments[0]->edit_unit_byte_count >= 32)
3644 6 return;
3645
3646 /* arbitrarily default to 48 kHz PAL audio frame size */
3647 /* TODO: We could compute this from the ratio between the audio
3648 * and video edit rates for 48 kHz NTSC we could use the
3649 * 1802-1802-1802-1802-1801 pattern. */
3650
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 track->edit_units_per_packet = FFMAX(1, track->edit_rate.num / track->edit_rate.den / 25);
3651 }
3652
3653 /**
3654 * Deal with the case where ClipWrapped essences does not have any IndexTableSegments.
3655 */
3656 233 static int mxf_handle_missing_index_segment(MXFContext *mxf, AVStream *st)
3657 {
3658 233 MXFTrack *track = st->priv_data;
3659 233 MXFIndexTableSegment *segment = NULL;
3660 233 MXFPartition *p = NULL;
3661 233 int essence_partition_count = 0;
3662 233 int edit_unit_byte_count = 0;
3663 int i, ret;
3664 233 MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[IndexTableSegment];
3665
3666
4/4
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 210 times.
✓ Branch 3 taken 11 times.
233 if (!track || track->wrapping != ClipWrapped)
3667 222 return 0;
3668
3669 /* check if track already has an IndexTableSegment */
3670
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 for (i = 0; i < mg->metadata_sets_count; i++) {
3671 9 MXFIndexTableSegment *s = (MXFIndexTableSegment*)mg->metadata_sets[i];
3672
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (s->body_sid == track->body_sid)
3673 9 return 0;
3674 }
3675
3676 /* find the essence partition */
3677
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (i = 0; i < mxf->partitions_count; i++) {
3678 /* BodySID == 0 -> no essence */
3679
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (mxf->partitions[i].body_sid != track->body_sid)
3680 4 continue;
3681
3682 2 p = &mxf->partitions[i];
3683 2 essence_partition_count++;
3684 }
3685
3686 /* only handle files with a single essence partition */
3687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (essence_partition_count != 1)
3688 return 0;
3689
3690
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && is_pcm(st->codecpar->codec_id)) {
3691 2 edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) *
3692 2 st->codecpar->ch_layout.nb_channels) >> 3;
3693 } else if (st->duration > 0 && p->first_essence_klv.length > 0 && p->first_essence_klv.length % st->duration == 0) {
3694 edit_unit_byte_count = p->first_essence_klv.length / st->duration;
3695 }
3696
3697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (edit_unit_byte_count <= 0)
3698 return 0;
3699
3700 2 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);
3701
3702
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!(segment = av_mallocz(sizeof(*segment))))
3703 return AVERROR(ENOMEM);
3704
3705
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = mxf_add_metadata_set(mxf, (MXFMetadataSet**)&segment, IndexTableSegment)))
3706 return ret;
3707
3708 /* Make sure we have nonzero unique index_sid, body_sid will be ok, because
3709 * using the same SID for index is forbidden in MXF. */
3710
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!track->index_sid)
3711 2 track->index_sid = track->body_sid;
3712
3713 /* stream will be treated as small EditUnitByteCount */
3714 2 segment->edit_unit_byte_count = edit_unit_byte_count;
3715 2 segment->index_start_position = 0;
3716 2 segment->index_duration = st->duration;
3717 2 segment->index_edit_rate = av_inv_q(st->time_base);
3718 2 segment->index_sid = track->index_sid;
3719 2 segment->body_sid = p->body_sid;
3720 2 return 0;
3721 }
3722
3723 108 static void mxf_read_random_index_pack(AVFormatContext *s)
3724 {
3725 108 MXFContext *mxf = s->priv_data;
3726 uint32_t length;
3727 int64_t file_size, max_rip_length, min_rip_length;
3728 KLVPacket klv;
3729
3730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
3731 return;
3732
3733 108 file_size = avio_size(s->pb);
3734
3735 /* S377m says to check the RIP length for "silly" values, without defining "silly".
3736 * The limit below assumes a file with nothing but partition packs and a RIP.
3737 * Before changing this, consider that a muxer may place each sample in its own partition.
3738 *
3739 * 105 is the size of the smallest possible PartitionPack
3740 * 12 is the size of each RIP entry
3741 * 28 is the size of the RIP header and footer, assuming an 8-byte BER
3742 */
3743 108 max_rip_length = ((file_size - mxf->run_in) / 105) * 12 + 28;
3744 108 max_rip_length = FFMIN(max_rip_length, INT_MAX); //2 GiB and up is also silly
3745
3746 /* We're only interested in RIPs with at least two entries.. */
3747 108 min_rip_length = 16+1+24+4;
3748
3749 /* See S377m section 11 */
3750 108 avio_seek(s->pb, file_size - 4, SEEK_SET);
3751 108 length = avio_rb32(s->pb);
3752
3753
4/4
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 98 times.
108 if (length < min_rip_length || length > max_rip_length)
3754 10 goto end;
3755 98 avio_seek(s->pb, file_size - length, SEEK_SET);
3756
1/2
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
98 if (klv_read_packet(mxf, &klv, s->pb) < 0 ||
3757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 !IS_KLV_KEY(klv.key, ff_mxf_random_index_pack_key))
3758 goto end;
3759
3/6
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 98 times.
98 if (klv.next_klv != file_size || klv.length <= 4 || (klv.length - 4) % 12) {
3760 av_log(s, AV_LOG_WARNING, "Invalid RIP KLV length\n");
3761 goto end;
3762 }
3763
3764 98 avio_skip(s->pb, klv.length - 12);
3765 98 mxf->footer_partition = avio_rb64(s->pb);
3766
3767 /* sanity check */
3768
1/2
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
98 if (mxf->run_in + mxf->footer_partition >= file_size) {
3769 av_log(s, AV_LOG_WARNING, "bad FooterPartition in RIP - ignoring\n");
3770 mxf->footer_partition = 0;
3771 }
3772
3773 98 end:
3774 108 avio_seek(s->pb, mxf->run_in, SEEK_SET);
3775 }
3776
3777 108 static int mxf_read_header(AVFormatContext *s)
3778 {
3779 108 MXFContext *mxf = s->priv_data;
3780 KLVPacket klv;
3781 108 int64_t essence_offset = 0;
3782 int ret;
3783 int64_t run_in;
3784
3785 108 mxf->last_forward_tell = INT64_MAX;
3786
3787
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 if (!mxf_read_sync(s->pb, mxf_header_partition_pack_key, 14)) {
3788 av_log(s, AV_LOG_ERROR, "could not find header partition pack key\n");
3789 return AVERROR_INVALIDDATA;
3790 }
3791 108 avio_seek(s->pb, -14, SEEK_CUR);
3792 108 mxf->fc = s;
3793 108 run_in = avio_tell(s->pb);
3794
2/4
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
108 if (run_in < 0 || run_in > RUN_IN_MAX)
3795 return AVERROR_INVALIDDATA;
3796 108 mxf->run_in = run_in;
3797
3798 108 mxf_read_random_index_pack(s);
3799
3800
1/2
✓ Branch 1 taken 8915 times.
✗ Branch 2 not taken.
8915 while (!avio_feof(s->pb)) {
3801 size_t x;
3802
3803 8915 ret = klv_read_packet(mxf, &klv, s->pb);
3804
4/4
✓ Branch 0 taken 8911 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 98 times.
✓ Branch 3 taken 8813 times.
8915 if (ret < 0 || IS_KLV_KEY(klv.key, ff_mxf_random_index_pack_key)) {
3805
3/4
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 98 times.
102 if (ret >= 0 && avio_size(s->pb) > klv.next_klv)
3806 av_log(s, AV_LOG_WARNING, "data after the RandomIndexPack, assuming end of file\n");
3807 /* EOF - seek to previous partition or stop */
3808
2/2
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 4 times.
102 if(mxf_parse_handle_partition_or_eof(mxf) <= 0)
3809 98 break;
3810 else
3811 4 continue;
3812 }
3813
3814 PRINT_KEY(s, "read header", klv.key);
3815 8813 av_log(s, AV_LOG_TRACE, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset);
3816
1/2
✓ Branch 1 taken 8813 times.
✗ Branch 2 not taken.
8813 if (mxf_match_uid(klv.key, mxf_encrypted_triplet_key, sizeof(mxf_encrypted_triplet_key)) ||
3817
2/2
✓ Branch 0 taken 8798 times.
✓ Branch 1 taken 15 times.
8813 IS_KLV_KEY(klv.key, mxf_essence_element_key) ||
3818
1/2
✓ Branch 0 taken 8798 times.
✗ Branch 1 not taken.
8798 IS_KLV_KEY(klv.key, mxf_canopus_essence_element_key) ||
3819
2/2
✓ Branch 0 taken 8797 times.
✓ Branch 1 taken 1 times.
8798 IS_KLV_KEY(klv.key, mxf_avid_essence_element_key) ||
3820
2/2
✓ Branch 0 taken 8706 times.
✓ Branch 1 taken 91 times.
8797 IS_KLV_KEY(klv.key, mxf_system_item_key_cp) ||
3821
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8705 times.
8706 IS_KLV_KEY(klv.key, mxf_system_item_key_gc)) {
3822
3823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!mxf->current_partition) {
3824 av_log(mxf->fc, AV_LOG_ERROR, "found essence prior to first PartitionPack\n");
3825 return AVERROR_INVALIDDATA;
3826 }
3827
3828
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 if (!mxf->current_partition->first_essence_klv.offset)
3829 108 mxf->current_partition->first_essence_klv = klv;
3830
3831
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 if (!essence_offset)
3832 108 essence_offset = klv.offset;
3833
3834 /* seek to footer, previous partition or stop */
3835
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 102 times.
108 if (mxf_parse_handle_essence(mxf) <= 0)
3836 6 break;
3837 102 continue;
3838
4/4
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 8435 times.
✓ Branch 3 taken 61 times.
✓ Branch 4 taken 209 times.
8705 } else if (mxf_is_partition_pack_key(klv.key) && mxf->current_partition) {
3839 /* next partition pack - keep going, seek to previous partition or stop */
3840
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 57 times.
61 if(mxf_parse_handle_partition_or_eof(mxf) <= 0)
3841 4 break;
3842
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 else if (mxf->parsing_backward)
3843 continue;
3844 /* we're still parsing forward. proceed to parsing this partition pack */
3845 }
3846
3847
2/2
✓ Branch 0 taken 300423 times.
✓ Branch 1 taken 4572 times.
304995 for (x = 0; x < FF_ARRAY_ELEMS(mxf_metadata_read_table); x++) {
3848 300423 const MXFMetadataReadTableEntry *metadata = &mxf_metadata_read_table[x];
3849
2/2
✓ Branch 0 taken 4129 times.
✓ Branch 1 taken 296294 times.
300423 if (IS_KLV_KEY(klv.key, metadata->key)) {
3850
2/2
✓ Branch 0 taken 3653 times.
✓ Branch 1 taken 476 times.
4129 if (metadata->read) {
3851
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3653 times.
3653 if ((ret = mxf_parse_klv(mxf, klv, metadata->read, metadata->ctx_size, metadata->type)) < 0)
3852 return ret;
3853 } else {
3854 476 avio_skip(s->pb, klv.length);
3855 }
3856 4129 break;
3857 }
3858 }
3859
2/2
✓ Branch 0 taken 4572 times.
✓ Branch 1 taken 4129 times.
8701 if (x >= FF_ARRAY_ELEMS(mxf_metadata_read_table)) {
3860 4572 av_log(s, AV_LOG_VERBOSE, "Dark key " PRIxUID "\n",
3861 4572 UID_ARG(klv.key));
3862 4572 avio_skip(s->pb, klv.length);
3863 }
3864 }
3865 /* FIXME avoid seek */
3866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (!essence_offset) {
3867 av_log(s, AV_LOG_ERROR, "no essence\n");
3868 return AVERROR_INVALIDDATA;
3869 }
3870 108 avio_seek(s->pb, essence_offset, SEEK_SET);
3871
3872 /* we need to do this before computing the index tables
3873 * to be able to fill in zero IndexDurations with st->duration */
3874
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 if ((ret = mxf_parse_structural_metadata(mxf)) < 0)
3875 return ret;
3876
3877
2/2
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 108 times.
341 for (int i = 0; i < s->nb_streams; i++)
3878 233 mxf_handle_missing_index_segment(mxf, s->streams[i]);
3879
3880
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 if ((ret = mxf_compute_index_tables(mxf)) < 0)
3881 return ret;
3882
3883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
108 if (mxf->nb_index_tables > 1) {
3884 /* TODO: look up which IndexSID to use via EssenceContainerData */
3885 av_log(mxf->fc, AV_LOG_INFO, "got %i index tables - only the first one (IndexSID %i) will be used\n",
3886 mxf->nb_index_tables, mxf->index_tables[0].index_sid);
3887
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
108 } else if (mxf->nb_index_tables == 0 && mxf->op == OPAtom && (s->error_recognition & AV_EF_EXPLODE)) {
3888 av_log(mxf->fc, AV_LOG_ERROR, "cannot demux OPAtom without an index\n");
3889 return AVERROR_INVALIDDATA;
3890 }
3891
3892 108 mxf_compute_essence_containers(s);
3893
3894
2/2
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 108 times.
341 for (int i = 0; i < s->nb_streams; i++)
3895 233 mxf_compute_edit_units_per_packet(mxf, s->streams[i]);
3896
3897 108 return 0;
3898 }
3899
3900 /* Get the edit unit of the next packet from current_offset in a track. The returned edit unit can be original_duration as well! */
3901 155 static int mxf_get_next_track_edit_unit(MXFContext *mxf, MXFTrack *track, int64_t current_offset, int64_t *edit_unit_out)
3902 {
3903 int64_t a, b, m, offset;
3904 155 MXFIndexTable *t = mxf_find_index_table(mxf, track->index_sid);
3905
3906
2/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 155 times.
155 if (!t || track->original_duration <= 0)
3907 return -1;
3908
3909 155 a = -1;
3910 155 b = track->original_duration;
3911
2/2
✓ Branch 0 taken 719 times.
✓ Branch 1 taken 155 times.
874 while (b - 1 > a) {
3912 719 m = (a + (uint64_t)b) >> 1;
3913
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 719 times.
719 if (mxf_edit_unit_absolute_offset(mxf, t, m, track->edit_rate, NULL, &offset, NULL, 0) < 0)
3914 return -1;
3915
2/2
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 375 times.
719 if (offset < current_offset)
3916 344 a = m;
3917 else
3918 375 b = m;
3919 }
3920
3921 155 *edit_unit_out = b;
3922
3923 155 return 0;
3924 }
3925
3926 362 static int64_t mxf_compute_sample_count(MXFContext *mxf, AVStream *st,
3927 int64_t edit_unit)
3928 {
3929 362 MXFTrack *track = st->priv_data;
3930 362 AVRational time_base = av_inv_q(track->edit_rate);
3931 362 AVRational sample_rate = av_inv_q(st->time_base);
3932
3933 // For non-audio sample_count equals current edit unit
3934
2/2
✓ Branch 0 taken 181 times.
✓ Branch 1 taken 181 times.
362 if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
3935 181 return edit_unit;
3936
3937
1/2
✓ Branch 0 taken 181 times.
✗ Branch 1 not taken.
181 if ((sample_rate.num / sample_rate.den) == 48000) {
3938 181 return av_rescale_q(edit_unit, sample_rate, track->edit_rate);
3939 } else {
3940 int64_t remainder = (sample_rate.num * (int64_t) time_base.num) %
3941 ( time_base.den * (int64_t)sample_rate.den);
3942 if (remainder)
3943 av_log(mxf->fc, AV_LOG_WARNING,
3944 "seeking detected on stream #%d with time base (%d/%d) and "
3945 "sample rate (%d/%d), audio pts won't be accurate.\n",
3946 st->index, time_base.num, time_base.den,
3947 sample_rate.num, sample_rate.den);
3948 return av_rescale_q(edit_unit, sample_rate, track->edit_rate);
3949 }
3950 }
3951
3952 /**
3953 * Make sure track->sample_count is correct based on what offset we're currently at.
3954 * Also determine the next edit unit (or packet) offset.
3955 * @return next_ofs if OK, <0 on error
3956 */
3957 5177 static int64_t mxf_set_current_edit_unit(MXFContext *mxf, AVStream *st, int64_t current_offset, int resync)
3958 {
3959 5177 int64_t next_ofs = -1;
3960 5177 MXFTrack *track = st->priv_data;
3961 5177 int64_t edit_unit = av_rescale_q(track->sample_count, st->time_base, av_inv_q(track->edit_rate));
3962 int64_t new_edit_unit;
3963 5177 MXFIndexTable *t = mxf_find_index_table(mxf, track->index_sid);
3964
3965
4/6
✓ Branch 0 taken 5177 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5170 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5170 times.
5177 if (!t || track->wrapping == UnknownWrapped || edit_unit > INT64_MAX - track->edit_units_per_packet)
3966 7 return -1;
3967
3968
2/2
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 4871 times.
5170 if (mxf_edit_unit_absolute_offset(mxf, t, edit_unit + track->edit_units_per_packet, track->edit_rate, NULL, &next_ofs, NULL, 0) < 0 &&
3969
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 251 times.
299 (next_ofs = mxf_essence_container_end(mxf, t->body_sid)) <= 0) {
3970 48 av_log(mxf->fc, AV_LOG_ERROR, "unable to compute the size of the last packet\n");
3971 48 return -1;
3972 }
3973
3974 /* check if the next edit unit offset (next_ofs) starts ahead of current_offset */
3975
1/2
✓ Branch 0 taken 5122 times.
✗ Branch 1 not taken.
5122 if (next_ofs > current_offset)
3976 5122 return next_ofs;
3977
3978 if (!resync) {
3979 av_log(mxf->fc, AV_LOG_ERROR, "cannot find current edit unit for stream %d, invalid index?\n", st->index);
3980 return -1;
3981 }
3982
3983 if (mxf_get_next_track_edit_unit(mxf, track, current_offset + 1, &new_edit_unit) < 0 || new_edit_unit <= 0) {
3984 av_log(mxf->fc, AV_LOG_ERROR, "failed to find next track edit unit in stream %d\n", st->index);
3985 return -1;
3986 }
3987
3988 new_edit_unit--;
3989 track->sample_count = mxf_compute_sample_count(mxf, st, new_edit_unit);
3990 av_log(mxf->fc, AV_LOG_WARNING, "edit unit sync lost on stream %d, jumping from %"PRId64" to %"PRId64"\n", st->index, edit_unit, new_edit_unit);
3991
3992 return mxf_set_current_edit_unit(mxf, st, current_offset, 0);
3993 }
3994
3995 2569 static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par,
3996 AVPacket *pkt)
3997 {
3998 2569 AVStream *st = mxf->fc->streams[pkt->stream_index];
3999 2569 MXFTrack *track = st->priv_data;
4000 2569 int64_t bits_per_sample = par->bits_per_coded_sample;
4001
4002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2569 times.
2569 if (!bits_per_sample)
4003 bits_per_sample = av_get_bits_per_sample(par->codec_id);
4004
4005 2569 pkt->pts = track->sample_count;
4006
4007
2/4
✓ Branch 0 taken 2569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2569 times.
✗ Branch 3 not taken.
2569 if (par->ch_layout.nb_channels <= 0 ||
4008 2569 bits_per_sample <= 0 ||
4009
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2569 times.
2569 par->ch_layout.nb_channels * (int64_t)bits_per_sample < 8)
4010 track->sample_count = mxf_compute_sample_count(mxf, st, av_rescale_q(track->sample_count, st->time_base, av_inv_q(track->edit_rate)) + 1);
4011 else
4012 2569 track->sample_count += pkt->size / (par->ch_layout.nb_channels * (int64_t)bits_per_sample / 8);
4013
4014 2569 return 0;
4015 }
4016
4017 5177 static int mxf_set_pts(MXFContext *mxf, AVStream *st, AVPacket *pkt)
4018 {
4019 5177 AVCodecParameters *par = st->codecpar;
4020 5177 MXFTrack *track = st->priv_data;
4021
4022
2/2
✓ Branch 0 taken 2602 times.
✓ Branch 1 taken 2575 times.
5177 if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
4023 /* see if we have an index table to derive timestamps from */
4024 2602 MXFIndexTable *t = mxf_find_index_table(mxf, track->index_sid);
4025
4026
3/4
✓ Branch 0 taken 2602 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1279 times.
✓ Branch 3 taken 1323 times.
2602 if (t && track->sample_count < t->nb_ptses) {
4027 1279 pkt->dts = track->sample_count + t->first_dts;
4028 1279 pkt->pts = t->ptses[track->sample_count];
4029
2/2
✓ Branch 0 taken 1025 times.
✓ Branch 1 taken 298 times.
1323 } else if (track->intra_only) {
4030 /* intra-only -> PTS = EditUnit.
4031 * let utils.c figure out DTS since it can be < PTS if low_delay = 0 (Sony IMX30) */
4032 1025 pkt->pts = track->sample_count;
4033 }
4034 2602 track->sample_count++;
4035
2/2
✓ Branch 0 taken 2569 times.
✓ Branch 1 taken 6 times.
2575 } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
4036 2569 int ret = mxf_set_audio_pts(mxf, par, pkt);
4037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2569 times.
2569 if (ret < 0)
4038 return ret;
4039
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (track) {
4040 6 pkt->dts = pkt->pts = track->sample_count;
4041 6 pkt->duration = 1;
4042 6 track->sample_count++;
4043 }
4044 5177 return 0;
4045 }
4046
4047 5307 static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
4048 {
4049 KLVPacket klv;
4050 5307 MXFContext *mxf = s->priv_data;
4051 int ret;
4052
4053 12856 while (1) {
4054 int64_t max_data_size;
4055 18163 int64_t pos = avio_tell(s->pb);
4056
4057
3/4
✓ Branch 0 taken 18163 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18028 times.
✓ Branch 3 taken 135 times.
36061 if (pos < mxf->current_klv_data.next_klv - mxf->current_klv_data.length || pos >= mxf->current_klv_data.next_klv) {
4058 18028 mxf->current_klv_data = (KLVPacket){{0}};
4059 18028 ret = klv_read_packet(mxf, &klv, s->pb);
4060
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 17898 times.
18028 if (ret < 0)
4061 130 break;
4062 // klv.key[0..3] == mxf_klv_key from here forward
4063 17898 max_data_size = klv.length;
4064 17898 pos = klv.next_klv - klv.length;
4065 PRINT_KEY(s, "read packet", klv.key);
4066 17898 av_log(s, AV_LOG_TRACE, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset);
4067
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17898 times.
17898 if (mxf_match_uid(klv.key, mxf_encrypted_triplet_key, sizeof(mxf_encrypted_triplet_key))) {
4068 ret = mxf_decrypt_triplet(s, pkt, &klv);
4069 if (ret < 0) {
4070 av_log(s, AV_LOG_ERROR, "invalid encoded triplet\n");
4071 return ret;
4072 }
4073 return 0;
4074 }
4075 } else {
4076 135 klv = mxf->current_klv_data;
4077 135 max_data_size = klv.next_klv - pos;
4078 }
4079
2/2
✓ Branch 0 taken 12833 times.
✓ Branch 1 taken 5200 times.
18033 if (IS_KLV_KEY(klv.key, mxf_essence_element_key) ||
4080
1/2
✓ Branch 0 taken 12833 times.
✗ Branch 1 not taken.
12833 IS_KLV_KEY(klv.key, mxf_canopus_essence_element_key) ||
4081
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12832 times.
12833 IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) {
4082 5201 int body_sid = find_body_sid_by_absolute_offset(mxf, klv.offset);
4083 5201 int index = mxf_get_stream_index(s, &klv, body_sid);
4084 int64_t next_ofs;
4085 AVStream *st;
4086 MXFTrack *track;
4087
4088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5201 times.
5201 if (index < 0) {
4089 av_log(s, AV_LOG_ERROR,
4090 "error getting stream index %"PRIu32"\n",
4091 AV_RB32(klv.key + 12));
4092 goto skip;
4093 }
4094
4095 5201 st = s->streams[index];
4096 5201 track = st->priv_data;
4097
4098
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 5177 times.
5201 if (s->streams[index]->discard == AVDISCARD_ALL)
4099 24 goto skip;
4100
4101 5177 next_ofs = mxf_set_current_edit_unit(mxf, st, pos, 1);
4102
4103
2/2
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 5026 times.
5177 if (track->wrapping != FrameWrapped) {
4104 int64_t size;
4105
4106
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 144 times.
151 if (next_ofs <= 0) {
4107 // If we have no way to packetize the data, then return it in chunks...
4108
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (klv.next_klv - klv.length == pos && max_data_size > MXF_MAX_CHUNK_SIZE) {
4109 ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;
4110 avpriv_request_sample(s, "Huge KLV without proper index in non-frame wrapped essence");
4111 }
4112 7 size = FFMIN(max_data_size, MXF_MAX_CHUNK_SIZE);
4113 } else {
4114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if ((size = next_ofs - pos) <= 0) {
4115 av_log(s, AV_LOG_ERROR, "bad size: %"PRId64"\n", size);
4116 mxf->current_klv_data = (KLVPacket){{0}};
4117 return AVERROR_INVALIDDATA;
4118 }
4119 // We must not overread, because the next edit unit might be in another KLV
4120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if (size > max_data_size)
4121 size = max_data_size;
4122 }
4123
4124 151 mxf->current_klv_data = klv;
4125 151 klv.offset = pos;
4126 151 klv.length = size;
4127 151 klv.next_klv = klv.offset + klv.length;
4128 }
4129
4130 /* check for 8 channels AES3 element */
4131
4/6
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 4253 times.
✓ Branch 2 taken 924 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 924 times.
✗ Branch 5 not taken.
5177 if (klv.key[12] == 0x06 && klv.key[13] == 0x01 && klv.key[14] == 0x10) {
4132 924 ret = mxf_get_d10_aes3_packet(s->pb, s->streams[index],
4133 924 pkt, klv.length);
4134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 924 times.
924 if (ret < 0) {
4135 av_log(s, AV_LOG_ERROR, "error reading D-10 aes3 frame\n");
4136 mxf->current_klv_data = (KLVPacket){{0}};
4137 return ret;
4138 }
4139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4253 times.
4253 } else if (mxf->eia608_extract &&
4140 s->streams[index]->codecpar->codec_id == AV_CODEC_ID_EIA_608) {
4141 ret = mxf_get_eia608_packet(s, s->streams[index], pkt, klv.length);
4142 if (ret < 0) {
4143 mxf->current_klv_data = (KLVPacket){{0}};
4144 return ret;
4145 }
4146 } else {
4147 4253 ret = av_get_packet(s->pb, pkt, klv.length);
4148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4253 times.
4253 if (ret < 0) {
4149 mxf->current_klv_data = (KLVPacket){{0}};
4150 return ret;
4151 }
4152 }
4153 5177 pkt->stream_index = index;
4154 5177 pkt->pos = klv.offset;
4155
4156 5177 ret = mxf_set_pts(mxf, st, pkt);
4157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5177 times.
5177 if (ret < 0) {
4158 mxf->current_klv_data = (KLVPacket){{0}};
4159 return ret;
4160 }
4161
4162 /* seek for truncated packets */
4163 5177 avio_seek(s->pb, klv.next_klv, SEEK_SET);
4164
4165 5177 return 0;
4166 } else {
4167 12832 skip:
4168 12856 avio_skip(s->pb, max_data_size);
4169 12856 mxf->current_klv_data = (KLVPacket){{0}};
4170 }
4171 }
4172
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 130 times.
130 return avio_feof(s->pb) ? AVERROR_EOF : ret;
4173 }
4174
4175 108 static int mxf_read_close(AVFormatContext *s)
4176 {
4177 108 MXFContext *mxf = s->priv_data;
4178
4179 108 av_freep(&mxf->packages_refs);
4180 108 av_freep(&mxf->essence_container_data_refs);
4181
4182
2/2
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 108 times.
341 for (int i = 0; i < s->nb_streams; i++)
4183 233 s->streams[i]->priv_data = NULL;
4184
4185
2/2
✓ Branch 0 taken 2808 times.
✓ Branch 1 taken 108 times.
2916 for (int type = 0; type < FF_ARRAY_ELEMS(mxf->metadata_set_groups); type++) {
4186 2808 MXFMetadataSetGroup *mg = &mxf->metadata_set_groups[type];
4187
2/2
✓ Branch 0 taken 2953 times.
✓ Branch 1 taken 2808 times.
5761 for (int i = 0; i < mg->metadata_sets_count; i++)
4188 2953 mxf_free_metadataset(mg->metadata_sets + i, type);
4189 2808 mg->metadata_sets_count = 0;
4190 2808 av_freep(&mg->metadata_sets);
4191 }
4192 108 av_freep(&mxf->partitions);
4193 108 av_freep(&mxf->aesc);
4194 108 av_freep(&mxf->local_tags);
4195
4196
1/2
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
108 if (mxf->index_tables) {
4197
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 108 times.
216 for (int i = 0; i < mxf->nb_index_tables; i++) {
4198 108 av_freep(&mxf->index_tables[i].segments);
4199 108 av_freep(&mxf->index_tables[i].ptses);
4200 108 av_freep(&mxf->index_tables[i].fake_index);
4201 108 av_freep(&mxf->index_tables[i].offsets);
4202 }
4203 }
4204 108 av_freep(&mxf->index_tables);
4205
4206 108 return 0;
4207 }
4208
4209 7260 static int mxf_probe(const AVProbeData *p) {
4210 7260 const uint8_t *bufp = p->buf;
4211
2/2
✓ Branch 0 taken 6245 times.
✓ Branch 1 taken 1015 times.
7260 const uint8_t *end = p->buf + FFMIN(p->buf_size, RUN_IN_MAX + 1 + sizeof(mxf_header_partition_pack_key));
4212
4213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7260 times.
7260 if (p->buf_size < sizeof(mxf_header_partition_pack_key))
4214 return 0;
4215
4216 /* Must skip Run-In Sequence and search for MXF header partition pack key SMPTE 377M 5.5 */
4217 7260 end -= sizeof(mxf_header_partition_pack_key);
4218
4219
2/2
✓ Branch 0 taken 13504359 times.
✓ Branch 1 taken 7159 times.
13511518 for (; bufp < end;) {
4220
2/2
✓ Branch 0 taken 570496 times.
✓ Branch 1 taken 12933863 times.
13504359 if (!((bufp[13] - 1) & 0xF2)){
4221
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 570395 times.
570496 if (AV_RN32(bufp ) == AV_RN32(mxf_header_partition_pack_key ) &&
4222
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 AV_RN32(bufp+ 4) == AV_RN32(mxf_header_partition_pack_key+ 4) &&
4223
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 AV_RN32(bufp+ 8) == AV_RN32(mxf_header_partition_pack_key+ 8) &&
4224
1/2
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
101 AV_RN16(bufp+12) == AV_RN16(mxf_header_partition_pack_key+12))
4225
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1 times.
101 return bufp == p->buf ? AVPROBE_SCORE_MAX : AVPROBE_SCORE_MAX - 1;
4226 570395 bufp ++;
4227 } else
4228 12933863 bufp += 10;
4229 }
4230
4231 7159 return 0;
4232 }
4233
4234 /* rudimentary byte seek */
4235 /* XXX: use MXF Index */
4236 212 static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
4237 {
4238 212 AVStream *st = s->streams[stream_index];
4239 int64_t seconds;
4240 212 MXFContext* mxf = s->priv_data;
4241 int64_t seekpos;
4242 int ret;
4243 MXFIndexTable *t;
4244 212 MXFTrack *source_track = st->priv_data;
4245
4246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 if (!source_track)
4247 return 0;
4248
4249 /* if audio then truncate sample_time to EditRate */
4250
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 154 times.
212 if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
4251 58 sample_time = av_rescale_q(sample_time, st->time_base,
4252 av_inv_q(source_track->edit_rate));
4253
4254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 if (mxf->nb_index_tables <= 0) {
4255 if (!s->bit_rate)
4256 return AVERROR_INVALIDDATA;
4257 if (sample_time < 0)
4258 sample_time = 0;
4259 seconds = av_rescale(sample_time, st->time_base.num, st->time_base.den);
4260
4261 seekpos = avio_seek(s->pb, (s->bit_rate * seconds) >> 3, SEEK_SET);
4262 if (seekpos < 0)
4263 return seekpos;
4264
4265 avpriv_update_cur_dts(s, st, sample_time);
4266 mxf->current_klv_data = (KLVPacket){{0}};
4267 } else {
4268 MXFPartition *partition;
4269
4270 212 t = &mxf->index_tables[0];
4271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 if (t->index_sid != source_track->index_sid) {
4272 int i;
4273 /* If the first index table does not belong to the stream, then find a stream which does belong to the index table */
4274 for (i = 0; i < s->nb_streams; i++) {
4275 MXFTrack *new_source_track = s->streams[i]->priv_data;
4276 if (new_source_track && new_source_track->index_sid == t->index_sid) {
4277 sample_time = av_rescale_q(sample_time, new_source_track->edit_rate, source_track->edit_rate);
4278 source_track = new_source_track;
4279 st = s->streams[i];
4280 break;
4281 }
4282 }
4283 if (i == s->nb_streams)
4284 5 return AVERROR_INVALIDDATA;
4285 }
4286
4287 /* clamp above zero, else ff_index_search_timestamp() returns negative
4288 * this also means we allow seeking before the start */
4289 212 sample_time = FFMAX(sample_time, 0);
4290
4291
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 158 times.
212 if (t->fake_index) {
4292 /* The first frames may not be keyframes in presentation order, so
4293 * we have to advance the target to be able to find the first
4294 * keyframe backwards... */
4295
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
54 if (!(flags & AVSEEK_FLAG_ANY) &&
4296
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 13 times.
54 (flags & AVSEEK_FLAG_BACKWARD) &&
4297
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 t->ptses[0] != AV_NOPTS_VALUE &&
4298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 sample_time < t->ptses[0] &&
4299 (t->fake_index[t->ptses[0]].flags & AVINDEX_KEYFRAME))
4300 sample_time = t->ptses[0];
4301
4302 /* behave as if we have a proper index */
4303
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 49 times.
54 if ((sample_time = ff_index_search_timestamp(t->fake_index, t->nb_ptses, sample_time, flags)) < 0)
4304 5 return sample_time;
4305 /* get the stored order index from the display order index */
4306 49 sample_time += t->offsets[sample_time];
4307 } else {
4308 /* no IndexEntryArray (one or more CBR segments)
4309 * make sure we don't seek past the end */
4310
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 98 times.
158 sample_time = FFMIN(sample_time, source_track->original_duration - 1);
4311 }
4312
4313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
207 if (source_track->wrapping == UnknownWrapped)
4314 av_log(mxf->fc, AV_LOG_WARNING, "attempted seek in an UnknownWrapped essence\n");
4315
4316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 207 times.
207 if ((ret = mxf_edit_unit_absolute_offset(mxf, t, sample_time, source_track->edit_rate, &sample_time, &seekpos, &partition, 1)) < 0)
4317 return ret;
4318
4319 207 avpriv_update_cur_dts(s, st, sample_time);
4320
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 155 times.
207 if (source_track->wrapping == ClipWrapped) {
4321 52 KLVPacket klv = partition->first_essence_klv;
4322
2/4
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 52 times.
52 if (seekpos < klv.next_klv - klv.length || seekpos >= klv.next_klv) {
4323 av_log(mxf->fc, AV_LOG_ERROR, "attempted seek out of clip wrapped KLV\n");
4324 return AVERROR_INVALIDDATA;
4325 }
4326 52 mxf->current_klv_data = klv;
4327 } else {
4328 155 mxf->current_klv_data = (KLVPacket){{0}};
4329 }
4330 207 avio_seek(s->pb, seekpos, SEEK_SET);
4331 }
4332
4333 // Update all tracks sample count
4334
2/2
✓ Branch 0 taken 362 times.
✓ Branch 1 taken 207 times.
569 for (int i = 0; i < s->nb_streams; i++) {
4335 362 AVStream *cur_st = s->streams[i];
4336 362 MXFTrack *cur_track = cur_st->priv_data;
4337
1/2
✓ Branch 0 taken 362 times.
✗ Branch 1 not taken.
362 if (cur_track) {
4338 362 int64_t track_edit_unit = sample_time;
4339
2/2
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 207 times.
362 if (st != cur_st)
4340 155 mxf_get_next_track_edit_unit(mxf, cur_track, seekpos, &track_edit_unit);
4341 362 cur_track->sample_count = mxf_compute_sample_count(mxf, cur_st, track_edit_unit);
4342 }
4343 }
4344 207 return 0;
4345 }
4346
4347 static const AVOption options[] = {
4348 { "eia608_extract", "extract eia 608 captions from s436m track",
4349 offsetof(MXFContext, eia608_extract), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1,
4350 AV_OPT_FLAG_DECODING_PARAM },
4351 { NULL },
4352 };
4353
4354 static const AVClass demuxer_class = {
4355 .class_name = "mxf",
4356 .item_name = av_default_item_name,
4357 .option = options,
4358 .version = LIBAVUTIL_VERSION_INT,
4359 .category = AV_CLASS_CATEGORY_DEMUXER,
4360 };
4361
4362 const FFInputFormat ff_mxf_demuxer = {
4363 .p.name = "mxf",
4364 .p.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
4365 .p.flags = AVFMT_SEEK_TO_PTS | AVFMT_NOGENSEARCH,
4366 .p.priv_class = &demuxer_class,
4367 .priv_data_size = sizeof(MXFContext),
4368 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
4369 .read_probe = mxf_probe,
4370 .read_header = mxf_read_header,
4371 .read_packet = mxf_read_packet,
4372 .read_close = mxf_read_close,
4373 .read_seek = mxf_read_seek,
4374 };
4375