FFmpeg coverage


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