FFmpeg
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"
72 #include "libavutil/intreadwrite.h"
73 #include "libavutil/opt.h"
74 #include "mxf.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  */
84 typedef struct IMFAssetLocator {
86  char *absolute_uri;
88 
89 /**
90  * IMF Asset locator map
91  * Results from the parsing of one or more ASSETMAP XML files
92  */
93 typedef struct IMFAssetLocatorMap {
94  uint32_t asset_count;
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 
118 typedef struct IMFContext {
119  const AVClass *class;
120  const char *base_url;
126  uint32_t track_count;
128 } IMFContext;
129 
130 static int imf_uri_is_url(const char *string)
131 {
132  return strstr(string, "://") != NULL;
133 }
134 
135 static int imf_uri_is_unix_abs_path(const char *string)
136 {
137  return string[0] == '/';
138 }
139 
140 static int imf_uri_is_dos_abs_path(const char *string)
141 {
142  /* Absolute path case: `C:\path\to\somwhere` */
143  if (string[1] == ':' && string[2] == '\\')
144  return 1;
145 
146  /* Absolute path case: `C:/path/to/somwhere` */
147  if (string[1] == ':' && string[2] == '/')
148  return 1;
149 
150  /* Network path case: `\\path\to\somwhere` */
151  if (string[0] == '\\' && string[1] == '\\')
152  return 1;
153 
154  return 0;
155 }
156 
157 static int imf_time_to_ts(int64_t *ts, AVRational t, AVRational time_base)
158 {
159  int dst_num;
160  int dst_den;
161  AVRational r;
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  while (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 (ff_imf_xml_read_uuid(ff_imf_xml_get_child_element_by_name(asset_element, "Id"), asset->uuid)) {
237  av_log(s, AV_LOG_ERROR, "Could not parse UUID from asset in asset map.\n");
238  return AVERROR_INVALIDDATA;
239  }
240 
241  av_log(s, AV_LOG_DEBUG, "Found asset id: " AV_PRI_URN_UUID "\n", AV_UUID_ARG(asset->uuid));
242 
243  if (!(node = ff_imf_xml_get_child_element_by_name(asset_element, "ChunkList"))) {
244  av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing ChunkList node\n");
245  return AVERROR_INVALIDDATA;
246  }
247 
248  if (!(node = ff_imf_xml_get_child_element_by_name(node, "Chunk"))) {
249  av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing Chunk node\n");
250  return AVERROR_INVALIDDATA;
251  }
252 
253  uri = xmlNodeGetContent(ff_imf_xml_get_child_element_by_name(node, "Path"));
255  asset->absolute_uri = av_append_path_component(base_url, uri);
256  else
257  asset->absolute_uri = av_strdup(uri);
258  xmlFree(uri);
259  if (!asset->absolute_uri)
260  return AVERROR(ENOMEM);
261 
262  av_log(s, AV_LOG_DEBUG, "Found asset absolute URI: %s\n", asset->absolute_uri);
263 
264  asset_map->asset_count++;
265  asset_element = xmlNextElementSibling(asset_element);
266  }
267 
268  return ret;
269 }
270 
271 /**
272  * Initializes an IMFAssetLocatorMap structure.
273  */
275 {
276  asset_map->assets = NULL;
277  asset_map->asset_count = 0;
278 }
279 
280 /**
281  * Free a IMFAssetLocatorMap pointer.
282  */
284 {
285  for (uint32_t i = 0; i < asset_map->asset_count; i++)
286  av_freep(&asset_map->assets[i].absolute_uri);
287 
288  av_freep(&asset_map->assets);
289 }
290 
291 static int parse_assetmap(AVFormatContext *s, const char *url)
292 {
293  IMFContext *c = s->priv_data;
294  AVIOContext *in = NULL;
295  struct AVBPrint buf;
297  xmlDoc *doc = NULL;
298  const char *base_url;
299  char *tmp_str = NULL;
300  int ret;
301 
302  av_log(s, AV_LOG_DEBUG, "Asset Map URL: %s\n", url);
303 
304  av_dict_copy(&opts, c->avio_opts, 0);
305  ret = s->io_open(s, &in, url, AVIO_FLAG_READ, &opts);
306  av_dict_free(&opts);
307  if (ret < 0)
308  return ret;
309 
310  av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer length
311 
312  ret = avio_read_to_bprint(in, &buf, SIZE_MAX);
313  if (ret < 0 || !avio_feof(in)) {
314  av_log(s, AV_LOG_ERROR, "Unable to read to asset map '%s'\n", url);
315  if (ret == 0)
317  goto clean_up;
318  }
319 
320  LIBXML_TEST_VERSION
321 
322  tmp_str = av_strdup(url);
323  if (!tmp_str) {
324  ret = AVERROR(ENOMEM);
325  goto clean_up;
326  }
327  base_url = av_dirname(tmp_str);
328 
329  doc = xmlReadMemory(buf.str, buf.len, url, NULL, 0);
330 
331  ret = parse_imf_asset_map_from_xml_dom(s, doc, &c->asset_locator_map, base_url);
332  if (!ret)
333  av_log(s, AV_LOG_DEBUG, "Found %d assets from %s\n",
334  c->asset_locator_map.asset_count, url);
335 
336  xmlFreeDoc(doc);
337 
338 clean_up:
339  if (tmp_str)
340  av_freep(&tmp_str);
341  ff_format_io_close(s, &in);
342  av_bprint_finalize(&buf, NULL);
343  return ret;
344 }
345 
347 {
348  for (uint32_t i = 0; i < asset_map->asset_count; i++) {
349  if (memcmp(asset_map->assets[i].uuid, uuid, 16) == 0)
350  return &(asset_map->assets[i]);
351  }
352  return NULL;
353 }
354 
357  int32_t resource_index)
358 {
359  IMFContext *c = s->priv_data;
360  int ret = 0;
361  int64_t seek_offset = 0;
363  AVStream *st;
364  IMFVirtualTrackResourcePlaybackCtx *track_resource = track->resources + resource_index;
365 
366  if (track_resource->ctx) {
367  av_log(s, AV_LOG_DEBUG, "Input context already opened for %s.\n",
368  track_resource->locator->absolute_uri);
369  return 0;
370  }
371 
372  track_resource->ctx = avformat_alloc_context();
373  if (!track_resource->ctx)
374  return AVERROR(ENOMEM);
375 
376  track_resource->ctx->io_open = s->io_open;
377  track_resource->ctx->io_close = s->io_close;
378  track_resource->ctx->io_close2 = s->io_close2;
379  track_resource->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO;
380 
381  if ((ret = ff_copy_whiteblacklists(track_resource->ctx, s)) < 0)
382  goto cleanup;
383 
384  if ((ret = av_opt_set(track_resource->ctx, "format_whitelist", "mxf", 0)))
385  goto cleanup;
386 
387  if ((ret = av_dict_copy(&opts, c->avio_opts, 0)) < 0)
388  goto cleanup;
389 
390  ret = avformat_open_input(&track_resource->ctx,
391  track_resource->locator->absolute_uri,
392  NULL,
393  &opts);
394  if (ret < 0) {
395  av_log(s, AV_LOG_ERROR, "Could not open %s input context: %s\n",
396  track_resource->locator->absolute_uri, av_err2str(ret));
397  goto cleanup;
398  }
399  av_dict_free(&opts);
400 
401  /* make sure there is only one stream in the file */
402 
403  if (track_resource->ctx->nb_streams != 1) {
405  goto cleanup;
406  }
407 
408  st = track_resource->ctx->streams[0];
409 
410  /* Determine the seek offset into the Track File, taking into account:
411  * - the current timestamp within the virtual track
412  * - the entry point of the resource
413  */
414  if (imf_time_to_ts(&seek_offset,
415  av_sub_q(track->current_timestamp, track_resource->ts_offset),
416  st->time_base))
417  av_log(s, AV_LOG_WARNING, "Incoherent stream timebase " AVRATIONAL_FORMAT
418  "and composition timeline position: " AVRATIONAL_FORMAT "\n",
420 
421  if (seek_offset) {
422  av_log(s, AV_LOG_DEBUG, "Seek at resource %s entry point: %" PRIi64 "\n",
423  track_resource->locator->absolute_uri, seek_offset);
424  ret = avformat_seek_file(track_resource->ctx, 0, seek_offset, seek_offset, seek_offset, 0);
425  if (ret < 0) {
426  av_log(s,
427  AV_LOG_ERROR,
428  "Could not seek at %" PRId64 "on %s: %s\n",
429  seek_offset,
430  track_resource->locator->absolute_uri,
431  av_err2str(ret));
432  avformat_close_input(&track_resource->ctx);
433  return ret;
434  }
435  }
436 
437  return 0;
438 
439 cleanup:
440  av_dict_free(&opts);
441  avformat_free_context(track_resource->ctx);
442  track_resource->ctx = NULL;
443  return ret;
444 }
445 
447  FFIMFTrackFileResource *track_file_resource,
449 {
450  IMFContext *c = s->priv_data;
451  IMFAssetLocator *asset_locator;
452  void *tmp;
453 
454  asset_locator = find_asset_map_locator(&c->asset_locator_map, track_file_resource->track_file_uuid);
455  if (!asset_locator) {
456  av_log(s, AV_LOG_ERROR, "Could not find asset locator for UUID: " AV_PRI_URN_UUID "\n",
457  AV_UUID_ARG(track_file_resource->track_file_uuid));
458  return AVERROR_INVALIDDATA;
459  }
460 
461  av_log(s,
462  AV_LOG_DEBUG,
463  "Found locator for " AV_PRI_URN_UUID ": %s\n",
464  AV_UUID_ARG(asset_locator->uuid),
465  asset_locator->absolute_uri);
466 
467  if (track->resource_count > INT32_MAX - track_file_resource->base.repeat_count
468  || (track->resource_count + track_file_resource->base.repeat_count)
469  > INT_MAX / sizeof(IMFVirtualTrackResourcePlaybackCtx))
470  return AVERROR(ENOMEM);
471  tmp = av_fast_realloc(track->resources,
472  &track->resources_alloc_sz,
473  (track->resource_count + track_file_resource->base.repeat_count)
475  if (!tmp)
476  return AVERROR(ENOMEM);
477  track->resources = tmp;
478 
479  for (uint32_t i = 0; i < track_file_resource->base.repeat_count; i++) {
481 
482  vt_ctx.locator = asset_locator;
483  vt_ctx.resource = track_file_resource;
484  vt_ctx.ctx = NULL;
485  vt_ctx.start_time = track->duration;
486  vt_ctx.ts_offset = av_sub_q(vt_ctx.start_time,
487  av_div_q(av_make_q((int)track_file_resource->base.entry_point, 1),
488  track_file_resource->base.edit_rate));
489  vt_ctx.end_time = av_add_q(track->duration,
490  av_make_q((int)track_file_resource->base.duration
491  * track_file_resource->base.edit_rate.den,
492  track_file_resource->base.edit_rate.num));
493  track->resources[track->resource_count++] = vt_ctx;
494  track->duration = vt_ctx.end_time;
495  }
496 
497  return 0;
498 }
499 
501 {
502  for (uint32_t i = 0; i < track->resource_count; i++)
504 
505  av_freep(&track->resources);
506 }
507 
509  FFIMFTrackFileVirtualTrack *virtual_track,
511 {
512  IMFContext *c = s->priv_data;
514  void *tmp;
515  int ret = 0;
516 
517  if (!(track = av_mallocz(sizeof(IMFVirtualTrackPlaybackCtx))))
518  return AVERROR(ENOMEM);
519  track->current_resource_index = -1;
520  track->index = track_index;
521  track->duration = av_make_q(0, 1);
522 
523  for (uint32_t i = 0; i < virtual_track->resource_count; i++) {
524  av_log(s,
525  AV_LOG_DEBUG,
526  "Open stream from file " AV_PRI_URN_UUID ", stream %d\n",
527  AV_UUID_ARG(virtual_track->resources[i].track_file_uuid),
528  i);
529  if ((ret = open_track_file_resource(s, &virtual_track->resources[i], track)) != 0) {
530  av_log(s,
531  AV_LOG_ERROR,
532  "Could not open image track resource " AV_PRI_URN_UUID "\n",
533  AV_UUID_ARG(virtual_track->resources[i].track_file_uuid));
534  goto clean_up;
535  }
536  }
537 
538  track->current_timestamp = av_make_q(0, track->duration.den);
539 
540  if (c->track_count == UINT32_MAX) {
541  ret = AVERROR(ENOMEM);
542  goto clean_up;
543  }
544  tmp = av_realloc_array(c->tracks, c->track_count + 1, sizeof(IMFVirtualTrackPlaybackCtx *));
545  if (!tmp) {
546  ret = AVERROR(ENOMEM);
547  goto clean_up;
548  }
549  c->tracks = tmp;
550  c->tracks[c->track_count++] = track;
551 
552  return 0;
553 
554 clean_up:
556  av_free(track);
557  return ret;
558 }
559 
561 {
562  IMFContext *c = s->priv_data;
563  int ret = 0;
564 
565  for (uint32_t i = 0; i < c->track_count; i++) {
566  AVStream *asset_stream;
567  AVStream *first_resource_stream;
568 
569  /* Open the first resource of the track to get stream information */
570  ret = open_track_resource_context(s, c->tracks[i], 0);
571  if (ret)
572  return ret;
573  first_resource_stream = c->tracks[i]->resources[0].ctx->streams[0];
574  av_log(s, AV_LOG_DEBUG, "Open the first resource of track %d\n", c->tracks[i]->index);
575 
576  /* Copy stream information */
577  asset_stream = avformat_new_stream(s, NULL);
578  if (!asset_stream) {
579  av_log(s, AV_LOG_ERROR, "Could not create stream\n");
580  return AVERROR(ENOMEM);
581  }
582  asset_stream->id = i;
583  ret = avcodec_parameters_copy(asset_stream->codecpar, first_resource_stream->codecpar);
584  if (ret < 0) {
585  av_log(s, AV_LOG_ERROR, "Could not copy stream parameters\n");
586  return ret;
587  }
588  avpriv_set_pts_info(asset_stream,
589  first_resource_stream->pts_wrap_bits,
590  first_resource_stream->time_base.num,
591  first_resource_stream->time_base.den);
592  asset_stream->duration = (int64_t)av_q2d(av_mul_q(c->tracks[i]->duration,
593  av_inv_q(asset_stream->time_base)));
594  }
595 
596  return 0;
597 }
598 
600 {
601  IMFContext *c = s->priv_data;
602  int32_t track_index = 0;
603  int ret;
604 
605  if (c->cpl->main_image_2d_track) {
606  if ((ret = open_virtual_track(s, c->cpl->main_image_2d_track, track_index++)) != 0) {
607  av_log(s, AV_LOG_ERROR, "Could not open image track " AV_PRI_URN_UUID "\n",
608  AV_UUID_ARG(c->cpl->main_image_2d_track->base.id_uuid));
609  return ret;
610  }
611  }
612 
613  for (uint32_t i = 0; i < c->cpl->main_audio_track_count; i++) {
614  if ((ret = open_virtual_track(s, &c->cpl->main_audio_tracks[i], track_index++)) != 0) {
615  av_log(s, AV_LOG_ERROR, "Could not open audio track " AV_PRI_URN_UUID "\n",
616  AV_UUID_ARG(c->cpl->main_audio_tracks[i].base.id_uuid));
617  return ret;
618  }
619  }
620 
622 }
623 
625 {
626  IMFContext *c = s->priv_data;
627  char *asset_map_path;
628  char *tmp_str;
629  int ret = 0;
630 
631  c->interrupt_callback = &s->interrupt_callback;
632  tmp_str = av_strdup(s->url);
633  if (!tmp_str)
634  return AVERROR(ENOMEM);
635  c->base_url = av_strdup(av_dirname(tmp_str));
636  av_freep(&tmp_str);
637  if (!c->base_url)
638  return AVERROR(ENOMEM);
639 
640  if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0)
641  return ret;
642 
643  av_log(s, AV_LOG_DEBUG, "start parsing IMF CPL: %s\n", s->url);
644 
645  if ((ret = ff_imf_parse_cpl(s->pb, &c->cpl)) < 0)
646  return ret;
647 
648  av_log(s,
649  AV_LOG_DEBUG,
650  "parsed IMF CPL: " AV_PRI_URN_UUID "\n",
651  AV_UUID_ARG(c->cpl->id_uuid));
652 
653  if (!c->asset_map_paths) {
654  c->asset_map_paths = av_append_path_component(c->base_url, "ASSETMAP.xml");
655  if (!c->asset_map_paths) {
656  ret = AVERROR(ENOMEM);
657  return ret;
658  }
659  av_log(s, AV_LOG_DEBUG, "No asset maps provided, using the default ASSETMAP.xml\n");
660  }
661 
662  /* Parse each asset map XML file */
663  imf_asset_locator_map_init(&c->asset_locator_map);
664  asset_map_path = av_strtok(c->asset_map_paths, ",", &tmp_str);
665  while (asset_map_path != NULL) {
666  av_log(s, AV_LOG_DEBUG, "start parsing IMF Asset Map: %s\n", asset_map_path);
667 
668  if ((ret = parse_assetmap(s, asset_map_path)))
669  return ret;
670 
671  asset_map_path = av_strtok(NULL, ",", &tmp_str);
672  }
673 
674  av_log(s, AV_LOG_DEBUG, "parsed IMF Asset Maps\n");
675 
676  if ((ret = open_cpl_tracks(s)))
677  return ret;
678 
679  av_log(s, AV_LOG_DEBUG, "parsed IMF package\n");
680 
681  return 0;
682 }
683 
685 {
686  IMFContext *c = s->priv_data;
688 
689  AVRational minimum_timestamp = av_make_q(INT32_MAX, 1);
690  for (uint32_t i = c->track_count; i > 0; i--) {
691  av_log(s, AV_LOG_TRACE, "Compare track %d timestamp " AVRATIONAL_FORMAT
692  " to minimum " AVRATIONAL_FORMAT
693  " (over duration: " AVRATIONAL_FORMAT ")\n", i,
694  AVRATIONAL_ARG(c->tracks[i - 1]->current_timestamp),
695  AVRATIONAL_ARG(minimum_timestamp),
696  AVRATIONAL_ARG(c->tracks[i - 1]->duration));
697 
698  if (av_cmp_q(c->tracks[i - 1]->current_timestamp, minimum_timestamp) <= 0) {
699  track = c->tracks[i - 1];
700  minimum_timestamp = track->current_timestamp;
701  }
702  }
703 
704  av_log(s, AV_LOG_DEBUG, "Found next track to read: %d (timestamp: %lf / %lf)\n",
705  track->index, av_q2d(track->current_timestamp), av_q2d(minimum_timestamp));
706  return track;
707 }
708 
710 {
711  *resource = NULL;
712 
713  if (av_cmp_q(track->current_timestamp, track->duration) >= 0) {
714  av_log(s, AV_LOG_DEBUG, "Reached the end of the virtual track\n");
715  return AVERROR_EOF;
716  }
717 
718  av_log(s,
719  AV_LOG_TRACE,
720  "Looking for track %d resource for timestamp = %lf / %lf\n",
721  track->index,
722  av_q2d(track->current_timestamp),
723  av_q2d(track->duration));
724  for (uint32_t i = 0; i < track->resource_count; i++) {
725 
726  if (av_cmp_q(track->resources[i].end_time, track->current_timestamp) > 0) {
727  av_log(s, AV_LOG_DEBUG, "Found resource %d in track %d to read at timestamp %lf: "
728  "entry=%" PRIu32 ", duration=%" PRIu32 ", editrate=" AVRATIONAL_FORMAT "\n",
729  i, track->index, av_q2d(track->current_timestamp),
731  track->resources[i].resource->base.duration,
733 
734  if (track->current_resource_index != i) {
735  int ret;
736 
737  av_log(s, AV_LOG_TRACE, "Switch resource on track %d: re-open context\n",
738  track->index);
739 
740  ret = open_track_resource_context(s, track, i);
741  if (ret != 0)
742  return ret;
743  if (track->current_resource_index > 0)
745  track->current_resource_index = i;
746  }
747 
748  *resource = track->resources + track->current_resource_index;
749  return 0;
750  }
751  }
752 
753  av_log(s, AV_LOG_ERROR, "Could not find IMF track resource to read\n");
755 }
756 
758 {
760  int ret = 0;
762  int64_t delta_ts;
763  AVStream *st;
764  AVRational next_timestamp;
765 
767 
768  ret = get_resource_context_for_timestamp(s, track, &resource);
769  if (ret)
770  return ret;
771 
772  ret = av_read_frame(resource->ctx, pkt);
773  if (ret)
774  return ret;
775 
776  av_log(s, AV_LOG_DEBUG, "Got packet: pts=%" PRId64 ", dts=%" PRId64
777  ", duration=%" PRId64 ", stream_index=%d, pos=%" PRId64
778  ", time_base=" AVRATIONAL_FORMAT "\n", pkt->pts, pkt->dts, pkt->duration,
780 
781  /* IMF resources contain only one stream */
782 
783  if (pkt->stream_index != 0)
784  return AVERROR_INVALIDDATA;
785  st = resource->ctx->streams[0];
786 
787  pkt->stream_index = track->index;
788 
789  /* adjust the packet PTS and DTS based on the temporal position of the resource within the timeline */
790 
791  ret = imf_time_to_ts(&delta_ts, resource->ts_offset, st->time_base);
792 
793  if (!ret) {
794  if (pkt->pts != AV_NOPTS_VALUE)
795  pkt->pts += delta_ts;
796  if (pkt->dts != AV_NOPTS_VALUE)
797  pkt->dts += delta_ts;
798  } else {
799  av_log(s, AV_LOG_WARNING, "Incoherent time stamp " AVRATIONAL_FORMAT
800  " for time base " AVRATIONAL_FORMAT,
801  AVRATIONAL_ARG(resource->ts_offset),
803  }
804 
805  /* advance the track timestamp by the packet duration */
806 
807  next_timestamp = av_add_q(track->current_timestamp,
808  av_mul_q(av_make_q((int)pkt->duration, 1), st->time_base));
809 
810  /* if necessary, clamp the next timestamp to the end of the current resource */
811 
812  if (av_cmp_q(next_timestamp, resource->end_time) > 0) {
813 
814  int64_t new_pkt_dur;
815 
816  /* shrink the packet duration */
817 
818  ret = imf_time_to_ts(&new_pkt_dur,
819  av_sub_q(resource->end_time, track->current_timestamp),
820  st->time_base);
821 
822  if (!ret)
823  pkt->duration = new_pkt_dur;
824  else
825  av_log(s, AV_LOG_WARNING, "Incoherent time base in packet duration calculation\n");
826 
827  /* shrink the packet itself for audio essence */
828 
829  if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
830 
832  /* AV_CODEC_ID_PCM_S24LE is the only PCM format supported in IMF */
833  /* in this case, explicitly shrink the packet */
834 
835  int bytes_per_sample = av_get_exact_bits_per_sample(st->codecpar->codec_id) >> 3;
836  int64_t nbsamples = av_rescale_q(pkt->duration,
837  st->time_base,
838  av_make_q(1, st->codecpar->sample_rate));
839  av_shrink_packet(pkt, nbsamples * st->codecpar->ch_layout.nb_channels * bytes_per_sample);
840 
841  } else {
842  /* in all other cases, use side data to skip samples */
843  int64_t skip_samples;
844 
845  ret = imf_time_to_ts(&skip_samples,
846  av_sub_q(next_timestamp, resource->end_time),
847  av_make_q(1, st->codecpar->sample_rate));
848 
849  if (ret || skip_samples < 0 || skip_samples > UINT32_MAX) {
850  av_log(s, AV_LOG_WARNING, "Cannot skip audio samples\n");
851  } else {
852  uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
853  if (!side_data)
854  return AVERROR(ENOMEM);
855 
856  AV_WL32(side_data + 4, skip_samples); /* skip from end of this packet */
857  side_data[6] = 1; /* reason for end is convergence */
858  }
859  }
860 
861  next_timestamp = resource->end_time;
862 
863  } else {
864  av_log(s, AV_LOG_WARNING, "Non-audio packet duration reduced\n");
865  }
866  }
867 
868  track->current_timestamp = next_timestamp;
869 
870  return 0;
871 }
872 
874 {
875  IMFContext *c = s->priv_data;
876 
877  av_log(s, AV_LOG_DEBUG, "Close IMF package\n");
878  av_dict_free(&c->avio_opts);
879  av_freep(&c->base_url);
880  imf_asset_locator_map_deinit(&c->asset_locator_map);
881  ff_imf_cpl_free(c->cpl);
882 
883  for (uint32_t i = 0; i < c->track_count; i++) {
885  av_freep(&c->tracks[i]);
886  }
887 
888  av_freep(&c->tracks);
889 
890  return 0;
891 }
892 
893 static int imf_probe(const AVProbeData *p)
894 {
895  if (!strstr(p->buf, "<CompositionPlaylist"))
896  return 0;
897 
898  /* check for a ContentTitle element without including ContentTitleText,
899  * which is used by the D-Cinema CPL.
900  */
901  if (!strstr(p->buf, "ContentTitle>"))
902  return 0;
903 
904  return AVPROBE_SCORE_MAX;
905 }
906 
907 static int coherent_ts(int64_t ts, AVRational in_tb, AVRational out_tb)
908 {
909  int dst_num;
910  int dst_den;
911  int ret;
912 
913  ret = av_reduce(&dst_num, &dst_den, ts * in_tb.num * out_tb.den,
914  in_tb.den * out_tb.num, INT64_MAX);
915  if (!ret || dst_den != 1)
916  return 0;
917 
918  return 1;
919 }
920 
921 static int imf_seek(AVFormatContext *s, int stream_index, int64_t min_ts,
922  int64_t ts, int64_t max_ts, int flags)
923 {
924  IMFContext *c = s->priv_data;
925  uint32_t i;
926 
928  return AVERROR(ENOSYS);
929 
930  /* rescale timestamps to Composition edit units */
931  if (stream_index < 0)
933  av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
934  &min_ts, &ts, &max_ts);
935  else
936  ff_rescale_interval(s->streams[stream_index]->time_base,
937  av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
938  &min_ts, &ts, &max_ts);
939 
940  /* requested timestamp bounds are too close */
941  if (max_ts < min_ts)
942  return -1;
943 
944  /* clamp requested timestamp to provided bounds */
945  ts = FFMAX(FFMIN(ts, max_ts), min_ts);
946 
947  av_log(s, AV_LOG_DEBUG, "Seeking to Composition Playlist edit unit %" PRIi64 "\n", ts);
948 
949  /* set the dts of each stream and temporal offset of each track */
950  for (i = 0; i < c->track_count; i++) {
951  AVStream *st = s->streams[i];
952  IMFVirtualTrackPlaybackCtx *t = c->tracks[i];
953  int64_t dts;
954 
955  if (!coherent_ts(ts, av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
956  st->time_base))
957  av_log(s, AV_LOG_WARNING, "Seek position is not coherent across tracks\n");
958 
959  dts = av_rescale(ts,
960  st->time_base.den * c->cpl->edit_rate.den,
961  st->time_base.num * c->cpl->edit_rate.num);
962 
963  av_log(s, AV_LOG_DEBUG, "Seeking to dts=%" PRId64 " on stream_index=%d\n",
964  dts, i);
965 
966  t->current_timestamp = av_mul_q(av_make_q(dts, 1), st->time_base);
967  if (t->current_resource_index >= 0) {
969  t->current_resource_index = -1;
970  }
971  }
972 
973  return 0;
974 }
975 
976 static const AVOption imf_options[] = {
977  {
978  .name = "assetmaps",
979  .help = "Comma-separated paths to ASSETMAP files."
980  "If not specified, the `ASSETMAP.xml` file in the same "
981  "directory as the CPL is used.",
982  .offset = offsetof(IMFContext, asset_map_paths),
983  .type = AV_OPT_TYPE_STRING,
984  .default_val = {.str = NULL},
986  },
987  {NULL},
988 };
989 
990 static const AVClass imf_class = {
991  .class_name = "imf",
992  .item_name = av_default_item_name,
993  .option = imf_options,
994  .version = LIBAVUTIL_VERSION_INT,
995 };
996 
998  .name = "imf",
999  .long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"),
1001  .flags_internal = FF_FMT_INIT_CLEANUP,
1002  .priv_class = &imf_class,
1003  .priv_data_size = sizeof(IMFContext),
1004  .read_probe = imf_probe,
1007  .read_close = imf_close,
1008  .read_seek2 = imf_seek,
1009 };
FFIMFTrackFileVirtualTrack::resources
FFIMFTrackFileResource * resources
Resource elements of the Virtual Track.
Definition: imf.h:113
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
IMFVirtualTrackResourcePlaybackCtx::ts_offset
AVRational ts_offset
start_time minus the entry point into the resource (s)
Definition: imfdec.c:104
AVFMT_NO_BYTE_SEEK
#define AVFMT_NO_BYTE_SEEK
Format does not allow seeking by bytes.
Definition: avformat.h:489
ffio_copy_url_options
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:1023
FF_FMT_INIT_CLEANUP
#define FF_FMT_INIT_CLEANUP
For an AVInputFormat with this flag set read_close() needs to be called by the caller upon read_heade...
Definition: internal.h:48
r
const char * r
Definition: vf_curves.c:116
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: options.c:237
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:57
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
set_context_streams_from_tracks
static int set_context_streams_from_tracks(AVFormatContext *s)
Definition: imfdec.c:560
AVUUID
uint8_t AVUUID[AV_UUID_LEN]
Definition: uuid.h:60
AVSEEK_FLAG_FRAME
#define AVSEEK_FLAG_FRAME
seeking based on frame number
Definition: avformat.h:2292
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
parse_assetmap
static int parse_assetmap(AVFormatContext *s, const char *url)
Definition: imfdec.c:291
AV_UUID_ARG
#define AV_UUID_ARG(x)
Definition: uuid.h:51
track_index
static int track_index(VividasDemuxContext *viv, AVFormatContext *s, uint8_t *buf, unsigned size)
Definition: vividas.c:435
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
IMFVirtualTrackResourcePlaybackCtx
Definition: imfdec.c:98
av_div_q
AVRational av_div_q(AVRational b, AVRational c)
Divide one rational by another.
Definition: rational.c:88
imf_close
static int imf_close(AVFormatContext *s)
Definition: imfdec.c:873
find_asset_map_locator
static IMFAssetLocator * find_asset_map_locator(IMFAssetLocatorMap *asset_map, AVUUID uuid)
Definition: imfdec.c:346
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:218
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
cleanup
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:130
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1281
FFIMFTrackFileVirtualTrack::resource_count
uint32_t resource_count
Number of Resource elements present in the Virtual Track.
Definition: imf.h:112
AVOption
AVOption.
Definition: opt.h:251
AVFMT_FLAG_CUSTOM_IO
#define AVFMT_FLAG_CUSTOM_IO
The caller has supplied a custom AVIOContext, don't avio_close() it.
Definition: avformat.h:1339
AVSEEK_FLAG_BYTE
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition: avformat.h:2290
IMFVirtualTrackResourcePlaybackCtx::start_time
AVRational start_time
inclusive start time of the resource on the CPL timeline (s)
Definition: imfdec.c:102
IMFContext::asset_locator_map
IMFAssetLocatorMap asset_locator_map
Definition: imfdec.c:125
imf_probe
static int imf_probe(const AVProbeData *p)
Definition: imfdec.c:893
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:392
AVDictionary
Definition: dict.c:30
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_sub_q
AVRational av_sub_q(AVRational b, AVRational c)
Subtract one rational from another.
Definition: rational.c:101
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: demux.c:1438
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:300
IMFContext::asset_map_paths
char * asset_map_paths
Definition: imfdec.c:121
IMFAssetLocatorMap::asset_count
uint32_t asset_count
Definition: imfdec.c:94
AVIOInterruptCB
Callback for checking whether to abort blocking functions.
Definition: avio.h:59
imf_uri_is_unix_abs_path
static int imf_uri_is_unix_abs_path(const char *string)
Definition: imfdec.c:135
av_append_path_component
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition: avstring.c:307
AVPROBE_SCORE_MAX
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:465
avformat_close_input
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: demux.c:368
coherent_ts
static int coherent_ts(int64_t ts, AVRational in_tb, AVRational out_tb)
Definition: imfdec.c:907
AVRATIONAL_ARG
#define AVRATIONAL_ARG(rational)
Definition: imfdec.c:79
mxf.h
avpriv_set_pts_info
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:697
imf_uri_is_dos_abs_path
static int imf_uri_is_dos_abs_path(const char *string)
Definition: imfdec.c:140
IMFVirtualTrackPlaybackCtx::resource_count
uint32_t resource_count
Number of resources (<= INT32_MAX)
Definition: imfdec.c:111
av_shrink_packet
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
Definition: avpacket.c:112
ff_imf_cpl_free
void ff_imf_cpl_free(FFIMFCPL *cpl)
Deletes an FFIMFCPL data structure previously instantiated with ff_imf_cpl_alloc().
Definition: imf_cpl.c:751
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
FFIMFBaseResource::duration
uint32_t duration
BaseResourceType/Duration.
Definition: imf.h:70
ff_imf_xml_get_child_element_by_name
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
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:487
AVStream::duration
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:998
av_reduce
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
AVRational::num
int num
Numerator.
Definition: rational.h:59
av_dirname
const char * av_dirname(char *path)
Thread safe dirname.
Definition: avstring.c:286
IMFAssetLocator::uuid
AVUUID uuid
Definition: imfdec.c:85
open_track_file_resource
static int open_track_file_resource(AVFormatContext *s, FFIMFTrackFileResource *track_file_resource, IMFVirtualTrackPlaybackCtx *track)
Definition: imfdec.c:446
IMFContext::track_count
uint32_t track_count
Definition: imfdec.c:126
imf_seek
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:921
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:206
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
AVInputFormat
Definition: avformat.h:656
FFIMFTrackFileVirtualTrack
IMF Composition Playlist Virtual Track that consists of Track File Resources.
Definition: imf.h:110
avformat_open_input
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:220
IMFVirtualTrackPlaybackCtx::current_timestamp
AVRational current_timestamp
Current temporal position.
Definition: imfdec.c:109
av_fast_realloc
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:505
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:256
avio_read_to_bprint
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:1355
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:225
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1331
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:661
AVProbeData::buf
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:455
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
av_strtok
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:189
imf_options
static const AVOption imf_options[]
Definition: imfdec.c:976
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
IMFVirtualTrackResourcePlaybackCtx::locator
IMFAssetLocator * locator
Location of the resource.
Definition: imfdec.c:99
IMFAssetLocator
IMF Asset locator.
Definition: imfdec.c:84
IMFVirtualTrackPlaybackCtx
Definition: imfdec.c:107
get_next_track_with_minimum_timestamp
static IMFVirtualTrackPlaybackCtx * get_next_track_with_minimum_timestamp(AVFormatContext *s)
Definition: imfdec.c:684
IMFVirtualTrackResourcePlaybackCtx::resource
FFIMFTrackFileResource * resource
Underlying IMF CPL resource.
Definition: imfdec.c:100
AVFormatContext
Format I/O context.
Definition: avformat.h:1213
internal.h
IMFVirtualTrackResourcePlaybackCtx::ctx
AVFormatContext * ctx
Context associated with the resource.
Definition: imfdec.c:101
opts
AVDictionary * opts
Definition: movenc.c:50
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1108
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:532
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:978
NULL
#define NULL
Definition: coverity.c:32
read_probe
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
ff_copy_whiteblacklists
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition: avformat.c:741
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:453
ff_rescale_interval
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:756
imf_uri_is_url
static int imf_uri_is_url(const char *string)
Definition: imfdec.c:130
IMFContext::interrupt_callback
AVIOInterruptCB * interrupt_callback
Definition: imfdec.c:122
get_resource_context_for_timestamp
static int get_resource_context_for_timestamp(AVFormatContext *s, IMFVirtualTrackPlaybackCtx *track, IMFVirtualTrackResourcePlaybackCtx **resource)
Definition: imfdec.c:709
ff_imf_demuxer
const AVInputFormat ff_imf_demuxer
Definition: imfdec.c:997
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:212
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
open_track_resource_context
static int open_track_resource_context(AVFormatContext *s, IMFVirtualTrackPlaybackCtx *track, int32_t resource_index)
Definition: imfdec.c:355
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:177
IMFAssetLocator::absolute_uri
char * absolute_uri
Definition: imfdec.c:86
IMFVirtualTrackResourcePlaybackCtx::end_time
AVRational end_time
exclusive end time of the resource on the CPL timeline (s)
Definition: imfdec.c:103
AVFormatContext::nb_streams
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1269
imf_read_packet
static int imf_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: imfdec.c:757
av_get_exact_bits_per_sample
int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
Return codec bits per sample.
Definition: utils.c:495
FFIMFBaseResource::edit_rate
AVRational edit_rate
BaseResourceType/EditRate.
Definition: imf.h:68
AVIOContext
Bytestream IO Context.
Definition: avio.h:162
AV_CODEC_ID_PCM_S24LE
@ AV_CODEC_ID_PCM_S24LE
Definition: codec_id.h:330
imf_asset_locator_map_deinit
static void imf_asset_locator_map_deinit(IMFAssetLocatorMap *asset_map)
Free a IMFAssetLocatorMap pointer.
Definition: imfdec.c:283
FFIMFTrackFileResource::track_file_uuid
AVUUID track_file_uuid
TrackFileResourceType/TrackFileId.
Definition: imf.h:79
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:164
IMFContext::cpl
FFIMFCPL * cpl
Definition: imfdec.c:124
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:121
imf_asset_locator_map_init
static void imf_asset_locator_map_init(IMFAssetLocatorMap *asset_map)
Initializes an IMFAssetLocatorMap structure.
Definition: imfdec.c:274
av_make_q
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
avformat_seek_file
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:657
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
ff_format_io_close
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: avformat.c:779
AVOption::name
const char * name
Definition: opt.h:252
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:373
AV_PRI_URN_UUID
#define AV_PRI_URN_UUID
Definition: uuid.h:43
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
open_cpl_tracks
static int open_cpl_tracks(AVFormatContext *s)
Definition: imfdec.c:599
AVRATIONAL_FORMAT
#define AVRATIONAL_FORMAT
Definition: imfdec.c:78
FFIMFBaseResource::repeat_count
uint32_t repeat_count
BaseResourceType/RepeatCount.
Definition: imf.h:71
IMFVirtualTrackPlaybackCtx::current_resource_index
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
ff_imf_parse_cpl
int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl)
Parse an IMF Composition Playlist document into the FFIMFCPL data structure.
Definition: imf_cpl.c:777
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:74
bprint.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:367
avio_internal.h
packet.h
FFIMFBaseResource::entry_point
uint32_t entry_point
BaseResourceType/EntryPoint.
Definition: imf.h:69
imf_read_header
static int imf_read_header(AVFormatContext *s)
Definition: imfdec.c:624
AV_OPT_FLAG_DECODING_PARAM
#define AV_OPT_FLAG_DECODING_PARAM
a generic parameter which can be set by the user for demuxing or decoding
Definition: opt.h:282
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:264
AVFMT_EXPERIMENTAL
#define AVFMT_EXPERIMENTAL
The muxer/demuxer is experimental and should be used with caution.
Definition: avformat.h:478
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
demux.h
AV_PKT_DATA_SKIP_SAMPLES
@ AV_PKT_DATA_SKIP_SAMPLES
Recommmends skipping the specified number of samples.
Definition: packet.h:157
imf_virtual_track_playback_context_deinit
static void imf_virtual_track_playback_context_deinit(IMFVirtualTrackPlaybackCtx *track)
Definition: imfdec.c:500
IMFVirtualTrackPlaybackCtx::index
int32_t index
Track index in playlist.
Definition: imfdec.c:108
parse_imf_asset_map_from_xml_dom
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
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
imf_time_to_ts
static int imf_time_to_ts(int64_t *ts, AVRational t, AVRational time_base)
Definition: imfdec.c:157
av_cmp_q
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
AVStream::id
int id
Format-specific stream ID.
Definition: avformat.h:962
ret
ret
Definition: filter_design.txt:187
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
AVStream
Stream structure.
Definition: avformat.h:948
IMFAssetLocatorMap
IMF Asset locator map Results from the parsing of one or more ASSETMAP XML files.
Definition: imfdec.c:93
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
IMFContext
Definition: imfdec.c:118
IMFVirtualTrackPlaybackCtx::duration
AVRational duration
Overall duration.
Definition: imfdec.c:110
IMFVirtualTrackPlaybackCtx::resources_alloc_sz
unsigned int resources_alloc_sz
Size of the buffer holding the resource.
Definition: imfdec.c:112
FFIMFTrackFileResource
IMF Composition Playlist Track File Resource.
Definition: imf.h:77
av_packet_new_side_data
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, size_t size)
Allocate new information of a packet.
Definition: avpacket.c:230
AVERROR_STREAM_NOT_FOUND
#define AVERROR_STREAM_NOT_FOUND
Stream not found.
Definition: error.h:67
AVRational::den
int den
Denominator.
Definition: rational.h:60
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: avformat.c:95
open_virtual_track
static int open_virtual_track(AVFormatContext *s, FFIMFTrackFileVirtualTrack *virtual_track, int32_t track_index)
Definition: imfdec.c:508
AVFormatContext::io_close
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1779
IMFContext::avio_opts
AVDictionary * avio_opts
Definition: imfdec.c:123
AVFormatContext::io_open
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:1773
av_mul_q
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
AVPacket::stream_index
int stream_index
Definition: packet.h:376
imf_class
static const AVClass imf_class
Definition: imfdec.c:990
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:628
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:280
IMFContext::tracks
IMFVirtualTrackPlaybackCtx ** tracks
Definition: imfdec.c:127
ff_imf_xml_read_uuid
int ff_imf_xml_read_uuid(xmlNodePtr element, AVUUID uuid)
Reads a UUID from an XML element.
Definition: imf_cpl.c:73
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
av_add_q
AVRational av_add_q(AVRational b, AVRational c)
Add two rationals.
Definition: rational.c:93
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:61
AVPacket
This structure stores compressed data.
Definition: packet.h:351
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_copy
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:394
AVFormatContext::io_close2
int(* io_close2)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1820
int32_t
int32_t
Definition: audioconvert.c:56
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
IMFContext::base_url
const char * base_url
Definition: imfdec.c:120
FFIMFCPL
IMF Composition Playlist.
Definition: imf.h:129
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
imf.h
Public header file for the processing of Interoperable Master Format (IMF) packages.
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
IMFVirtualTrackPlaybackCtx::resources
IMFVirtualTrackResourcePlaybackCtx * resources
Buffer holding the resources.
Definition: imfdec.c:113
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
AVStream::pts_wrap_bits
int pts_wrap_bits
Number of bits in timestamps.
Definition: avformat.h:1117
FFIMFTrackFileResource::base
FFIMFBaseResource base
Definition: imf.h:78
AVPacket::time_base
AVRational time_base
Time base of the packet's timestamps.
Definition: packet.h:418
IMFAssetLocatorMap::assets
IMFAssetLocator * assets
Definition: imfdec.c:95
avio_feof
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:375