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/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  */
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\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 
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 (!(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  asset_element = xmlNextElementSibling(asset_element);
284  }
285 
286  return ret;
287 }
288 
289 /**
290  * Initializes an IMFAssetLocatorMap structure.
291  */
293 {
294  asset_map->assets = NULL;
295  asset_map->asset_count = 0;
296 }
297 
298 /**
299  * Free a IMFAssetLocatorMap pointer.
300  */
302 {
303  for (uint32_t i = 0; i < asset_map->asset_count; i++)
304  av_freep(&asset_map->assets[i].absolute_uri);
305 
306  av_freep(&asset_map->assets);
307 }
308 
309 static int parse_assetmap(AVFormatContext *s, const char *url)
310 {
311  IMFContext *c = s->priv_data;
312  AVIOContext *in = NULL;
313  struct AVBPrint buf;
315  xmlDoc *doc = NULL;
316  const char *base_url;
317  char *tmp_str = NULL;
318  int ret;
319 
320  av_log(s, AV_LOG_DEBUG, "Asset Map URL: %s\n", url);
321 
322  av_dict_copy(&opts, c->avio_opts, 0);
323  ret = s->io_open(s, &in, url, AVIO_FLAG_READ, &opts);
324  av_dict_free(&opts);
325  if (ret < 0)
326  return ret;
327 
328  av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer length
329 
330  ret = avio_read_to_bprint(in, &buf, SIZE_MAX);
331  if (ret < 0 || !avio_feof(in)) {
332  av_log(s, AV_LOG_ERROR, "Unable to read to asset map '%s'\n", url);
333  if (ret == 0)
335  goto clean_up;
336  }
337 
338  LIBXML_TEST_VERSION
339 
340  tmp_str = av_strdup(url);
341  if (!tmp_str) {
342  ret = AVERROR(ENOMEM);
343  goto clean_up;
344  }
345  base_url = av_dirname(tmp_str);
346 
347  doc = xmlReadMemory(buf.str, buf.len, url, NULL, 0);
348 
349  ret = parse_imf_asset_map_from_xml_dom(s, doc, &c->asset_locator_map, base_url);
350  if (!ret)
351  av_log(s, AV_LOG_DEBUG, "Found %d assets from %s\n",
352  c->asset_locator_map.asset_count, url);
353 
354  xmlFreeDoc(doc);
355 
356 clean_up:
357  if (tmp_str)
358  av_freep(&tmp_str);
359  ff_format_io_close(s, &in);
360  av_bprint_finalize(&buf, NULL);
361  return ret;
362 }
363 
365 {
366  for (uint32_t i = 0; i < asset_map->asset_count; i++) {
367  if (memcmp(asset_map->assets[i].uuid, uuid, 16) == 0)
368  return &(asset_map->assets[i]);
369  }
370  return NULL;
371 }
372 
375  int32_t resource_index)
376 {
377  IMFContext *c = s->priv_data;
378  int ret = 0;
379  int64_t seek_offset = 0;
381  AVStream *st;
382  IMFVirtualTrackResourcePlaybackCtx *track_resource = track->resources + resource_index;
383 
384  if (track_resource->ctx) {
385  av_log(s, AV_LOG_DEBUG, "Input context already opened for %s.\n",
386  track_resource->locator->absolute_uri);
387  return 0;
388  }
389 
390  track_resource->ctx = avformat_alloc_context();
391  if (!track_resource->ctx)
392  return AVERROR(ENOMEM);
393 
394  track_resource->ctx->io_open = s->io_open;
395  track_resource->ctx->io_close2 = s->io_close2;
396  track_resource->ctx->opaque = s->opaque;
397  track_resource->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO;
398 
399  if ((ret = ff_copy_whiteblacklists(track_resource->ctx, s)) < 0)
400  goto cleanup;
401 
402  if ((ret = av_opt_set(track_resource->ctx, "format_whitelist", "mxf", 0)))
403  goto cleanup;
404 
405  if ((ret = av_dict_copy(&opts, c->avio_opts, 0)) < 0)
406  goto cleanup;
407 
408  ret = avformat_open_input(&track_resource->ctx,
409  track_resource->locator->absolute_uri,
410  NULL,
411  &opts);
412  if (ret < 0) {
413  av_log(s, AV_LOG_ERROR, "Could not open %s input context: %s\n",
414  track_resource->locator->absolute_uri, av_err2str(ret));
415  goto cleanup;
416  }
417  av_dict_free(&opts);
418 
419  /* make sure there is only one stream in the file */
420 
421  if (track_resource->ctx->nb_streams != 1) {
423  goto cleanup;
424  }
425 
426  st = track_resource->ctx->streams[0];
427 
428  /* Determine the seek offset into the Track File, taking into account:
429  * - the current timestamp within the virtual track
430  * - the entry point of the resource
431  */
432  if (imf_time_to_ts(&seek_offset,
433  av_sub_q(track->current_timestamp, track_resource->ts_offset),
434  st->time_base))
435  av_log(s, AV_LOG_WARNING, "Incoherent stream timebase " AVRATIONAL_FORMAT
436  "and composition timeline position: " AVRATIONAL_FORMAT "\n",
438 
439  if (seek_offset) {
440  av_log(s, AV_LOG_DEBUG, "Seek at resource %s entry point: %" PRIi64 "\n",
441  track_resource->locator->absolute_uri, seek_offset);
442  ret = avformat_seek_file(track_resource->ctx, 0, seek_offset, seek_offset, seek_offset, 0);
443  if (ret < 0) {
444  av_log(s,
445  AV_LOG_ERROR,
446  "Could not seek at %" PRId64 "on %s: %s\n",
447  seek_offset,
448  track_resource->locator->absolute_uri,
449  av_err2str(ret));
450  avformat_close_input(&track_resource->ctx);
451  return ret;
452  }
453  }
454 
455  return 0;
456 
457 cleanup:
458  av_dict_free(&opts);
459  avformat_free_context(track_resource->ctx);
460  track_resource->ctx = NULL;
461  return ret;
462 }
463 
465  FFIMFTrackFileResource *track_file_resource,
467 {
468  IMFContext *c = s->priv_data;
469  IMFAssetLocator *asset_locator;
470  void *tmp;
471 
472  asset_locator = find_asset_map_locator(&c->asset_locator_map, track_file_resource->track_file_uuid);
473  if (!asset_locator) {
474  av_log(s, AV_LOG_ERROR, "Could not find asset locator for UUID: " AV_PRI_URN_UUID "\n",
475  AV_UUID_ARG(track_file_resource->track_file_uuid));
476  return AVERROR_INVALIDDATA;
477  }
478 
479  av_log(s,
480  AV_LOG_DEBUG,
481  "Found locator for " AV_PRI_URN_UUID ": %s\n",
482  AV_UUID_ARG(asset_locator->uuid),
483  asset_locator->absolute_uri);
484 
485  if (track->resource_count > INT32_MAX - track_file_resource->base.repeat_count
486  || (track->resource_count + track_file_resource->base.repeat_count)
487  > INT_MAX / sizeof(IMFVirtualTrackResourcePlaybackCtx))
488  return AVERROR(ENOMEM);
489  tmp = av_fast_realloc(track->resources,
490  &track->resources_alloc_sz,
491  (track->resource_count + track_file_resource->base.repeat_count)
493  if (!tmp)
494  return AVERROR(ENOMEM);
495  track->resources = tmp;
496 
497  for (uint32_t i = 0; i < track_file_resource->base.repeat_count; i++) {
499 
500  vt_ctx.locator = asset_locator;
501  vt_ctx.resource = track_file_resource;
502  vt_ctx.ctx = NULL;
503  vt_ctx.start_time = track->duration;
504  vt_ctx.ts_offset = av_sub_q(vt_ctx.start_time,
505  av_div_q(av_make_q((int)track_file_resource->base.entry_point, 1),
506  track_file_resource->base.edit_rate));
507  vt_ctx.end_time = av_add_q(track->duration,
508  av_make_q((int)track_file_resource->base.duration
509  * track_file_resource->base.edit_rate.den,
510  track_file_resource->base.edit_rate.num));
511  track->resources[track->resource_count++] = vt_ctx;
512  track->duration = vt_ctx.end_time;
513  }
514 
515  return 0;
516 }
517 
519 {
520  for (uint32_t i = 0; i < track->resource_count; i++)
522 
523  av_freep(&track->resources);
524 }
525 
527  FFIMFTrackFileVirtualTrack *virtual_track,
529 {
530  IMFContext *c = s->priv_data;
532  void *tmp;
533  int ret = 0;
534 
535  if (!(track = av_mallocz(sizeof(IMFVirtualTrackPlaybackCtx))))
536  return AVERROR(ENOMEM);
537  track->current_resource_index = -1;
538  track->index = track_index;
539  track->duration = av_make_q(0, 1);
540 
541  if (!virtual_track->resource_count) {
542  av_log(s, AV_LOG_ERROR, "Virtual track has no resources\n");
544  goto clean_up;
545  }
546 
547  for (uint32_t i = 0; i < virtual_track->resource_count; i++) {
548  av_log(s,
549  AV_LOG_DEBUG,
550  "Open stream from file " AV_PRI_URN_UUID ", stream %d\n",
551  AV_UUID_ARG(virtual_track->resources[i].track_file_uuid),
552  i);
553  if ((ret = open_track_file_resource(s, &virtual_track->resources[i], track)) != 0) {
554  av_log(s,
555  AV_LOG_ERROR,
556  "Could not open image track resource " AV_PRI_URN_UUID "\n",
557  AV_UUID_ARG(virtual_track->resources[i].track_file_uuid));
558  goto clean_up;
559  }
560  }
561 
562  track->current_timestamp = av_make_q(0, track->duration.den);
563 
564  if (c->track_count == UINT32_MAX) {
565  ret = AVERROR(ENOMEM);
566  goto clean_up;
567  }
568  tmp = av_realloc_array(c->tracks, c->track_count + 1, sizeof(IMFVirtualTrackPlaybackCtx *));
569  if (!tmp) {
570  ret = AVERROR(ENOMEM);
571  goto clean_up;
572  }
573  c->tracks = tmp;
574  c->tracks[c->track_count++] = track;
575 
576  return 0;
577 
578 clean_up:
580  av_free(track);
581  return ret;
582 }
583 
585 {
586  IMFContext *c = s->priv_data;
587  int ret = 0;
588 
589  for (uint32_t i = 0; i < c->track_count; i++) {
590  AVStream *asset_stream;
591  AVStream *first_resource_stream;
592 
593  /* Open the first resource of the track to get stream information */
594  ret = open_track_resource_context(s, c->tracks[i], 0);
595  if (ret)
596  return ret;
597  first_resource_stream = c->tracks[i]->resources[0].ctx->streams[0];
598  av_log(s, AV_LOG_DEBUG, "Open the first resource of track %d\n", c->tracks[i]->index);
599 
600  asset_stream = ff_stream_clone(s, first_resource_stream);
601  if (!asset_stream) {
602  av_log(s, AV_LOG_ERROR, "Could not clone stream\n");
603  return AVERROR(ENOMEM);
604  }
605 
606  asset_stream->id = i;
607  asset_stream->nb_frames = 0;
608  avpriv_set_pts_info(asset_stream,
609  first_resource_stream->pts_wrap_bits,
610  first_resource_stream->time_base.num,
611  first_resource_stream->time_base.den);
612  asset_stream->duration = (int64_t)av_q2d(av_mul_q(c->tracks[i]->duration,
613  av_inv_q(asset_stream->time_base)));
614  }
615 
616  return 0;
617 }
618 
620 {
621  IMFContext *c = s->priv_data;
622  int32_t track_index = 0;
623  int ret;
624 
625  if (c->cpl->main_image_2d_track) {
626  if ((ret = open_virtual_track(s, c->cpl->main_image_2d_track, track_index++)) != 0) {
627  av_log(s, AV_LOG_ERROR, "Could not open image track " AV_PRI_URN_UUID "\n",
628  AV_UUID_ARG(c->cpl->main_image_2d_track->base.id_uuid));
629  return ret;
630  }
631  }
632 
633  for (uint32_t i = 0; i < c->cpl->main_audio_track_count; i++) {
634  if ((ret = open_virtual_track(s, &c->cpl->main_audio_tracks[i], track_index++)) != 0) {
635  av_log(s, AV_LOG_ERROR, "Could not open audio track " AV_PRI_URN_UUID "\n",
636  AV_UUID_ARG(c->cpl->main_audio_tracks[i].base.id_uuid));
637  return ret;
638  }
639  }
640 
642 }
643 
645 {
646  IMFContext *c = s->priv_data;
647  char *asset_map_path;
648  char *tmp_str;
649  AVDictionaryEntry* tcr;
650  char tc_buf[AV_TIMECODE_STR_SIZE];
651  int ret = 0;
652 
653  c->interrupt_callback = &s->interrupt_callback;
654  tmp_str = av_strdup(s->url);
655  if (!tmp_str)
656  return AVERROR(ENOMEM);
657  c->base_url = av_strdup(av_dirname(tmp_str));
658  av_freep(&tmp_str);
659  if (!c->base_url)
660  return AVERROR(ENOMEM);
661 
662  if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0)
663  return ret;
664 
665  av_log(s, AV_LOG_DEBUG, "start parsing IMF CPL: %s\n", s->url);
666 
667  if ((ret = ff_imf_parse_cpl(s, s->pb, &c->cpl)) < 0)
668  return ret;
669 
670  tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
671  if (!tcr && c->cpl->tc) {
672  ret = av_dict_set(&s->metadata, "timecode",
673  av_timecode_make_string(c->cpl->tc, tc_buf, 0), 0);
674  if (ret)
675  return ret;
676  av_log(s, AV_LOG_INFO, "Setting timecode to IMF CPL timecode %s\n", tc_buf);
677  }
678 
679  av_log(s,
680  AV_LOG_DEBUG,
681  "parsed IMF CPL: " AV_PRI_URN_UUID "\n",
682  AV_UUID_ARG(c->cpl->id_uuid));
683 
684  if (!c->asset_map_paths) {
685  c->asset_map_paths = av_append_path_component(c->base_url, "ASSETMAP.xml");
686  if (!c->asset_map_paths) {
687  ret = AVERROR(ENOMEM);
688  return ret;
689  }
690  av_log(s, AV_LOG_DEBUG, "No asset maps provided, using the default ASSETMAP.xml\n");
691  }
692 
693  /* Parse each asset map XML file */
694  imf_asset_locator_map_init(&c->asset_locator_map);
695  asset_map_path = av_strtok(c->asset_map_paths, ",", &tmp_str);
696  while (asset_map_path != NULL) {
697  av_log(s, AV_LOG_DEBUG, "start parsing IMF Asset Map: %s\n", asset_map_path);
698 
699  if ((ret = parse_assetmap(s, asset_map_path)))
700  return ret;
701 
702  asset_map_path = av_strtok(NULL, ",", &tmp_str);
703  }
704 
705  av_log(s, AV_LOG_DEBUG, "parsed IMF Asset Maps\n");
706 
707  if ((ret = open_cpl_tracks(s)))
708  return ret;
709 
710  av_log(s, AV_LOG_DEBUG, "parsed IMF package\n");
711 
712  return 0;
713 }
714 
716 {
717  IMFContext *c = s->priv_data;
719  AVRational minimum_timestamp = av_make_q(INT32_MAX, 1);
720 
721  for (uint32_t i = c->track_count; i > 0; i--) {
722  av_log(s, AV_LOG_TRACE, "Compare track %d timestamp " AVRATIONAL_FORMAT
723  " to minimum " AVRATIONAL_FORMAT
724  " (over duration: " AVRATIONAL_FORMAT ")\n", i,
725  AVRATIONAL_ARG(c->tracks[i - 1]->current_timestamp),
726  AVRATIONAL_ARG(minimum_timestamp),
727  AVRATIONAL_ARG(c->tracks[i - 1]->duration));
728 
729  if (av_cmp_q(c->tracks[i - 1]->current_timestamp, minimum_timestamp) <= 0) {
730  track = c->tracks[i - 1];
731  minimum_timestamp = track->current_timestamp;
732  }
733  }
734 
735  return track;
736 }
737 
739 {
740  *resource = NULL;
741 
742  if (av_cmp_q(track->current_timestamp, track->duration) >= 0) {
743  av_log(s, AV_LOG_DEBUG, "Reached the end of the virtual track\n");
744  return AVERROR_EOF;
745  }
746 
747  av_log(s,
748  AV_LOG_TRACE,
749  "Looking for track %d resource for timestamp = %lf / %lf\n",
750  track->index,
751  av_q2d(track->current_timestamp),
752  av_q2d(track->duration));
753  for (uint32_t i = 0; i < track->resource_count; i++) {
754 
755  if (av_cmp_q(track->resources[i].end_time, track->current_timestamp) > 0) {
756  av_log(s, AV_LOG_DEBUG, "Found resource %d in track %d to read at timestamp %lf: "
757  "entry=%" PRIu32 ", duration=%" PRIu32 ", editrate=" AVRATIONAL_FORMAT "\n",
758  i, track->index, av_q2d(track->current_timestamp),
760  track->resources[i].resource->base.duration,
762 
763  if (track->current_resource_index != i) {
764  int ret;
765 
766  av_log(s, AV_LOG_TRACE, "Switch resource on track %d: re-open context\n",
767  track->index);
768 
769  ret = open_track_resource_context(s, track, i);
770  if (ret != 0)
771  return ret;
772  if (track->current_resource_index > 0)
774  track->current_resource_index = i;
775  }
776 
777  *resource = track->resources + track->current_resource_index;
778  return 0;
779  }
780  }
781 
782  av_log(s, AV_LOG_ERROR, "Could not find IMF track resource to read\n");
784 }
785 
787 {
789  int ret = 0;
791  int64_t delta_ts;
792  AVStream *st;
793  AVRational next_timestamp;
794 
796 
797  if (!track) {
798  av_log(s, AV_LOG_ERROR, "No track found for playback\n");
799  return AVERROR_INVALIDDATA;
800  }
801 
802  av_log(s, AV_LOG_DEBUG, "Found track %d to read at timestamp %lf\n",
803  track->index, av_q2d(track->current_timestamp));
804 
805  ret = get_resource_context_for_timestamp(s, track, &resource);
806  if (ret)
807  return ret;
808 
809  ret = av_read_frame(resource->ctx, pkt);
810  if (ret)
811  return ret;
812 
813  av_log(s, AV_LOG_DEBUG, "Got packet: pts=%" PRId64 ", dts=%" PRId64
814  ", duration=%" PRId64 ", stream_index=%d, pos=%" PRId64
815  ", time_base=" AVRATIONAL_FORMAT "\n", pkt->pts, pkt->dts, pkt->duration,
817 
818  /* IMF resources contain only one stream */
819 
820  if (pkt->stream_index != 0)
821  return AVERROR_INVALIDDATA;
822  st = resource->ctx->streams[0];
823 
824  pkt->stream_index = track->index;
825 
826  /* adjust the packet PTS and DTS based on the temporal position of the resource within the timeline */
827 
828  ret = imf_time_to_ts(&delta_ts, resource->ts_offset, st->time_base);
829 
830  if (!ret) {
831  if (pkt->pts != AV_NOPTS_VALUE)
832  pkt->pts += delta_ts;
833  if (pkt->dts != AV_NOPTS_VALUE)
834  pkt->dts += delta_ts;
835  } else {
836  av_log(s, AV_LOG_WARNING, "Incoherent time stamp " AVRATIONAL_FORMAT
837  " for time base " AVRATIONAL_FORMAT,
838  AVRATIONAL_ARG(resource->ts_offset),
840  }
841 
842  /* advance the track timestamp by the packet duration */
843 
844  next_timestamp = av_add_q(track->current_timestamp,
845  av_mul_q(av_make_q((int)pkt->duration, 1), st->time_base));
846 
847  /* if necessary, clamp the next timestamp to the end of the current resource */
848 
849  if (av_cmp_q(next_timestamp, resource->end_time) > 0) {
850 
851  int64_t new_pkt_dur;
852 
853  /* shrink the packet duration */
854 
855  ret = imf_time_to_ts(&new_pkt_dur,
856  av_sub_q(resource->end_time, track->current_timestamp),
857  st->time_base);
858 
859  if (!ret)
860  pkt->duration = new_pkt_dur;
861  else
862  av_log(s, AV_LOG_WARNING, "Incoherent time base in packet duration calculation\n");
863 
864  /* shrink the packet itself for audio essence */
865 
866  if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
867 
869  /* AV_CODEC_ID_PCM_S24LE is the only PCM format supported in IMF */
870  /* in this case, explicitly shrink the packet */
871 
872  int bytes_per_sample = av_get_exact_bits_per_sample(st->codecpar->codec_id) >> 3;
873  int64_t nbsamples = av_rescale_q(pkt->duration,
874  st->time_base,
875  av_make_q(1, st->codecpar->sample_rate));
876  av_shrink_packet(pkt, nbsamples * st->codecpar->ch_layout.nb_channels * bytes_per_sample);
877 
878  } else {
879  /* in all other cases, use side data to skip samples */
880  int64_t skip_samples;
881 
882  ret = imf_time_to_ts(&skip_samples,
883  av_sub_q(next_timestamp, resource->end_time),
884  av_make_q(1, st->codecpar->sample_rate));
885 
886  if (ret || skip_samples < 0 || skip_samples > UINT32_MAX) {
887  av_log(s, AV_LOG_WARNING, "Cannot skip audio samples\n");
888  } else {
889  uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
890  if (!side_data)
891  return AVERROR(ENOMEM);
892 
893  AV_WL32(side_data + 4, skip_samples); /* skip from end of this packet */
894  side_data[6] = 1; /* reason for end is convergence */
895  }
896  }
897 
898  next_timestamp = resource->end_time;
899 
900  } else {
901  av_log(s, AV_LOG_WARNING, "Non-audio packet duration reduced\n");
902  }
903  }
904 
905  track->current_timestamp = next_timestamp;
906 
907  return 0;
908 }
909 
911 {
912  IMFContext *c = s->priv_data;
913 
914  av_log(s, AV_LOG_DEBUG, "Close IMF package\n");
915  av_dict_free(&c->avio_opts);
916  av_freep(&c->base_url);
917  imf_asset_locator_map_deinit(&c->asset_locator_map);
918  ff_imf_cpl_free(c->cpl);
919 
920  for (uint32_t i = 0; i < c->track_count; i++) {
922  av_freep(&c->tracks[i]);
923  }
924 
925  av_freep(&c->tracks);
926 
927  return 0;
928 }
929 
930 static int imf_probe(const AVProbeData *p)
931 {
932  if (!strstr(p->buf, "<CompositionPlaylist"))
933  return 0;
934 
935  /* check for a ContentTitle element without including ContentTitleText,
936  * which is used by the D-Cinema CPL.
937  */
938  if (!strstr(p->buf, "ContentTitle>"))
939  return 0;
940 
941  return AVPROBE_SCORE_MAX;
942 }
943 
944 static int coherent_ts(int64_t ts, AVRational in_tb, AVRational out_tb)
945 {
946  int dst_num;
947  int dst_den;
948  int ret;
949 
950  ret = av_reduce(&dst_num, &dst_den, ts * in_tb.num * out_tb.den,
951  in_tb.den * out_tb.num, INT64_MAX);
952  if (!ret || dst_den != 1)
953  return 0;
954 
955  return 1;
956 }
957 
958 static int imf_seek(AVFormatContext *s, int stream_index, int64_t min_ts,
959  int64_t ts, int64_t max_ts, int flags)
960 {
961  IMFContext *c = s->priv_data;
962  uint32_t i;
963 
965  return AVERROR(ENOSYS);
966 
967  /* rescale timestamps to Composition edit units */
968  if (stream_index < 0)
970  av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
971  &min_ts, &ts, &max_ts);
972  else
973  ff_rescale_interval(s->streams[stream_index]->time_base,
974  av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
975  &min_ts, &ts, &max_ts);
976 
977  /* requested timestamp bounds are too close */
978  if (max_ts < min_ts)
979  return -1;
980 
981  /* clamp requested timestamp to provided bounds */
982  ts = FFMAX(FFMIN(ts, max_ts), min_ts);
983 
984  av_log(s, AV_LOG_DEBUG, "Seeking to Composition Playlist edit unit %" PRIi64 "\n", ts);
985 
986  /* set the dts of each stream and temporal offset of each track */
987  for (i = 0; i < c->track_count; i++) {
988  AVStream *st = s->streams[i];
989  IMFVirtualTrackPlaybackCtx *t = c->tracks[i];
990  int64_t dts;
991 
992  if (!coherent_ts(ts, av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num),
993  st->time_base))
994  av_log(s, AV_LOG_WARNING, "Seek position is not coherent across tracks\n");
995 
996  dts = av_rescale(ts,
997  st->time_base.den * c->cpl->edit_rate.den,
998  st->time_base.num * c->cpl->edit_rate.num);
999 
1000  av_log(s, AV_LOG_DEBUG, "Seeking to dts=%" PRId64 " on stream_index=%d\n",
1001  dts, i);
1002 
1003  t->current_timestamp = av_mul_q(av_make_q(dts, 1), st->time_base);
1004  if (t->current_resource_index >= 0) {
1006  t->current_resource_index = -1;
1007  }
1008  }
1009 
1010  return 0;
1011 }
1012 
1013 static const AVOption imf_options[] = {
1014  {
1015  .name = "assetmaps",
1016  .help = "Comma-separated paths to ASSETMAP files."
1017  "If not specified, the `ASSETMAP.xml` file in the same "
1018  "directory as the CPL is used.",
1019  .offset = offsetof(IMFContext, asset_map_paths),
1020  .type = AV_OPT_TYPE_STRING,
1021  .default_val = {.str = NULL},
1022  .flags = AV_OPT_FLAG_DECODING_PARAM,
1023  },
1024  {NULL},
1025 };
1026 
1027 static const AVClass imf_class = {
1028  .class_name = "imf",
1029  .item_name = av_default_item_name,
1030  .option = imf_options,
1031  .version = LIBAVUTIL_VERSION_INT,
1032 };
1033 
1035  .p.name = "imf",
1036  .p.long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"),
1037  .p.flags = AVFMT_NO_BYTE_SEEK,
1038  .p.priv_class = &imf_class,
1039  .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
1040  .priv_data_size = sizeof(IMFContext),
1041  .read_probe = imf_probe,
1044  .read_close = imf_close,
1045  .read_seek2 = imf_seek,
1046 };
flags
const SwsFlags flags[]
Definition: swscale.c:85
FFIMFTrackFileVirtualTrack::resources
FFIMFTrackFileResource * resources
Resource elements of the Virtual Track.
Definition: imf.h:114
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AV_TIMECODE_STR_SIZE
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33
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:487
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:994
r
const char * r
Definition: vf_curves.c:127
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
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:53
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:422
set_context_streams_from_tracks
static int set_context_streams_from_tracks(AVFormatContext *s)
Definition: imfdec.c:584
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:2576
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:309
AV_UUID_ARG
#define AV_UUID_ARG(x)
Definition: uuid.h:51
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:910
find_asset_map_locator
static IMFAssetLocator * find_asset_map_locator(IMFAssetLocatorMap *asset_map, AVUUID uuid)
Definition: imfdec.c:364
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:263
int64_t
long long int64_t
Definition: coverity.c:34
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:208
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:1382
FFIMFTrackFileVirtualTrack::resource_count
uint32_t resource_count
Number of Resource elements present in the Virtual Track.
Definition: imf.h:113
AVOption
AVOption.
Definition: opt.h:428
AVFMT_FLAG_CUSTOM_IO
#define AVFMT_FLAG_CUSTOM_IO
The caller has supplied a custom AVIOContext, don't avio_close() it.
Definition: avformat.h:1473
AVSEEK_FLAG_BYTE
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition: avformat.h:2574
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:930
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:621
AVDictionary
Definition: dict.c:32
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:1588
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:329
track_index
static int track_index(VividasDemuxContext *viv, AVFormatContext *s, const uint8_t *buf, unsigned size)
Definition: vividas.c:438
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:292
AVPROBE_SCORE_MAX
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:464
avformat_close_input
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: demux.c:377
coherent_ts
static int coherent_ts(int64_t ts, AVRational in_tb, AVRational out_tb)
Definition: imfdec.c:944
AVRATIONAL_ARG
#define AVRATIONAL_ARG(rational)
Definition: imfdec.c:79
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:829
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: packet.c:113
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:846
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
FFIMFBaseResource::duration
uint32_t duration
BaseResourceType/Duration.
Definition: imf.h:71
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:824
AVStream::duration
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:806
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:271
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:464
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:958
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:236
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
FFIMFTrackFileVirtualTrack
IMF Composition Playlist Virtual Track that consists of Track File Resources.
Definition: imf.h:111
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:231
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_read_callback.c:42
IMFVirtualTrackPlaybackCtx::current_timestamp
AVRational current_timestamp
Current temporal position.
Definition: imfdec.c:109
av_dict_get
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:60
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:495
intreadwrite.h
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:1254
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:217
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1465
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:551
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:201
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:179
imf_options
static const AVOption imf_options[]
Definition: imfdec.c:1013
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
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
AVFormatContext::opaque
void * opaque
User data.
Definition: avformat.h:1878
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
IMFVirtualTrackResourcePlaybackCtx::locator
IMFAssetLocator * locator
Location of the resource.
Definition: imfdec.c:99
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
IMFAssetLocator
IMF Asset locator.
Definition: imfdec.c:84
IMFVirtualTrackPlaybackCtx
Definition: imfdec.c:107
FF_INFMT_FLAG_INIT_CLEANUP
#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
get_next_track_with_minimum_timestamp
static IMFVirtualTrackPlaybackCtx * get_next_track_with_minimum_timestamp(AVFormatContext *s)
Definition: imfdec.c:715
IMFVirtualTrackResourcePlaybackCtx::resource
FFIMFTrackFileResource * resource
Underlying IMF CPL resource.
Definition: imfdec.c:100
AVFormatContext
Format I/O context.
Definition: avformat.h:1314
internal.h
IMFVirtualTrackResourcePlaybackCtx::ctx
AVFormatContext * ctx
Context associated with the resource.
Definition: imfdec.c:101
opts
static AVDictionary * opts
Definition: movenc.c:51
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:770
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
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:786
NULL
#define NULL
Definition: coverity.c:32
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:874
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:242
AVProbeData
This structure contains the data a format has to probe a file.
Definition: avformat.h:452
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:752
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:738
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition: codec_par.h:207
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:373
AVCodecParameters::sample_rate
int sample_rate
The number of audio samples per second.
Definition: codec_par.h:213
IMFAssetLocator::absolute_uri
char * absolute_uri
Definition: imfdec.c:86
AVStream::nb_frames
int64_t nb_frames
number of frames in this stream if known or 0
Definition: avformat.h:808
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:1370
imf_read_packet
static int imf_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: imfdec.c:786
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:461
FFIMFBaseResource::edit_rate
AVRational edit_rate
BaseResourceType/EditRate.
Definition: imf.h:69
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
AV_CODEC_ID_PCM_S24LE
@ AV_CODEC_ID_PCM_S24LE
Definition: codec_id.h:342
imf_asset_locator_map_deinit
static void imf_asset_locator_map_deinit(IMFAssetLocatorMap *asset_map)
Free a IMFAssetLocatorMap pointer.
Definition: imfdec.c:301
FFIMFTrackFileResource::track_file_uuid
AVUUID track_file_uuid
TrackFileResourceType/TrackFileId.
Definition: imf.h:80
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:88
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:164
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
IMFContext::cpl
FFIMFCPL * cpl
Definition: imfdec.c:124
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
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:122
imf_asset_locator_map_init
static void imf_asset_locator_map_init(IMFAssetLocatorMap *asset_map)
Initializes an IMFAssetLocatorMap structure.
Definition: imfdec.c:292
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:664
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:247
ff_format_io_close
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: avformat.c:951
AVOption::name
const char * name
Definition: opt.h:429
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:70
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:602
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:233
read_header
static int read_header(FFV1Context *f, RangeCoder *c)
Definition: ffv1dec.c:574
open_cpl_tracks
static int open_cpl_tracks(AVFormatContext *s)
Definition: imfdec.c:619
AVRATIONAL_FORMAT
#define AVRATIONAL_FORMAT
Definition: imfdec.c:78
FFIMFBaseResource::repeat_count
uint32_t repeat_count
BaseResourceType/RepeatCount.
Definition: imf.h:72
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
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
ff_imf_parse_cpl
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:875
bprint.h
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:596
avio_internal.h
packet.h
s
uint8_t s
Definition: llvidencdsp.c:39
FFIMFBaseResource::entry_point
uint32_t entry_point
BaseResourceType/EntryPoint.
Definition: imf.h:70
imf_read_header
static int imf_read_header(AVFormatContext *s)
Definition: imfdec.c:644
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
demux.h
imf_virtual_track_playback_context_deinit
static void imf_virtual_track_playback_context_deinit(IMFVirtualTrackPlaybackCtx *track)
Definition: imfdec.c:518
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:759
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:747
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:81
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:78
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: packet.c:231
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:148
open_virtual_track
static int open_virtual_track(AVFormatContext *s, FFIMFTrackFileVirtualTrack *virtual_track, int32_t track_index)
Definition: imfdec.c:526
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:1919
AV_PKT_DATA_SKIP_SAMPLES
@ AV_PKT_DATA_SKIP_SAMPLES
Recommends skipping the specified number of samples.
Definition: packet.h:153
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
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:605
imf_class
static const AVClass imf_class
Definition: imfdec.c:1027
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
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:355
read_probe
static int read_probe(const AVProbeData *p)
Definition: cdg.c:30
mem.h
av_strdup
#define av_strdup(s)
Definition: ops_asmgen.c:47
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:34
AVDictionaryEntry
Definition: dict.h:90
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:57
ff_imf_demuxer
const FFInputFormat ff_imf_demuxer
Definition: imfdec.c:1034
ff_stream_clone
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:246
AVPacket
This structure stores compressed data.
Definition: packet.h:580
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
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:86
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:247
AVPacket::pos
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:623
FFInputFormat
Definition: demux.h:66
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:1929
int32_t
int32_t
Definition: audioconvert.c:56
IMFContext::base_url
const char * base_url
Definition: imfdec.c:120
FFIMFCPL
IMF Composition Playlist.
Definition: imf.h:130
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
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
avstring.h
AV_OPT_TYPE_STRING
@ 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
AVStream::pts_wrap_bits
int pts_wrap_bits
Number of bits in timestamps.
Definition: avformat.h:890
FFIMFTrackFileResource::base
FFIMFBaseResource base
Definition: imf.h:79
av_timecode_make_string
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum_arg)
Load timecode string in buf.
Definition: timecode.c:104
AVPacket::time_base
AVRational time_base
Time base of the packet's timestamps.
Definition: packet.h:647
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:349