FFmpeg
Loading...
Searching...
No Matches
imfdec.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/*
20 *
21 * Copyright (c) Sandflow Consulting LLC
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions are met:
25 *
26 * * Redistributions of source code must retain the above copyright notice, this
27 * list of conditions and the following disclaimer.
28 * * Redistributions in binary form must reproduce the above copyright notice,
29 * this list of conditions and the following disclaimer in the documentation
30 * and/or other materials provided with the distribution.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGE.
43 */
44
45/**
46 * Demuxes an IMF Composition
47 *
48 * References
49 * OV 2067-0:2018 - SMPTE Overview Document - Interoperable Master Format
50 * ST 2067-2:2020 - SMPTE Standard - Interoperable Master Format — Core Constraints
51 * ST 2067-3:2020 - SMPTE Standard - Interoperable Master Format — Composition Playlist
52 * ST 2067-5:2020 - SMPTE Standard - Interoperable Master Format — Essence Component
53 * ST 2067-20:2016 - SMPTE Standard - Interoperable Master Format — Application #2
54 * ST 2067-21:2020 - SMPTE Standard - Interoperable Master Format — Application #2 Extended
55 * ST 2067-102:2017 - SMPTE Standard - Interoperable Master Format — Common Image Pixel Color Schemes
56 * ST 429-9:2007 - SMPTE Standard - D-Cinema Packaging — Asset Mapping and File Segmentation
57 *
58 * @author Marc-Antoine Arnaud
59 * @author Valentin Noel
60 * @author Nicholas Vanderzwet
61 * @file
62 * @ingroup lavu_imf
63 */
64
65#include "avio_internal.h"
66#include "demux.h"
67#include "imf.h"
68#include "internal.h"
69#include "libavcodec/packet.h"
70#include "libavutil/avstring.h"
71#include "libavutil/bprint.h"
73#include "libavutil/mem.h"
74#include "libavutil/opt.h"
75#include <inttypes.h>
76#include <libxml/parser.h>
77
78#define AVRATIONAL_FORMAT "%d/%d"
79#define AVRATIONAL_ARG(rational) rational.num, rational.den
80
81/**
82 * IMF Asset locator
83 */
88
89/**
90 * IMF Asset locator map
91 * Results from the parsing of one or more ASSETMAP XML files
92 */
97
99 IMFAssetLocator *locator; /**< Location of the resource */
100 FFIMFTrackFileResource *resource; /**< Underlying IMF CPL resource */
101 AVFormatContext *ctx; /**< Context associated with the resource */
102 AVRational start_time; /**< inclusive start time of the resource on the CPL timeline (s) */
103 AVRational end_time; /**< exclusive end time of the resource on the CPL timeline (s) */
104 AVRational ts_offset; /**< start_time minus the entry point into the resource (s) */
106
108 int32_t index; /**< Track index in playlist */
109 AVRational current_timestamp; /**< Current temporal position */
110 AVRational duration; /**< Overall duration */
111 uint32_t resource_count; /**< Number of resources (<= INT32_MAX) */
112 unsigned int resources_alloc_sz; /**< Size of the buffer holding the resource */
113 IMFVirtualTrackResourcePlaybackCtx *resources; /**< Buffer holding the resources */
114 int32_t current_resource_index; /**< Index of the current resource in resources,
115 or < 0 if a current resource has yet to be selected */
117
129
130static int imf_uri_is_url(const char *string)
131{
132 return strstr(string, "://") != NULL;
133}
134
135static int imf_uri_is_unix_abs_path(const char *string)
136{
137 return string[0] == '/';
138}
139
140static int imf_uri_is_dos_abs_path(const char *string)
141{
142 /* Absolute path case: `C:\path\to\somewhere` */
143 if (string[1] == ':' && string[2] == '\\')
144 return 1;
145
146 /* Absolute path case: `C:/path/to/somewhere` */
147 if (string[1] == ':' && string[2] == '/')
148 return 1;
149
150 /* Network path case: `\\path\to\somewhere` */
151 if (string[0] == '\\' && string[1] == '\\')
152 return 1;
153
154 return 0;
155}
156
157static int imf_time_to_ts(int64_t *ts, AVRational t, AVRational time_base)
158{
159 int dst_num;
160 int dst_den;
162
163 r = av_div_q(t, time_base);
164
165 if ((av_reduce(&dst_num, &dst_den, r.num, r.den, INT64_MAX) != 1))
166 return 1;
167
168 if (dst_den != 1)
169 return 1;
170
171 *ts = dst_num;
172
173 return 0;
174}
175
176/**
177 * Parse a ASSETMAP XML file to extract the UUID-URI mapping of assets.
178 * @param s the current format context, if any (can be NULL).
179 * @param doc the XML document to be parsed.
180 * @param asset_map pointer on the IMFAssetLocatorMap to fill.
181 * @param base_url the url of the asset map XML file, if any (can be NULL).
182 * @return a negative value in case of error, 0 otherwise.
183 */
185 xmlDocPtr doc,
186 IMFAssetLocatorMap *asset_map,
187 const char *base_url)
188{
189 xmlNodePtr asset_map_element = NULL;
190 xmlNodePtr node = NULL;
191 xmlNodePtr asset_element = NULL;
192 unsigned long elem_count;
193 char *uri;
194 int ret = 0;
195 IMFAssetLocator *asset = NULL;
196 void *tmp;
197
198 asset_map_element = xmlDocGetRootElement(doc);
199
200 if (!asset_map_element) {
201 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing root node\n");
202 return AVERROR_INVALIDDATA;
203 }
204
205 if (asset_map_element->type != XML_ELEMENT_NODE || av_strcasecmp(asset_map_element->name, "AssetMap")) {
206 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - wrong root node name[%s] type[%d]\n",
207 asset_map_element->name, (int)asset_map_element->type);
208 return AVERROR_INVALIDDATA;
209 }
210
211 /* parse asset locators */
212 if (!(node = ff_imf_xml_get_child_element_by_name(asset_map_element, "AssetList"))) {
213 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing AssetList node\n");
214 return AVERROR_INVALIDDATA;
215 }
216 elem_count = xmlChildElementCount(node);
217 if (elem_count > UINT32_MAX
218 || asset_map->asset_count > UINT32_MAX - elem_count)
219 return AVERROR(ENOMEM);
220 tmp = av_realloc_array(asset_map->assets,
221 elem_count + asset_map->asset_count,
222 sizeof(IMFAssetLocator));
223 if (!tmp) {
224 av_log(s, AV_LOG_ERROR, "Cannot allocate IMF asset locators\n");
225 return AVERROR(ENOMEM);
226 }
227 asset_map->assets = tmp;
228
229 asset_element = xmlFirstElementChild(node);
230 for (; asset_element; asset_element = xmlNextElementSibling(asset_element)) {
231 if (av_strcasecmp(asset_element->name, "Asset") != 0)
232 continue;
233
234 asset = &(asset_map->assets[asset_map->asset_count]);
235
236 if (!(node = ff_imf_xml_get_child_element_by_name(asset_element, "Id"))) {
237 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing Id node\n");
238 return AVERROR_INVALIDDATA;
239 }
240
241 if (ff_imf_xml_read_uuid(node, asset->uuid)) {
242 av_log(s, AV_LOG_ERROR, "Could not parse UUID from asset in asset map.\n");
243 return AVERROR_INVALIDDATA;
244 }
245
246 av_log(s, AV_LOG_DEBUG, "Found asset id: " AV_PRI_URN_UUID "\n", AV_UUID_ARG(asset->uuid));
247
248 if (!(node = ff_imf_xml_get_child_element_by_name(asset_element, "ChunkList"))) {
249 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing ChunkList node\n");
250 return AVERROR_INVALIDDATA;
251 }
252
253 if (!(node = ff_imf_xml_get_child_element_by_name(node, "Chunk"))) {
254 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing Chunk node\n");
255 return AVERROR_INVALIDDATA;
256 }
257
258 xmlNodePtr path_node = ff_imf_xml_get_child_element_by_name(node, "Path");
259 if (!path_node) {
260 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing Path element in Chunk\n");
262 break;
263 }
264 uri = xmlNodeGetContent(path_node);
265 if (!uri || !uri[0]) {
266 av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - empty Path element in Chunk\n");
267 xmlFree(uri);
269 break;
270 }
271
273 asset->absolute_uri = av_append_path_component(base_url, uri);
274 else
275 asset->absolute_uri = av_strdup(uri);
276 xmlFree(uri);
277 if (!asset->absolute_uri)
278 return AVERROR(ENOMEM);
279
280 av_log(s, AV_LOG_DEBUG, "Found asset absolute URI: %s\n", asset->absolute_uri);
281
282 asset_map->asset_count++;
283 }
284
285 return ret;
286}
287
288/**
289 * Initializes an IMFAssetLocatorMap structure.
290 */
292{
293 asset_map->assets = NULL;
294 asset_map->asset_count = 0;
295}
296
297/**
298 * Free a IMFAssetLocatorMap pointer.
299 */
301{
302 for (uint32_t i = 0; i < asset_map->asset_count; i++)
303 av_freep(&asset_map->assets[i].absolute_uri);
304
305 av_freep(&asset_map->assets);
306}
307
308static int parse_assetmap(AVFormatContext *s, const char *url)
309{
310 IMFContext *c = s->priv_data;
311 AVIOContext *in = NULL;
312 struct AVBPrint buf;
314 xmlDoc *doc = NULL;
315 const char *base_url;
316 char *tmp_str = NULL;
317 int ret;
318
319 av_log(s, AV_LOG_DEBUG, "Asset Map URL: %s\n", url);
320
321 av_dict_copy(&opts, c->avio_opts, 0);
322 ret = s->io_open(s, &in, url, AVIO_FLAG_READ, &opts);
324 if (ret < 0)
325 return ret;
326
327 av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer length
328
329 ret = avio_read_to_bprint(in, &buf, SIZE_MAX);
330 if (ret < 0 || !avio_feof(in)) {
331 av_log(s, AV_LOG_ERROR, "Unable to read to asset map '%s'\n", url);
332 if (ret == 0)
334 goto clean_up;
335 }
336
337 LIBXML_TEST_VERSION
338
339 tmp_str = av_strdup(url);
340 if (!tmp_str) {
341 ret = AVERROR(ENOMEM);
342 goto clean_up;
343 }
344 base_url = av_dirname(tmp_str);
345
346 doc = xmlReadMemory(buf.str, buf.len, url, NULL, 0);
347
348 ret = parse_imf_asset_map_from_xml_dom(s, doc, &c->asset_locator_map, base_url);
349 if (!ret)
350 av_log(s, AV_LOG_DEBUG, "Found %d assets from %s\n",
351 c->asset_locator_map.asset_count, url);
352
353 xmlFreeDoc(doc);
354
355clean_up:
356 if (tmp_str)
357 av_freep(&tmp_str);
358 ff_format_io_close(s, &in);
360 return ret;
361}
362
364{
365 for (uint32_t i = 0; i < asset_map->asset_count; i++) {
366 if (memcmp(asset_map->assets[i].uuid, uuid, 16) == 0)
367 return &(asset_map->assets[i]);
368 }
369 return NULL;
370}
371
374 int32_t resource_index)
375{
376 IMFContext *c = s->priv_data;
377 int ret = 0;
378 int64_t seek_offset = 0;
380 AVStream *st;
381 IMFVirtualTrackResourcePlaybackCtx *track_resource = track->resources + resource_index;
382
383 if (track_resource->ctx) {
384 av_log(s, AV_LOG_DEBUG, "Input context already opened for %s.\n",
385 track_resource->locator->absolute_uri);
386 return 0;
387 }
388
389 track_resource->ctx = avformat_alloc_context();
390 if (!track_resource->ctx)
391 return AVERROR(ENOMEM);
392
393 track_resource->ctx->io_open = s->io_open;
394 track_resource->ctx->io_close2 = s->io_close2;
395 track_resource->ctx->opaque = s->opaque;
396 track_resource->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO;
397
398 if ((ret = ff_copy_whiteblacklists(track_resource->ctx, s)) < 0)
399 goto cleanup;
400
401 if ((ret = av_opt_set(track_resource->ctx, "format_whitelist", "mxf", 0)))
402 goto cleanup;
403
404 if ((ret = av_dict_copy(&opts, c->avio_opts, 0)) < 0)
405 goto cleanup;
406
407 ret = avformat_open_input(&track_resource->ctx,
408 track_resource->locator->absolute_uri,
409 NULL,
410 &opts);
411 if (ret < 0) {
412 av_log(s, AV_LOG_ERROR, "Could not open %s input context: %s\n",
413 track_resource->locator->absolute_uri, av_err2str(ret));
414 goto cleanup;
415 }
417
418 /* make sure there is only one stream in the file */
419
420 if (track_resource->ctx->nb_streams != 1) {
422 goto cleanup;
423 }
424
425 st = track_resource->ctx->streams[0];
426
427 /* Determine the seek offset into the Track File, taking into account:
428 * - the current timestamp within the virtual track
429 * - the entry point of the resource
430 */
431 if (imf_time_to_ts(&seek_offset,
432 av_sub_q(track->current_timestamp, track_resource->ts_offset),
433 st->time_base))
434 av_log(s, AV_LOG_WARNING, "Incoherent stream timebase " AVRATIONAL_FORMAT
435 "and composition timeline position: " AVRATIONAL_FORMAT "\n",
437
438 if (seek_offset) {
439 av_log(s, AV_LOG_DEBUG, "Seek at resource %s entry point: %" PRIi64 "\n",
440 track_resource->locator->absolute_uri, seek_offset);
441 ret = avformat_seek_file(track_resource->ctx, 0, seek_offset, seek_offset, seek_offset, 0);
442 if (ret < 0) {
443 av_log(s,
445 "Could not seek at %" PRId64 "on %s: %s\n",
446 seek_offset,
447 track_resource->locator->absolute_uri,
448 av_err2str(ret));
449 avformat_close_input(&track_resource->ctx);
450 return ret;
451 }
452 }
453
454 return 0;
455
456cleanup:
458 avformat_free_context(track_resource->ctx);
459 track_resource->ctx = NULL;
460 return ret;
461}
462
464 FFIMFTrackFileResource *track_file_resource,
466{
467 IMFContext *c = s->priv_data;
468 IMFAssetLocator *asset_locator;
469 void *tmp;
470
471 asset_locator = find_asset_map_locator(&c->asset_locator_map, track_file_resource->track_file_uuid);
472 if (!asset_locator) {
473 av_log(s, AV_LOG_ERROR, "Could not find asset locator for UUID: " AV_PRI_URN_UUID "\n",
474 AV_UUID_ARG(track_file_resource->track_file_uuid));
475 return AVERROR_INVALIDDATA;
476 }
477
478 av_log(s,
480 "Found locator for " AV_PRI_URN_UUID ": %s\n",
481 AV_UUID_ARG(asset_locator->uuid),
482 asset_locator->absolute_uri);
483
484 if (track->resource_count > INT32_MAX - track_file_resource->base.repeat_count
485 || (track->resource_count + track_file_resource->base.repeat_count)
486 > INT_MAX / sizeof(IMFVirtualTrackResourcePlaybackCtx))
487 return AVERROR(ENOMEM);
489 &track->resources_alloc_sz,
490 (track->resource_count + track_file_resource->base.repeat_count)
492 if (!tmp)
493 return AVERROR(ENOMEM);
494 track->resources = tmp;
495
496 for (uint32_t i = 0; i < track_file_resource->base.repeat_count; i++) {
498
499 vt_ctx.locator = asset_locator;
500 vt_ctx.resource = track_file_resource;
501 vt_ctx.ctx = NULL;
502 vt_ctx.start_time = track->duration;
503 vt_ctx.ts_offset = av_sub_q(vt_ctx.start_time,
504 av_div_q(av_make_q((int)track_file_resource->base.entry_point, 1),
505 track_file_resource->base.edit_rate));
506 vt_ctx.end_time = av_add_q(track->duration,
507 av_make_q((int)track_file_resource->base.duration
508 * track_file_resource->base.edit_rate.den,
509 track_file_resource->base.edit_rate.num));
510 track->resources[track->resource_count++] = vt_ctx;
511 track->duration = vt_ctx.end_time;
512 }
513
514 return 0;
515}
516
518{
519 for (uint32_t i = 0; i < track->resource_count; i++)
521
522 av_freep(&track->resources);
523}
524
526 FFIMFTrackFileVirtualTrack *virtual_track,
528{
529 IMFContext *c = s->priv_data;
531 void *tmp;
532 int ret = 0;
533
534 if (!(track = av_mallocz(sizeof(IMFVirtualTrackPlaybackCtx))))
535 return AVERROR(ENOMEM);
536 track->current_resource_index = -1;
537 track->index = track_index;
538 track->duration = av_make_q(0, 1);
539
540 if (!virtual_track->resource_count) {
541 av_log(s, AV_LOG_ERROR, "Virtual track has no resources\n");
543 goto clean_up;
544 }
545
546 for (uint32_t i = 0; i < virtual_track->resource_count; i++) {
547 av_log(s,
549 "Open stream from file " AV_PRI_URN_UUID ", stream %d\n",
550 AV_UUID_ARG(virtual_track->resources[i].track_file_uuid),
551 i);
552 if ((ret = open_track_file_resource(s, &virtual_track->resources[i], track)) != 0) {
553 av_log(s,
555 "Could not open image track resource " AV_PRI_URN_UUID "\n",
556 AV_UUID_ARG(virtual_track->resources[i].track_file_uuid));
557 goto clean_up;
558 }
559 }
560
561 track->current_timestamp = av_make_q(0, track->duration.den);
562
563 if (c->track_count == UINT32_MAX) {
564 ret = AVERROR(ENOMEM);
565 goto clean_up;
566 }
567 tmp = av_realloc_array(c->tracks, c->track_count + 1, sizeof(IMFVirtualTrackPlaybackCtx *));
568 if (!tmp) {
569 ret = AVERROR(ENOMEM);
570 goto clean_up;
571 }
572 c->tracks = tmp;
573 c->tracks[c->track_count++] = track;
574
575 return 0;
576
577clean_up:
579 av_free(track);
580 return ret;
581}
582
584{
585 IMFContext *c = s->priv_data;
586 int ret = 0;
587
588 for (uint32_t i = 0; i < c->track_count; i++) {
589 AVStream *asset_stream;
590 AVStream *first_resource_stream;
591
592 /* Open the first resource of the track to get stream information */
593 ret = open_track_resource_context(s, c->tracks[i], 0);
594 if (ret)
595 return ret;
596 first_resource_stream = c->tracks[i]->resources[0].ctx->streams[0];
597 av_log(s, AV_LOG_DEBUG, "Open the first resource of track %d\n", c->tracks[i]->index);
598
599 asset_stream = ff_stream_clone(s, first_resource_stream);
600 if (!asset_stream) {
601 av_log(s, AV_LOG_ERROR, "Could not clone stream\n");
602 return AVERROR(ENOMEM);
603 }
604
605 asset_stream->id = i;
606 asset_stream->nb_frames = 0;
607 avpriv_set_pts_info(asset_stream,
608 first_resource_stream->pts_wrap_bits,
609 first_resource_stream->time_base.num,
610 first_resource_stream->time_base.den);
611 asset_stream->duration = (int64_t)av_q2d(av_mul_q(c->tracks[i]->duration,
612 av_inv_q(asset_stream->time_base)));
613 }
614
615 return 0;
616}
617
619{
620 IMFContext *c = s->priv_data;
622 int ret;
623
624 if (c->cpl->main_image_2d_track) {
625 if ((ret = open_virtual_track(s, c->cpl->main_image_2d_track, track_index++)) != 0) {
626 av_log(s, AV_LOG_ERROR, "Could not open image track " AV_PRI_URN_UUID "\n",
627 AV_UUID_ARG(c->cpl->main_image_2d_track->base.id_uuid));
628 return ret;
629 }
630 }
631
632 for (uint32_t i = 0; i < c->cpl->main_audio_track_count; i++) {
633 if ((ret = open_virtual_track(s, &c->cpl->main_audio_tracks[i], track_index++)) != 0) {
634 av_log(s, AV_LOG_ERROR, "Could not open audio track " AV_PRI_URN_UUID "\n",
635 AV_UUID_ARG(c->cpl->main_audio_tracks[i].base.id_uuid));
636 return ret;
637 }
638 }
639
641}
642
644{
645 IMFContext *c = s->priv_data;
646 char *asset_map_path;
647 char *tmp_str;
649 char tc_buf[AV_TIMECODE_STR_SIZE];
650 int ret = 0;
651
652 c->interrupt_callback = &s->interrupt_callback;
653 tmp_str = av_strdup(s->url);
654 if (!tmp_str)
655 return AVERROR(ENOMEM);
656 c->base_url = av_strdup(av_dirname(tmp_str));
657 av_freep(&tmp_str);
658 if (!c->base_url)
659 return AVERROR(ENOMEM);
660
661 if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0)
662 return ret;
663
664 av_log(s, AV_LOG_DEBUG, "start parsing IMF CPL: %s\n", s->url);
665
666 if ((ret = ff_imf_parse_cpl(s, s->pb, &c->cpl)) < 0)
667 return ret;
668
669 tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
670 if (!tcr && c->cpl->tc) {
671 ret = av_dict_set(&s->metadata, "timecode",
672 av_timecode_make_string(c->cpl->tc, tc_buf, 0), 0);
673 if (ret)
674 return ret;
675 av_log(s, AV_LOG_INFO, "Setting timecode to IMF CPL timecode %s\n", tc_buf);
676 }
677
678 av_log(s,
680 "parsed IMF CPL: " AV_PRI_URN_UUID "\n",
681 AV_UUID_ARG(c->cpl->id_uuid));
682
683 if (!c->asset_map_paths) {
684 c->asset_map_paths = av_append_path_component(c->base_url, "ASSETMAP.xml");
685 if (!c->asset_map_paths) {
686 ret = AVERROR(ENOMEM);
687 return ret;
688 }
689 av_log(s, AV_LOG_DEBUG, "No asset maps provided, using the default ASSETMAP.xml\n");
690 }
691
692 /* Parse each asset map XML file */
693 imf_asset_locator_map_init(&c->asset_locator_map);
694 asset_map_path = av_strtok(c->asset_map_paths, ",", &tmp_str);
695 while (asset_map_path != NULL) {
696 av_log(s, AV_LOG_DEBUG, "start parsing IMF Asset Map: %s\n", asset_map_path);
697
698 if ((ret = parse_assetmap(s, asset_map_path)))
699 return ret;
700
701 asset_map_path = av_strtok(NULL, ",", &tmp_str);
702 }
703
704 av_log(s, AV_LOG_DEBUG, "parsed IMF Asset Maps\n");
705
706 if ((ret = open_cpl_tracks(s)))
707 return ret;
708
709 av_log(s, AV_LOG_DEBUG, "parsed IMF package\n");
710
711 return 0;
712}
713
715{
716 IMFContext *c = s->priv_data;
718 AVRational minimum_timestamp = av_make_q(INT32_MAX, 1);
719
720 for (uint32_t i = c->track_count; i > 0; i--) {
721 av_log(s, AV_LOG_TRACE, "Compare track %d timestamp " AVRATIONAL_FORMAT
722 " to minimum " AVRATIONAL_FORMAT
723 " (over duration: " AVRATIONAL_FORMAT ")\n", i,
724 AVRATIONAL_ARG(c->tracks[i - 1]->current_timestamp),
725 AVRATIONAL_ARG(minimum_timestamp),
726 AVRATIONAL_ARG(c->tracks[i - 1]->duration));
727
728 if (av_cmp_q(c->tracks[i - 1]->current_timestamp, minimum_timestamp) <= 0) {
729 track = c->tracks[i - 1];
730 minimum_timestamp = track->current_timestamp;
731 }
732 }
733
734 return track;
735}
736
738{
739 *resource = NULL;
740
741 if (av_cmp_q(track->current_timestamp, track->duration) >= 0) {
742 av_log(s, AV_LOG_DEBUG, "Reached the end of the virtual track\n");
743 return AVERROR_EOF;
744 }
745
746 av_log(s,
748 "Looking for track %d resource for timestamp = %lf / %lf\n",
749 track->index,
751 av_q2d(track->duration));
752 for (uint32_t i = 0; i < track->resource_count; i++) {
753
754 if (av_cmp_q(track->resources[i].end_time, track->current_timestamp) > 0) {
755 av_log(s, AV_LOG_DEBUG, "Found resource %d in track %d to read at timestamp %lf: "
756 "entry=%" PRIu32 ", duration=%" PRIu32 ", editrate=" AVRATIONAL_FORMAT "\n",
757 i, track->index, av_q2d(track->current_timestamp),
761
762 if (track->current_resource_index != i) {
763 int ret;
764
765 av_log(s, AV_LOG_TRACE, "Switch resource on track %d: re-open context\n",
766 track->index);
767
768 ret = open_track_resource_context(s, track, i);
769 if (ret != 0)
770 return ret;
771 if (track->current_resource_index > 0)
773 track->current_resource_index = i;
774 }
775
776 *resource = track->resources + track->current_resource_index;
777 return 0;
778 }
779 }
780
781 av_log(s, AV_LOG_ERROR, "Could not find IMF track resource to read\n");
783}
784
786{
788 int ret = 0;
790 int64_t delta_ts;
791 AVStream *st;
792 AVRational next_timestamp;
793
795
796 if (!track) {
797 av_log(s, AV_LOG_ERROR, "No track found for playback\n");
798 return AVERROR_INVALIDDATA;
799 }
800
801 av_log(s, AV_LOG_DEBUG, "Found track %d to read at timestamp %lf\n",
802 track->index, av_q2d(track->current_timestamp));
803
804 ret = get_resource_context_for_timestamp(s, track, &resource);
805 if (ret)
806 return ret;
807
808 ret = av_read_frame(resource->ctx, pkt);
809 if (ret)
810 return ret;
811
812 av_log(s, AV_LOG_DEBUG, "Got packet: pts=%" PRId64 ", dts=%" PRId64
813 ", duration=%" PRId64 ", stream_index=%d, pos=%" PRId64
814 ", time_base=" AVRATIONAL_FORMAT "\n", pkt->pts, pkt->dts, pkt->duration,
815 pkt->stream_index, pkt->pos, AVRATIONAL_ARG(pkt->time_base));
816
817 /* IMF resources contain only one stream */
818
819 if (pkt->stream_index != 0)
820 return AVERROR_INVALIDDATA;
821 st = resource->ctx->streams[0];
822
823 pkt->stream_index = track->index;
824
825 /* adjust the packet PTS and DTS based on the temporal position of the resource within the timeline */
826
827 ret = imf_time_to_ts(&delta_ts, resource->ts_offset, st->time_base);
828
829 if (!ret) {
830 if (pkt->pts != AV_NOPTS_VALUE)
831 pkt->pts += delta_ts;
832 if (pkt->dts != AV_NOPTS_VALUE)
833 pkt->dts += delta_ts;
834 } else {
835 av_log(s, AV_LOG_WARNING, "Incoherent time stamp " AVRATIONAL_FORMAT
836 " for time base " AVRATIONAL_FORMAT,
837 AVRATIONAL_ARG(resource->ts_offset),
838 AVRATIONAL_ARG(pkt->time_base));
839 }
840
841 /* advance the track timestamp by the packet duration */
842
843 next_timestamp = av_add_q(track->current_timestamp,
844 av_mul_q(av_make_q((int)pkt->duration, 1), st->time_base));
845
846 /* if necessary, clamp the next timestamp to the end of the current resource */
847
848 if (av_cmp_q(next_timestamp, resource->end_time) > 0) {
849
850 int64_t new_pkt_dur;
851
852 /* shrink the packet duration */
853
854 ret = imf_time_to_ts(&new_pkt_dur,
855 av_sub_q(resource->end_time, track->current_timestamp),
856 st->time_base);
857
858 if (!ret)
859 pkt->duration = new_pkt_dur;
860 else
861 av_log(s, AV_LOG_WARNING, "Incoherent time base in packet duration calculation\n");
862
863 /* shrink the packet itself for audio essence */
864
866
868 /* AV_CODEC_ID_PCM_S24LE is the only PCM format supported in IMF */
869 /* in this case, explicitly shrink the packet */
870
871 int bytes_per_sample = av_get_exact_bits_per_sample(st->codecpar->codec_id) >> 3;
872 int64_t nbsamples = av_rescale_q(pkt->duration,
873 st->time_base,
875 av_shrink_packet(pkt, nbsamples * st->codecpar->ch_layout.nb_channels * bytes_per_sample);
876
877 } else {
878 /* in all other cases, use side data to skip samples */
879 int64_t skip_samples;
880
881 ret = imf_time_to_ts(&skip_samples,
882 av_sub_q(next_timestamp, resource->end_time),
884
885 if (ret || skip_samples < 0 || skip_samples > UINT32_MAX) {
886 av_log(s, AV_LOG_WARNING, "Cannot skip audio samples\n");
887 } else {
888 uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
889 if (!side_data)
890 return AVERROR(ENOMEM);
891
892 AV_WL32(side_data + 4, skip_samples); /* skip from end of this packet */
893 side_data[6] = 1; /* reason for end is convergence */
894 }
895 }
896
897 next_timestamp = resource->end_time;
898
899 } else {
900 av_log(s, AV_LOG_WARNING, "Non-audio packet duration reduced\n");
901 }
902 }
903
904 track->current_timestamp = next_timestamp;
905
906 return 0;
907}
908
910{
911 IMFContext *c = s->priv_data;
912
913 av_log(s, AV_LOG_DEBUG, "Close IMF package\n");
914 av_dict_free(&c->avio_opts);
915 av_freep(&c->base_url);
916 imf_asset_locator_map_deinit(&c->asset_locator_map);
917 ff_imf_cpl_free(c->cpl);
918
919 for (uint32_t i = 0; i < c->track_count; i++) {
921 av_freep(&c->tracks[i]);
922 }
923
924 av_freep(&c->tracks);
925
926 return 0;
927}
928
929static int imf_probe(const AVProbeData *p)
930{
931 if (!strstr(p->buf, "<CompositionPlaylist"))
932 return 0;
933
934 /* check for a ContentTitle element without including ContentTitleText,
935 * which is used by the D-Cinema CPL.
936 */
937 if (!strstr(p->buf, "ContentTitle>"))
938 return 0;
939
940 return AVPROBE_SCORE_MAX;
941}
942
943static int coherent_ts(int64_t ts, AVRational in_tb, AVRational out_tb)
944{
945 int dst_num;
946 int dst_den;
947 int ret;
948
949 ret = av_reduce(&dst_num, &dst_den, ts * in_tb.num * out_tb.den,
950 in_tb.den * out_tb.num, INT64_MAX);
951 if (!ret || dst_den != 1)
952 return 0;
953
954 return 1;
955}
956
957static int imf_seek(AVFormatContext *s, int stream_index, int64_t min_ts,
958 int64_t ts, int64_t max_ts, int flags)
959{
960 IMFContext *c = s->priv_data;
961 uint32_t i;
962
964 return AVERROR(ENOSYS);
965
966 /* rescale timestamps to Composition edit units */
967 if (stream_index < 0)
969 av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
970 &min_ts, &ts, &max_ts);
971 else
972 ff_rescale_interval(s->streams[stream_index]->time_base,
973 av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
974 &min_ts, &ts, &max_ts);
975
976 /* requested timestamp bounds are too close */
977 if (max_ts < min_ts)
978 return -1;
979
980 /* clamp requested timestamp to provided bounds */
981 ts = FFMAX(FFMIN(ts, max_ts), min_ts);
982
983 av_log(s, AV_LOG_DEBUG, "Seeking to Composition Playlist edit unit %" PRIi64 "\n", ts);
984
985 /* set the dts of each stream and temporal offset of each track */
986 for (i = 0; i < c->track_count; i++) {
987 AVStream *st = s->streams[i];
988 IMFVirtualTrackPlaybackCtx *t = c->tracks[i];
989 int64_t dts;
990
991 if (!coherent_ts(ts, av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
992 st->time_base))
993 av_log(s, AV_LOG_WARNING, "Seek position is not coherent across tracks\n");
994
995 dts = av_rescale(ts,
996 st->time_base.den * c->cpl->edit_rate.den,
997 st->time_base.num * c->cpl->edit_rate.num);
998
999 av_log(s, AV_LOG_DEBUG, "Seeking to dts=%" PRId64 " on stream_index=%d\n",
1000 dts, i);
1001
1002 t->current_timestamp = av_mul_q(av_make_q(dts, 1), st->time_base);
1003 if (t->current_resource_index >= 0) {
1005 t->current_resource_index = -1;
1006 }
1007 }
1008
1009 return 0;
1010}
1011
1012static const AVOption imf_options[] = {
1013 {
1014 .name = "assetmaps",
1015 .help = "Comma-separated paths to ASSETMAP files."
1016 "If not specified, the `ASSETMAP.xml` file in the same "
1017 "directory as the CPL is used.",
1018 .offset = offsetof(IMFContext, asset_map_paths),
1019 .type = AV_OPT_TYPE_STRING,
1020 .default_val = {.str = NULL},
1022 },
1023 {NULL},
1024};
1025
1026static const AVClass imf_class = {
1027 .class_name = "imf",
1028 .item_name = av_default_item_name,
1029 .option = imf_options,
1030 .version = LIBAVUTIL_VERSION_INT,
1031};
1032
1034 .p.name = "imf",
1035 .p.long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"),
1036 .p.flags = AVFMT_NO_BYTE_SEEK,
1037 .p.priv_class = &imf_class,
1038 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
1039 .priv_data_size = sizeof(IMFContext),
1044 .read_seek2 = imf_seek,
1045};
const FFInputFormat ff_imf_demuxer
Definition imfdec.c:1033
static AVDictionary * opts
int32_t
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition avformat.c:983
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition avformat.c:901
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:856
AVStream * ff_stream_clone(AVFormatContext *dst_ctx, const AVStream *src)
Create a new stream and copy to it all parameters from a source stream, with the exception of the ind...
Definition avformat.c:265
#define AVPROBE_SCORE_MAX
maximum score
Definition avformat.h:485
#define AVFMT_NO_BYTE_SEEK
Format does not allow seeking by bytes.
Definition avformat.h:508
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition avformat.h:2712
#define AVSEEK_FLAG_FRAME
seeking based on frame number
Definition avformat.h:2714
#define AVFMT_FLAG_CUSTOM_IO
The caller has supplied a custom AVIOContext, don't avio_close() it.
Definition avformat.h:1560
#define AVIO_FLAG_READ
read-only
Definition avio.h:617
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size)
Read contents of h into print buffer, up to max_size bytes, or up to EOF.
Definition aviobuf.c:1213
int ffio_copy_url_options(AVIOContext *pb, AVDictionary **avio_opts)
Read url related dictionary options from the AVIOContext and write to the given dictionary.
Definition aviobuf.c:953
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:68
AVBPrint public header.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
static int read_probe(const AVProbeData *p)
Definition cdg.c:30
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
void ff_rescale_interval(AVRational tb_in, AVRational tb_out, int64_t *min_ts, int64_t *ts, int64_t *max_ts)
Rescales a timestamp and the endpoints of an interval to which the temstamp belongs,...
Definition seek.c:755
#define FF_INFMT_FLAG_INIT_CLEANUP
For an FFInputFormat with this flag set read_close() needs to be called by the caller upon read_heade...
Definition demux.h:35
static AVPacket * pkt
static int read_header(FFV1Context *f, RangeCoder *c)
Definition ffv1dec.c:578
static av_cold void cleanup(FlashSV2Context *s)
#define AV_OPT_FLAG_DECODING_PARAM
A generic parameter which can be set by the user for demuxing or decoding.
Definition opt.h:355
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
Return codec bits per sample.
Definition utils.c:461
@ AV_CODEC_ID_PCM_S24LE
Definition codec_id.h:344
@ AV_PKT_DATA_SKIP_SAMPLES
Recommends skipping the specified number of samples.
Definition packet.h:153
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, size_t size)
Allocate new information of a packet.
Definition packet.c:231
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition packet.c:113
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition options.c:165
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition avformat.c:164
int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Seek to timestamp ts.
Definition seek.c:667
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition demux.c:1611
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition demux.c:231
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition demux.c:400
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:234
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:236
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:61
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition dict.c:250
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:87
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_STREAM_NOT_FOUND
Stream not found.
Definition error.h:67
#define AVERROR_EOF
End of file.
Definition error.h:57
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition log.h:236
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
AVRational av_add_q(AVRational b, AVRational c)
Add two rationals.
Definition rational.c:93
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition rational.c:80
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition rational.c:35
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition rational.h:71
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition rational.h:89
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
AVRational av_sub_q(AVRational b, AVRational c)
Subtract one rational from another.
Definition rational.c:101
AVRational av_div_q(AVRational b, AVRational c)
Divide one rational by another.
Definition rational.c:88
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition mem.c:601
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition mem.c:318
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition avstring.c:179
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
const char * av_dirname(char *path)
Thread safe dirname.
Definition avstring.c:274
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition avstring.c:295
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition avutil.h:263
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition opt.c:891
Public header file for the processing of Interoperable Master Format (IMF) packages.
xmlNodePtr ff_imf_xml_get_child_element_by_name(xmlNodePtr parent, const char *name_utf8)
Returns the first child element with the specified local name.
Definition imf_cpl.c:59
int ff_imf_parse_cpl(void *log_ctx, AVIOContext *in, FFIMFCPL **cpl)
Parse an IMF Composition Playlist document into the FFIMFCPL data structure.
Definition imf_cpl.c:873
void ff_imf_cpl_free(FFIMFCPL *cpl)
Deletes an FFIMFCPL data structure previously instantiated with ff_imf_cpl_alloc().
Definition imf_cpl.c:844
int ff_imf_xml_read_uuid(xmlNodePtr element, AVUUID uuid)
Reads a UUID from an XML element.
Definition imf_cpl.c:73
static void imf_asset_locator_map_init(IMFAssetLocatorMap *asset_map)
Initializes an IMFAssetLocatorMap structure.
Definition imfdec.c:291
static int imf_uri_is_url(const char *string)
Definition imfdec.c:130
static int set_context_streams_from_tracks(AVFormatContext *s)
Definition imfdec.c:583
static int imf_uri_is_unix_abs_path(const char *string)
Definition imfdec.c:135
static const AVClass imf_class
Definition imfdec.c:1026
#define AVRATIONAL_FORMAT
Definition imfdec.c:78
static int imf_uri_is_dos_abs_path(const char *string)
Definition imfdec.c:140
static int coherent_ts(int64_t ts, AVRational in_tb, AVRational out_tb)
Definition imfdec.c:943
static int imf_time_to_ts(int64_t *ts, AVRational t, AVRational time_base)
Definition imfdec.c:157
#define AVRATIONAL_ARG(rational)
Definition imfdec.c:79
static const AVOption imf_options[]
Definition imfdec.c:1012
static int imf_read_header(AVFormatContext *s)
Definition imfdec.c:643
static IMFAssetLocator * find_asset_map_locator(IMFAssetLocatorMap *asset_map, AVUUID uuid)
Definition imfdec.c:363
static int imf_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition imfdec.c:785
static int open_track_file_resource(AVFormatContext *s, FFIMFTrackFileResource *track_file_resource, IMFVirtualTrackPlaybackCtx *track)
Definition imfdec.c:463
static int open_cpl_tracks(AVFormatContext *s)
Definition imfdec.c:618
static void imf_asset_locator_map_deinit(IMFAssetLocatorMap *asset_map)
Free a IMFAssetLocatorMap pointer.
Definition imfdec.c:300
static int open_virtual_track(AVFormatContext *s, FFIMFTrackFileVirtualTrack *virtual_track, int32_t track_index)
Definition imfdec.c:525
static int imf_close(AVFormatContext *s)
Definition imfdec.c:909
static int parse_assetmap(AVFormatContext *s, const char *url)
Definition imfdec.c:308
static IMFVirtualTrackPlaybackCtx * get_next_track_with_minimum_timestamp(AVFormatContext *s)
Definition imfdec.c:714
static int imf_probe(const AVProbeData *p)
Definition imfdec.c:929
static int get_resource_context_for_timestamp(AVFormatContext *s, IMFVirtualTrackPlaybackCtx *track, IMFVirtualTrackResourcePlaybackCtx **resource)
Definition imfdec.c:737
static int parse_imf_asset_map_from_xml_dom(AVFormatContext *s, xmlDocPtr doc, IMFAssetLocatorMap *asset_map, const char *base_url)
Parse a ASSETMAP XML file to extract the UUID-URI mapping of assets.
Definition imfdec.c:184
static void imf_virtual_track_playback_context_deinit(IMFVirtualTrackPlaybackCtx *track)
Definition imfdec.c:517
static int imf_seek(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
Definition imfdec.c:957
static int open_track_resource_context(AVFormatContext *s, IMFVirtualTrackPlaybackCtx *track, int32_t resource_index)
Definition imfdec.c:372
#define r
Definition input.c:42
#define AV_WL32(p, v)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:97
static av_cold int read_close(AVFormatContext *ctx)
Definition libcdio.c:143
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define av_strdup(s)
Definition ops_static.c:55
AVOptions.
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
Definition log.h:76
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
Format I/O context.
Definition avformat.h:1400
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition avformat.h:1456
int(* io_close2)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition avformat.h:2031
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1552
void * opaque
User data.
Definition avformat.h:1980
AVStream ** streams
A list of all streams in the file.
Definition avformat.h:1468
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition avformat.h:2021
Bytestream IO Context.
Definition avio.h:160
Callback for checking whether to abort blocking functions.
Definition avio.h:59
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:587
This structure contains the data a format has to probe a file.
Definition avformat.h:473
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Stream structure.
Definition avformat.h:768
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:791
int64_t nb_frames
number of frames in this stream if known or 0
Definition avformat.h:829
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition avformat.h:827
int id
Format-specific stream ID.
Definition avformat.h:780
int pts_wrap_bits
Number of bits in timestamps.
Definition avformat.h:911
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:807
AVRational edit_rate
BaseResourceType/EditRate.
Definition imf.h:69
uint32_t duration
BaseResourceType/Duration.
Definition imf.h:71
uint32_t repeat_count
BaseResourceType/RepeatCount.
Definition imf.h:72
uint32_t entry_point
BaseResourceType/EntryPoint.
Definition imf.h:70
IMF Composition Playlist.
Definition imf.h:130
IMF Composition Playlist Track File Resource.
Definition imf.h:78
FFIMFBaseResource base
Definition imf.h:79
AVUUID track_file_uuid
TrackFileResourceType/TrackFileId.
Definition imf.h:80
IMF Composition Playlist Virtual Track that consists of Track File Resources.
Definition imf.h:111
FFIMFTrackFileResource * resources
Resource elements of the Virtual Track.
Definition imf.h:114
uint32_t resource_count
Number of Resource elements present in the Virtual Track.
Definition imf.h:113
IMF Asset locator map Results from the parsing of one or more ASSETMAP XML files.
Definition imfdec.c:93
uint32_t asset_count
Definition imfdec.c:94
IMFAssetLocator * assets
Definition imfdec.c:95
IMF Asset locator.
Definition imfdec.c:84
char * absolute_uri
Definition imfdec.c:86
AVUUID uuid
Definition imfdec.c:85
const char * base_url
Definition imfdec.c:120
IMFAssetLocatorMap asset_locator_map
Definition imfdec.c:125
FFIMFCPL * cpl
Definition imfdec.c:124
uint32_t track_count
Definition imfdec.c:126
AVDictionary * avio_opts
Definition imfdec.c:123
AVIOInterruptCB * interrupt_callback
Definition imfdec.c:122
char * asset_map_paths
Definition imfdec.c:121
IMFVirtualTrackPlaybackCtx ** tracks
Definition imfdec.c:127
AVRational duration
Overall duration.
Definition imfdec.c:110
AVRational current_timestamp
Current temporal position.
Definition imfdec.c:109
uint32_t resource_count
Number of resources (<= INT32_MAX)
Definition imfdec.c:111
int32_t current_resource_index
Index of the current resource in resources, or < 0 if a current resource has yet to be selected.
Definition imfdec.c:114
int32_t index
Track index in playlist.
Definition imfdec.c:108
IMFVirtualTrackResourcePlaybackCtx * resources
Buffer holding the resources.
Definition imfdec.c:113
unsigned int resources_alloc_sz
Size of the buffer holding the resource.
Definition imfdec.c:112
AVRational end_time
exclusive end time of the resource on the CPL timeline (s)
Definition imfdec.c:103
AVFormatContext * ctx
Context associated with the resource.
Definition imfdec.c:101
IMFAssetLocator * locator
Location of the resource.
Definition imfdec.c:99
FFIMFTrackFileResource * resource
Underlying IMF CPL resource.
Definition imfdec.c:100
AVRational ts_offset
start_time minus the entry point into the resource (s)
Definition imfdec.c:104
AVRational start_time
inclusive start time of the resource on the CPL timeline (s)
Definition imfdec.c:102
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum_arg)
Load timecode string in buf.
Definition timecode.c:104
#define AV_TIMECODE_STR_SIZE
Definition timecode.h:33
#define AV_PRI_URN_UUID
Definition uuid.h:43
#define AV_UUID_ARG(x)
Definition uuid.h:51
uint8_t AVUUID[AV_UUID_LEN]
Definition uuid.h:60
static int track_index(VividasDemuxContext *viv, AVFormatContext *s, const uint8_t *buf, unsigned size)
Definition vividas.c:438
static double c[64]