1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci/* 20cabdff1aSopenharmony_ci * 21cabdff1aSopenharmony_ci * Copyright (c) Sandflow Consulting LLC 22cabdff1aSopenharmony_ci * 23cabdff1aSopenharmony_ci * Redistribution and use in source and binary forms, with or without 24cabdff1aSopenharmony_ci * modification, are permitted provided that the following conditions are met: 25cabdff1aSopenharmony_ci * 26cabdff1aSopenharmony_ci * * Redistributions of source code must retain the above copyright notice, this 27cabdff1aSopenharmony_ci * list of conditions and the following disclaimer. 28cabdff1aSopenharmony_ci * * Redistributions in binary form must reproduce the above copyright notice, 29cabdff1aSopenharmony_ci * this list of conditions and the following disclaimer in the documentation 30cabdff1aSopenharmony_ci * and/or other materials provided with the distribution. 31cabdff1aSopenharmony_ci * 32cabdff1aSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 33cabdff1aSopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34cabdff1aSopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35cabdff1aSopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 36cabdff1aSopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 37cabdff1aSopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 38cabdff1aSopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 39cabdff1aSopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 40cabdff1aSopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41cabdff1aSopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42cabdff1aSopenharmony_ci * POSSIBILITY OF SUCH DAMAGE. 43cabdff1aSopenharmony_ci */ 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci/** 46cabdff1aSopenharmony_ci * Implements IMP CPL processing 47cabdff1aSopenharmony_ci * 48cabdff1aSopenharmony_ci * @author Pierre-Anthony Lemieux 49cabdff1aSopenharmony_ci * @file 50cabdff1aSopenharmony_ci * @ingroup lavu_imf 51cabdff1aSopenharmony_ci */ 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci#include "imf.h" 54cabdff1aSopenharmony_ci#include "libavformat/mxf.h" 55cabdff1aSopenharmony_ci#include "libavutil/bprint.h" 56cabdff1aSopenharmony_ci#include "libavutil/error.h" 57cabdff1aSopenharmony_ci#include <libxml/parser.h> 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_cixmlNodePtr ff_imf_xml_get_child_element_by_name(xmlNodePtr parent, const char *name_utf8) 60cabdff1aSopenharmony_ci{ 61cabdff1aSopenharmony_ci xmlNodePtr cur_element; 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci cur_element = xmlFirstElementChild(parent); 64cabdff1aSopenharmony_ci while (cur_element) { 65cabdff1aSopenharmony_ci if (xmlStrcmp(cur_element->name, name_utf8) == 0) 66cabdff1aSopenharmony_ci return cur_element; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci cur_element = xmlNextElementSibling(cur_element); 69cabdff1aSopenharmony_ci } 70cabdff1aSopenharmony_ci return NULL; 71cabdff1aSopenharmony_ci} 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ciint ff_imf_xml_read_uuid(xmlNodePtr element, AVUUID uuid) 74cabdff1aSopenharmony_ci{ 75cabdff1aSopenharmony_ci xmlChar *element_text = NULL; 76cabdff1aSopenharmony_ci int ret = 0; 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); 79cabdff1aSopenharmony_ci if (!element_text) 80cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 81cabdff1aSopenharmony_ci ret = av_uuid_urn_parse(element_text, uuid); 82cabdff1aSopenharmony_ci if (ret) { 83cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid UUID\n"); 84cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 85cabdff1aSopenharmony_ci } 86cabdff1aSopenharmony_ci xmlFree(element_text); 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci return ret; 89cabdff1aSopenharmony_ci} 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ciint ff_imf_xml_read_rational(xmlNodePtr element, AVRational *rational) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci xmlChar *element_text = NULL; 94cabdff1aSopenharmony_ci int ret = 0; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); 97cabdff1aSopenharmony_ci if (element_text == NULL || sscanf(element_text, "%i %i", &rational->num, &rational->den) != 2) { 98cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid rational number\n"); 99cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci xmlFree(element_text); 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci return ret; 104cabdff1aSopenharmony_ci} 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ciint ff_imf_xml_read_uint32(xmlNodePtr element, uint32_t *number) 107cabdff1aSopenharmony_ci{ 108cabdff1aSopenharmony_ci xmlChar *element_text = NULL; 109cabdff1aSopenharmony_ci int ret = 0; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); 112cabdff1aSopenharmony_ci if (element_text == NULL || sscanf(element_text, "%" PRIu32, number) != 1) { 113cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid unsigned 32-bit integer"); 114cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 115cabdff1aSopenharmony_ci } 116cabdff1aSopenharmony_ci xmlFree(element_text); 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci return ret; 119cabdff1aSopenharmony_ci} 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_cistatic void imf_base_virtual_track_init(FFIMFBaseVirtualTrack *track) 122cabdff1aSopenharmony_ci{ 123cabdff1aSopenharmony_ci memset(track->id_uuid, 0, sizeof(track->id_uuid)); 124cabdff1aSopenharmony_ci} 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_cistatic void imf_marker_virtual_track_init(FFIMFMarkerVirtualTrack *track) 127cabdff1aSopenharmony_ci{ 128cabdff1aSopenharmony_ci imf_base_virtual_track_init((FFIMFBaseVirtualTrack *)track); 129cabdff1aSopenharmony_ci track->resource_count = 0; 130cabdff1aSopenharmony_ci track->resources = NULL; 131cabdff1aSopenharmony_ci} 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_cistatic void imf_trackfile_virtual_track_init(FFIMFTrackFileVirtualTrack *track) 134cabdff1aSopenharmony_ci{ 135cabdff1aSopenharmony_ci imf_base_virtual_track_init((FFIMFBaseVirtualTrack *)track); 136cabdff1aSopenharmony_ci track->resource_count = 0; 137cabdff1aSopenharmony_ci track->resources_alloc_sz = 0; 138cabdff1aSopenharmony_ci track->resources = NULL; 139cabdff1aSopenharmony_ci} 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_cistatic void imf_base_resource_init(FFIMFBaseResource *rsrc) 142cabdff1aSopenharmony_ci{ 143cabdff1aSopenharmony_ci rsrc->duration = 0; 144cabdff1aSopenharmony_ci rsrc->edit_rate = av_make_q(0, 1); 145cabdff1aSopenharmony_ci rsrc->entry_point = 0; 146cabdff1aSopenharmony_ci rsrc->repeat_count = 1; 147cabdff1aSopenharmony_ci} 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_cistatic void imf_marker_resource_init(FFIMFMarkerResource *rsrc) 150cabdff1aSopenharmony_ci{ 151cabdff1aSopenharmony_ci imf_base_resource_init((FFIMFBaseResource *)rsrc); 152cabdff1aSopenharmony_ci rsrc->marker_count = 0; 153cabdff1aSopenharmony_ci rsrc->markers = NULL; 154cabdff1aSopenharmony_ci} 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_cistatic void imf_marker_init(FFIMFMarker *marker) 157cabdff1aSopenharmony_ci{ 158cabdff1aSopenharmony_ci marker->label_utf8 = NULL; 159cabdff1aSopenharmony_ci marker->offset = 0; 160cabdff1aSopenharmony_ci marker->scope_utf8 = NULL; 161cabdff1aSopenharmony_ci} 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_cistatic void imf_trackfile_resource_init(FFIMFTrackFileResource *rsrc) 164cabdff1aSopenharmony_ci{ 165cabdff1aSopenharmony_ci imf_base_resource_init((FFIMFBaseResource *)rsrc); 166cabdff1aSopenharmony_ci memset(rsrc->track_file_uuid, 0, sizeof(rsrc->track_file_uuid)); 167cabdff1aSopenharmony_ci} 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_cistatic int fill_content_title(xmlNodePtr cpl_element, FFIMFCPL *cpl) 170cabdff1aSopenharmony_ci{ 171cabdff1aSopenharmony_ci xmlNodePtr element = NULL; 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "ContentTitle"))) { 174cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "ContentTitle element not found in the IMF CPL\n"); 175cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci cpl->content_title_utf8 = xmlNodeListGetString(cpl_element->doc, 178cabdff1aSopenharmony_ci element->xmlChildrenNode, 179cabdff1aSopenharmony_ci 1); 180cabdff1aSopenharmony_ci if (!cpl->content_title_utf8) 181cabdff1aSopenharmony_ci cpl->content_title_utf8 = xmlStrdup(""); 182cabdff1aSopenharmony_ci if (!cpl->content_title_utf8) 183cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci return 0; 186cabdff1aSopenharmony_ci} 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_cistatic int fill_edit_rate(xmlNodePtr cpl_element, FFIMFCPL *cpl) 189cabdff1aSopenharmony_ci{ 190cabdff1aSopenharmony_ci xmlNodePtr element = NULL; 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "EditRate"))) { 193cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "EditRate element not found in the IMF CPL\n"); 194cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 195cabdff1aSopenharmony_ci } 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci return ff_imf_xml_read_rational(element, &cpl->edit_rate); 198cabdff1aSopenharmony_ci} 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_cistatic int fill_id(xmlNodePtr cpl_element, FFIMFCPL *cpl) 201cabdff1aSopenharmony_ci{ 202cabdff1aSopenharmony_ci xmlNodePtr element = NULL; 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "Id"))) { 205cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Id element not found in the IMF CPL\n"); 206cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci return ff_imf_xml_read_uuid(element, cpl->id_uuid); 210cabdff1aSopenharmony_ci} 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_cistatic int fill_marker(xmlNodePtr marker_elem, FFIMFMarker *marker) 213cabdff1aSopenharmony_ci{ 214cabdff1aSopenharmony_ci xmlNodePtr element = NULL; 215cabdff1aSopenharmony_ci int ret = 0; 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci /* read Offset */ 218cabdff1aSopenharmony_ci if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Offset"))) { 219cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Offset element not found in a Marker\n"); 220cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 221cabdff1aSopenharmony_ci } 222cabdff1aSopenharmony_ci if ((ret = ff_imf_xml_read_uint32(element, &marker->offset))) 223cabdff1aSopenharmony_ci return ret; 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci /* read Label and Scope */ 226cabdff1aSopenharmony_ci if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Label"))) { 227cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Label element not found in a Marker\n"); 228cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci if (!(marker->label_utf8 = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1))) { 231cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Empty Label element found in a Marker\n"); 232cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 233cabdff1aSopenharmony_ci } 234cabdff1aSopenharmony_ci if (!(marker->scope_utf8 = xmlGetNoNsProp(element, "scope"))) { 235cabdff1aSopenharmony_ci marker->scope_utf8 236cabdff1aSopenharmony_ci = xmlCharStrdup("http://www.smpte-ra.org/schemas/2067-3/2013#standard-markers"); 237cabdff1aSopenharmony_ci if (!marker->scope_utf8) { 238cabdff1aSopenharmony_ci xmlFree(marker->label_utf8); 239cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci } 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci return ret; 244cabdff1aSopenharmony_ci} 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_cistatic int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resource, FFIMFCPL *cpl) 247cabdff1aSopenharmony_ci{ 248cabdff1aSopenharmony_ci xmlNodePtr element = NULL; 249cabdff1aSopenharmony_ci int ret = 0; 250cabdff1aSopenharmony_ci 251cabdff1aSopenharmony_ci /* read EditRate */ 252cabdff1aSopenharmony_ci if (!(element = ff_imf_xml_get_child_element_by_name(resource_elem, "EditRate"))) { 253cabdff1aSopenharmony_ci resource->edit_rate = cpl->edit_rate; 254cabdff1aSopenharmony_ci } else if ((ret = ff_imf_xml_read_rational(element, &resource->edit_rate))) { 255cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid EditRate element found in a Resource\n"); 256cabdff1aSopenharmony_ci return ret; 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci /* read EntryPoint */ 260cabdff1aSopenharmony_ci if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "EntryPoint"))) { 261cabdff1aSopenharmony_ci if ((ret = ff_imf_xml_read_uint32(element, &resource->entry_point))) { 262cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid EntryPoint element found in a Resource\n"); 263cabdff1aSopenharmony_ci return ret; 264cabdff1aSopenharmony_ci } 265cabdff1aSopenharmony_ci } else { 266cabdff1aSopenharmony_ci resource->entry_point = 0; 267cabdff1aSopenharmony_ci } 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci /* read IntrinsicDuration */ 270cabdff1aSopenharmony_ci if (!(element = ff_imf_xml_get_child_element_by_name(resource_elem, "IntrinsicDuration"))) { 271cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "IntrinsicDuration element missing from Resource\n"); 272cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 273cabdff1aSopenharmony_ci } 274cabdff1aSopenharmony_ci if ((ret = ff_imf_xml_read_uint32(element, &resource->duration))) { 275cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid IntrinsicDuration element found in a Resource\n"); 276cabdff1aSopenharmony_ci return ret; 277cabdff1aSopenharmony_ci } 278cabdff1aSopenharmony_ci resource->duration -= resource->entry_point; 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci /* read SourceDuration */ 281cabdff1aSopenharmony_ci if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "SourceDuration"))) { 282cabdff1aSopenharmony_ci if ((ret = ff_imf_xml_read_uint32(element, &resource->duration))) { 283cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "SourceDuration element missing from Resource\n"); 284cabdff1aSopenharmony_ci return ret; 285cabdff1aSopenharmony_ci } 286cabdff1aSopenharmony_ci } 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci /* read RepeatCount */ 289cabdff1aSopenharmony_ci if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "RepeatCount"))) 290cabdff1aSopenharmony_ci ret = ff_imf_xml_read_uint32(element, &resource->repeat_count); 291cabdff1aSopenharmony_ci 292cabdff1aSopenharmony_ci return ret; 293cabdff1aSopenharmony_ci} 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_cistatic int fill_trackfile_resource(xmlNodePtr tf_resource_elem, 296cabdff1aSopenharmony_ci FFIMFTrackFileResource *tf_resource, 297cabdff1aSopenharmony_ci FFIMFCPL *cpl) 298cabdff1aSopenharmony_ci{ 299cabdff1aSopenharmony_ci xmlNodePtr element = NULL; 300cabdff1aSopenharmony_ci int ret = 0; 301cabdff1aSopenharmony_ci 302cabdff1aSopenharmony_ci if ((ret = fill_base_resource(tf_resource_elem, (FFIMFBaseResource *)tf_resource, cpl))) 303cabdff1aSopenharmony_ci return ret; 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci /* read TrackFileId */ 306cabdff1aSopenharmony_ci if ((element = ff_imf_xml_get_child_element_by_name(tf_resource_elem, "TrackFileId"))) { 307cabdff1aSopenharmony_ci if ((ret = ff_imf_xml_read_uuid(element, tf_resource->track_file_uuid))) { 308cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid TrackFileId element found in Resource\n"); 309cabdff1aSopenharmony_ci return ret; 310cabdff1aSopenharmony_ci } 311cabdff1aSopenharmony_ci } else { 312cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "TrackFileId element missing from Resource\n"); 313cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 314cabdff1aSopenharmony_ci } 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_ci return ret; 317cabdff1aSopenharmony_ci} 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_cistatic int fill_marker_resource(xmlNodePtr marker_resource_elem, 320cabdff1aSopenharmony_ci FFIMFMarkerResource *marker_resource, 321cabdff1aSopenharmony_ci FFIMFCPL *cpl) 322cabdff1aSopenharmony_ci{ 323cabdff1aSopenharmony_ci xmlNodePtr element = NULL; 324cabdff1aSopenharmony_ci int ret = 0; 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_ci if ((ret = fill_base_resource(marker_resource_elem, (FFIMFBaseResource *)marker_resource, cpl))) 327cabdff1aSopenharmony_ci return ret; 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_ci /* read markers */ 330cabdff1aSopenharmony_ci element = xmlFirstElementChild(marker_resource_elem); 331cabdff1aSopenharmony_ci while (element) { 332cabdff1aSopenharmony_ci if (xmlStrcmp(element->name, "Marker") == 0) { 333cabdff1aSopenharmony_ci void *tmp; 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci if (marker_resource->marker_count == UINT32_MAX) 336cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 337cabdff1aSopenharmony_ci tmp = av_realloc_array(marker_resource->markers, 338cabdff1aSopenharmony_ci marker_resource->marker_count + 1, 339cabdff1aSopenharmony_ci sizeof(FFIMFMarker)); 340cabdff1aSopenharmony_ci if (!tmp) 341cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 342cabdff1aSopenharmony_ci marker_resource->markers = tmp; 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci imf_marker_init(&marker_resource->markers[marker_resource->marker_count]); 345cabdff1aSopenharmony_ci ret = fill_marker(element, 346cabdff1aSopenharmony_ci &marker_resource->markers[marker_resource->marker_count]); 347cabdff1aSopenharmony_ci marker_resource->marker_count++; 348cabdff1aSopenharmony_ci if (ret) 349cabdff1aSopenharmony_ci return ret; 350cabdff1aSopenharmony_ci } 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci element = xmlNextElementSibling(element); 353cabdff1aSopenharmony_ci } 354cabdff1aSopenharmony_ci 355cabdff1aSopenharmony_ci return ret; 356cabdff1aSopenharmony_ci} 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_cistatic int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) 359cabdff1aSopenharmony_ci{ 360cabdff1aSopenharmony_ci int ret = 0; 361cabdff1aSopenharmony_ci AVUUID uuid; 362cabdff1aSopenharmony_ci xmlNodePtr resource_list_elem = NULL; 363cabdff1aSopenharmony_ci xmlNodePtr resource_elem = NULL; 364cabdff1aSopenharmony_ci xmlNodePtr track_id_elem = NULL; 365cabdff1aSopenharmony_ci unsigned long resource_elem_count; 366cabdff1aSopenharmony_ci void *tmp; 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci /* read TrackID element */ 369cabdff1aSopenharmony_ci if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(marker_sequence_elem, "TrackId"))) { 370cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "TrackId element missing from Sequence\n"); 371cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 372cabdff1aSopenharmony_ci } 373cabdff1aSopenharmony_ci if (ff_imf_xml_read_uuid(track_id_elem, uuid)) { 374cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in Sequence\n"); 375cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 376cabdff1aSopenharmony_ci } 377cabdff1aSopenharmony_ci av_log(NULL, 378cabdff1aSopenharmony_ci AV_LOG_DEBUG, 379cabdff1aSopenharmony_ci "Processing IMF CPL Marker Sequence for Virtual Track " AV_PRI_UUID "\n", 380cabdff1aSopenharmony_ci AV_UUID_ARG(uuid)); 381cabdff1aSopenharmony_ci 382cabdff1aSopenharmony_ci /* create main marker virtual track if it does not exist */ 383cabdff1aSopenharmony_ci if (!cpl->main_markers_track) { 384cabdff1aSopenharmony_ci cpl->main_markers_track = av_malloc(sizeof(FFIMFMarkerVirtualTrack)); 385cabdff1aSopenharmony_ci if (!cpl->main_markers_track) 386cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 387cabdff1aSopenharmony_ci imf_marker_virtual_track_init(cpl->main_markers_track); 388cabdff1aSopenharmony_ci av_uuid_copy(cpl->main_markers_track->base.id_uuid, uuid); 389cabdff1aSopenharmony_ci 390cabdff1aSopenharmony_ci } else if (!av_uuid_equal(cpl->main_markers_track->base.id_uuid, uuid)) { 391cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Multiple marker virtual tracks were found\n"); 392cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 393cabdff1aSopenharmony_ci } 394cabdff1aSopenharmony_ci 395cabdff1aSopenharmony_ci /* process resources */ 396cabdff1aSopenharmony_ci resource_list_elem = ff_imf_xml_get_child_element_by_name(marker_sequence_elem, "ResourceList"); 397cabdff1aSopenharmony_ci if (!resource_list_elem) 398cabdff1aSopenharmony_ci return 0; 399cabdff1aSopenharmony_ci 400cabdff1aSopenharmony_ci resource_elem_count = xmlChildElementCount(resource_list_elem); 401cabdff1aSopenharmony_ci if (resource_elem_count > UINT32_MAX 402cabdff1aSopenharmony_ci || cpl->main_markers_track->resource_count > UINT32_MAX - resource_elem_count) 403cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 404cabdff1aSopenharmony_ci tmp = av_realloc_array(cpl->main_markers_track->resources, 405cabdff1aSopenharmony_ci cpl->main_markers_track->resource_count + resource_elem_count, 406cabdff1aSopenharmony_ci sizeof(FFIMFMarkerResource)); 407cabdff1aSopenharmony_ci if (!tmp) { 408cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Cannot allocate Marker Resources\n"); 409cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 410cabdff1aSopenharmony_ci } 411cabdff1aSopenharmony_ci cpl->main_markers_track->resources = tmp; 412cabdff1aSopenharmony_ci 413cabdff1aSopenharmony_ci resource_elem = xmlFirstElementChild(resource_list_elem); 414cabdff1aSopenharmony_ci while (resource_elem) { 415cabdff1aSopenharmony_ci imf_marker_resource_init(&cpl->main_markers_track->resources[cpl->main_markers_track->resource_count]); 416cabdff1aSopenharmony_ci ret = fill_marker_resource(resource_elem, 417cabdff1aSopenharmony_ci &cpl->main_markers_track->resources[cpl->main_markers_track->resource_count], 418cabdff1aSopenharmony_ci cpl); 419cabdff1aSopenharmony_ci cpl->main_markers_track->resource_count++; 420cabdff1aSopenharmony_ci if (ret) 421cabdff1aSopenharmony_ci return ret; 422cabdff1aSopenharmony_ci 423cabdff1aSopenharmony_ci resource_elem = xmlNextElementSibling(resource_elem); 424cabdff1aSopenharmony_ci } 425cabdff1aSopenharmony_ci 426cabdff1aSopenharmony_ci return ret; 427cabdff1aSopenharmony_ci} 428cabdff1aSopenharmony_ci 429cabdff1aSopenharmony_cistatic int has_stereo_resources(xmlNodePtr element) 430cabdff1aSopenharmony_ci{ 431cabdff1aSopenharmony_ci if (xmlStrcmp(element->name, "Left") == 0 || xmlStrcmp(element->name, "Right") == 0) 432cabdff1aSopenharmony_ci return 1; 433cabdff1aSopenharmony_ci 434cabdff1aSopenharmony_ci element = xmlFirstElementChild(element); 435cabdff1aSopenharmony_ci while (element) { 436cabdff1aSopenharmony_ci if (has_stereo_resources(element)) 437cabdff1aSopenharmony_ci return 1; 438cabdff1aSopenharmony_ci 439cabdff1aSopenharmony_ci element = xmlNextElementSibling(element); 440cabdff1aSopenharmony_ci } 441cabdff1aSopenharmony_ci 442cabdff1aSopenharmony_ci return 0; 443cabdff1aSopenharmony_ci} 444cabdff1aSopenharmony_ci 445cabdff1aSopenharmony_cistatic int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cpl) 446cabdff1aSopenharmony_ci{ 447cabdff1aSopenharmony_ci int ret = 0; 448cabdff1aSopenharmony_ci AVUUID uuid; 449cabdff1aSopenharmony_ci xmlNodePtr resource_list_elem = NULL; 450cabdff1aSopenharmony_ci xmlNodePtr resource_elem = NULL; 451cabdff1aSopenharmony_ci xmlNodePtr track_id_elem = NULL; 452cabdff1aSopenharmony_ci unsigned long resource_elem_count; 453cabdff1aSopenharmony_ci FFIMFTrackFileVirtualTrack *vt = NULL; 454cabdff1aSopenharmony_ci void *tmp; 455cabdff1aSopenharmony_ci 456cabdff1aSopenharmony_ci /* read TrackID element */ 457cabdff1aSopenharmony_ci if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(audio_sequence_elem, "TrackId"))) { 458cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "TrackId element missing from audio sequence\n"); 459cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 460cabdff1aSopenharmony_ci } 461cabdff1aSopenharmony_ci if ((ret = ff_imf_xml_read_uuid(track_id_elem, uuid))) { 462cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); 463cabdff1aSopenharmony_ci return ret; 464cabdff1aSopenharmony_ci } 465cabdff1aSopenharmony_ci av_log(NULL, 466cabdff1aSopenharmony_ci AV_LOG_DEBUG, 467cabdff1aSopenharmony_ci "Processing IMF CPL Audio Sequence for Virtual Track " AV_PRI_UUID "\n", 468cabdff1aSopenharmony_ci AV_UUID_ARG(uuid)); 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci /* get the main audio virtual track corresponding to the sequence */ 471cabdff1aSopenharmony_ci for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) { 472cabdff1aSopenharmony_ci if (av_uuid_equal(cpl->main_audio_tracks[i].base.id_uuid, uuid)) { 473cabdff1aSopenharmony_ci vt = &cpl->main_audio_tracks[i]; 474cabdff1aSopenharmony_ci break; 475cabdff1aSopenharmony_ci } 476cabdff1aSopenharmony_ci } 477cabdff1aSopenharmony_ci 478cabdff1aSopenharmony_ci /* create a main audio virtual track if none exists for the sequence */ 479cabdff1aSopenharmony_ci if (!vt) { 480cabdff1aSopenharmony_ci if (cpl->main_audio_track_count == UINT32_MAX) 481cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 482cabdff1aSopenharmony_ci tmp = av_realloc_array(cpl->main_audio_tracks, 483cabdff1aSopenharmony_ci cpl->main_audio_track_count + 1, 484cabdff1aSopenharmony_ci sizeof(FFIMFTrackFileVirtualTrack)); 485cabdff1aSopenharmony_ci if (!tmp) 486cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 487cabdff1aSopenharmony_ci 488cabdff1aSopenharmony_ci cpl->main_audio_tracks = tmp; 489cabdff1aSopenharmony_ci vt = &cpl->main_audio_tracks[cpl->main_audio_track_count]; 490cabdff1aSopenharmony_ci imf_trackfile_virtual_track_init(vt); 491cabdff1aSopenharmony_ci cpl->main_audio_track_count++; 492cabdff1aSopenharmony_ci av_uuid_copy(vt->base.id_uuid, uuid); 493cabdff1aSopenharmony_ci } 494cabdff1aSopenharmony_ci 495cabdff1aSopenharmony_ci /* process resources */ 496cabdff1aSopenharmony_ci resource_list_elem = ff_imf_xml_get_child_element_by_name(audio_sequence_elem, "ResourceList"); 497cabdff1aSopenharmony_ci if (!resource_list_elem) 498cabdff1aSopenharmony_ci return 0; 499cabdff1aSopenharmony_ci 500cabdff1aSopenharmony_ci resource_elem_count = xmlChildElementCount(resource_list_elem); 501cabdff1aSopenharmony_ci if (resource_elem_count > UINT32_MAX 502cabdff1aSopenharmony_ci || vt->resource_count > UINT32_MAX - resource_elem_count) 503cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 504cabdff1aSopenharmony_ci tmp = av_fast_realloc(vt->resources, 505cabdff1aSopenharmony_ci &vt->resources_alloc_sz, 506cabdff1aSopenharmony_ci (vt->resource_count + resource_elem_count) 507cabdff1aSopenharmony_ci * sizeof(FFIMFTrackFileResource)); 508cabdff1aSopenharmony_ci if (!tmp) { 509cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Cannot allocate Main Audio Resources\n"); 510cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 511cabdff1aSopenharmony_ci } 512cabdff1aSopenharmony_ci vt->resources = tmp; 513cabdff1aSopenharmony_ci 514cabdff1aSopenharmony_ci resource_elem = xmlFirstElementChild(resource_list_elem); 515cabdff1aSopenharmony_ci while (resource_elem) { 516cabdff1aSopenharmony_ci imf_trackfile_resource_init(&vt->resources[vt->resource_count]); 517cabdff1aSopenharmony_ci ret = fill_trackfile_resource(resource_elem, 518cabdff1aSopenharmony_ci &vt->resources[vt->resource_count], 519cabdff1aSopenharmony_ci cpl); 520cabdff1aSopenharmony_ci if (ret) 521cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); 522cabdff1aSopenharmony_ci else 523cabdff1aSopenharmony_ci vt->resource_count++; 524cabdff1aSopenharmony_ci 525cabdff1aSopenharmony_ci resource_elem = xmlNextElementSibling(resource_elem); 526cabdff1aSopenharmony_ci } 527cabdff1aSopenharmony_ci 528cabdff1aSopenharmony_ci return ret; 529cabdff1aSopenharmony_ci} 530cabdff1aSopenharmony_ci 531cabdff1aSopenharmony_cistatic int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL *cpl) 532cabdff1aSopenharmony_ci{ 533cabdff1aSopenharmony_ci int ret = 0; 534cabdff1aSopenharmony_ci AVUUID uuid; 535cabdff1aSopenharmony_ci xmlNodePtr resource_list_elem = NULL; 536cabdff1aSopenharmony_ci xmlNodePtr resource_elem = NULL; 537cabdff1aSopenharmony_ci xmlNodePtr track_id_elem = NULL; 538cabdff1aSopenharmony_ci void *tmp; 539cabdff1aSopenharmony_ci unsigned long resource_elem_count; 540cabdff1aSopenharmony_ci 541cabdff1aSopenharmony_ci /* skip stereoscopic resources */ 542cabdff1aSopenharmony_ci if (has_stereo_resources(image_sequence_elem)) { 543cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Stereoscopic 3D image virtual tracks not supported\n"); 544cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 545cabdff1aSopenharmony_ci } 546cabdff1aSopenharmony_ci 547cabdff1aSopenharmony_ci /* read TrackId element*/ 548cabdff1aSopenharmony_ci if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(image_sequence_elem, "TrackId"))) { 549cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "TrackId element missing from audio sequence\n"); 550cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 551cabdff1aSopenharmony_ci } 552cabdff1aSopenharmony_ci if ((ret = ff_imf_xml_read_uuid(track_id_elem, uuid))) { 553cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); 554cabdff1aSopenharmony_ci return ret; 555cabdff1aSopenharmony_ci } 556cabdff1aSopenharmony_ci 557cabdff1aSopenharmony_ci /* create main image virtual track if one does not exist */ 558cabdff1aSopenharmony_ci if (!cpl->main_image_2d_track) { 559cabdff1aSopenharmony_ci cpl->main_image_2d_track = av_malloc(sizeof(FFIMFTrackFileVirtualTrack)); 560cabdff1aSopenharmony_ci if (!cpl->main_image_2d_track) 561cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 562cabdff1aSopenharmony_ci imf_trackfile_virtual_track_init(cpl->main_image_2d_track); 563cabdff1aSopenharmony_ci av_uuid_copy(cpl->main_image_2d_track->base.id_uuid, uuid); 564cabdff1aSopenharmony_ci 565cabdff1aSopenharmony_ci } else if (!av_uuid_equal(cpl->main_image_2d_track->base.id_uuid, uuid)) { 566cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Multiple MainImage virtual tracks found\n"); 567cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 568cabdff1aSopenharmony_ci } 569cabdff1aSopenharmony_ci av_log(NULL, 570cabdff1aSopenharmony_ci AV_LOG_DEBUG, 571cabdff1aSopenharmony_ci "Processing IMF CPL Main Image Sequence for Virtual Track " AV_PRI_UUID "\n", 572cabdff1aSopenharmony_ci AV_UUID_ARG(uuid)); 573cabdff1aSopenharmony_ci 574cabdff1aSopenharmony_ci /* process resources */ 575cabdff1aSopenharmony_ci resource_list_elem = ff_imf_xml_get_child_element_by_name(image_sequence_elem, "ResourceList"); 576cabdff1aSopenharmony_ci if (!resource_list_elem) 577cabdff1aSopenharmony_ci return 0; 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci resource_elem_count = xmlChildElementCount(resource_list_elem); 580cabdff1aSopenharmony_ci if (resource_elem_count > UINT32_MAX 581cabdff1aSopenharmony_ci || cpl->main_image_2d_track->resource_count > UINT32_MAX - resource_elem_count 582cabdff1aSopenharmony_ci || (cpl->main_image_2d_track->resource_count + resource_elem_count) 583cabdff1aSopenharmony_ci > INT_MAX / sizeof(FFIMFTrackFileResource)) 584cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 585cabdff1aSopenharmony_ci tmp = av_fast_realloc(cpl->main_image_2d_track->resources, 586cabdff1aSopenharmony_ci &cpl->main_image_2d_track->resources_alloc_sz, 587cabdff1aSopenharmony_ci (cpl->main_image_2d_track->resource_count + resource_elem_count) 588cabdff1aSopenharmony_ci * sizeof(FFIMFTrackFileResource)); 589cabdff1aSopenharmony_ci if (!tmp) { 590cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Cannot allocate Main Image Resources\n"); 591cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 592cabdff1aSopenharmony_ci } 593cabdff1aSopenharmony_ci cpl->main_image_2d_track->resources = tmp; 594cabdff1aSopenharmony_ci 595cabdff1aSopenharmony_ci resource_elem = xmlFirstElementChild(resource_list_elem); 596cabdff1aSopenharmony_ci while (resource_elem) { 597cabdff1aSopenharmony_ci imf_trackfile_resource_init( 598cabdff1aSopenharmony_ci &cpl->main_image_2d_track->resources[cpl->main_image_2d_track->resource_count]); 599cabdff1aSopenharmony_ci ret = fill_trackfile_resource(resource_elem, 600cabdff1aSopenharmony_ci &cpl->main_image_2d_track->resources[cpl->main_image_2d_track->resource_count], 601cabdff1aSopenharmony_ci cpl); 602cabdff1aSopenharmony_ci if (ret) 603cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); 604cabdff1aSopenharmony_ci else 605cabdff1aSopenharmony_ci cpl->main_image_2d_track->resource_count++; 606cabdff1aSopenharmony_ci 607cabdff1aSopenharmony_ci resource_elem = xmlNextElementSibling(resource_elem); 608cabdff1aSopenharmony_ci } 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_ci return 0; 611cabdff1aSopenharmony_ci} 612cabdff1aSopenharmony_ci 613cabdff1aSopenharmony_cistatic int fill_virtual_tracks(xmlNodePtr cpl_element, FFIMFCPL *cpl) 614cabdff1aSopenharmony_ci{ 615cabdff1aSopenharmony_ci int ret = 0; 616cabdff1aSopenharmony_ci xmlNodePtr segment_list_elem = NULL; 617cabdff1aSopenharmony_ci xmlNodePtr segment_elem = NULL; 618cabdff1aSopenharmony_ci xmlNodePtr sequence_list_elem = NULL; 619cabdff1aSopenharmony_ci xmlNodePtr sequence_elem = NULL; 620cabdff1aSopenharmony_ci 621cabdff1aSopenharmony_ci if (!(segment_list_elem = ff_imf_xml_get_child_element_by_name(cpl_element, "SegmentList"))) { 622cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "SegmentList element missing\n"); 623cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 624cabdff1aSopenharmony_ci } 625cabdff1aSopenharmony_ci 626cabdff1aSopenharmony_ci /* process sequences */ 627cabdff1aSopenharmony_ci segment_elem = xmlFirstElementChild(segment_list_elem); 628cabdff1aSopenharmony_ci while (segment_elem) { 629cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_DEBUG, "Processing IMF CPL Segment\n"); 630cabdff1aSopenharmony_ci 631cabdff1aSopenharmony_ci sequence_list_elem = ff_imf_xml_get_child_element_by_name(segment_elem, "SequenceList"); 632cabdff1aSopenharmony_ci if (!segment_list_elem) 633cabdff1aSopenharmony_ci continue; 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci sequence_elem = xmlFirstElementChild(sequence_list_elem); 636cabdff1aSopenharmony_ci while (sequence_elem) { 637cabdff1aSopenharmony_ci if (xmlStrcmp(sequence_elem->name, "MarkerSequence") == 0) 638cabdff1aSopenharmony_ci ret = push_marker_sequence(sequence_elem, cpl); 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci else if (xmlStrcmp(sequence_elem->name, "MainImageSequence") == 0) 641cabdff1aSopenharmony_ci ret = push_main_image_2d_sequence(sequence_elem, cpl); 642cabdff1aSopenharmony_ci 643cabdff1aSopenharmony_ci else if (xmlStrcmp(sequence_elem->name, "MainAudioSequence") == 0) 644cabdff1aSopenharmony_ci ret = push_main_audio_sequence(sequence_elem, cpl); 645cabdff1aSopenharmony_ci 646cabdff1aSopenharmony_ci else 647cabdff1aSopenharmony_ci av_log(NULL, 648cabdff1aSopenharmony_ci AV_LOG_INFO, 649cabdff1aSopenharmony_ci "The following Sequence is not supported and is ignored: %s\n", 650cabdff1aSopenharmony_ci sequence_elem->name); 651cabdff1aSopenharmony_ci 652cabdff1aSopenharmony_ci /* abort parsing only if memory error occurred */ 653cabdff1aSopenharmony_ci if (ret == AVERROR(ENOMEM)) 654cabdff1aSopenharmony_ci return ret; 655cabdff1aSopenharmony_ci 656cabdff1aSopenharmony_ci sequence_elem = xmlNextElementSibling(sequence_elem); 657cabdff1aSopenharmony_ci } 658cabdff1aSopenharmony_ci 659cabdff1aSopenharmony_ci segment_elem = xmlNextElementSibling(segment_elem); 660cabdff1aSopenharmony_ci } 661cabdff1aSopenharmony_ci 662cabdff1aSopenharmony_ci return ret; 663cabdff1aSopenharmony_ci} 664cabdff1aSopenharmony_ci 665cabdff1aSopenharmony_ciint ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl) 666cabdff1aSopenharmony_ci{ 667cabdff1aSopenharmony_ci int ret = 0; 668cabdff1aSopenharmony_ci xmlNodePtr cpl_element = NULL; 669cabdff1aSopenharmony_ci 670cabdff1aSopenharmony_ci *cpl = ff_imf_cpl_alloc(); 671cabdff1aSopenharmony_ci if (!*cpl) { 672cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 673cabdff1aSopenharmony_ci goto cleanup; 674cabdff1aSopenharmony_ci } 675cabdff1aSopenharmony_ci 676cabdff1aSopenharmony_ci cpl_element = xmlDocGetRootElement(doc); 677cabdff1aSopenharmony_ci if (!cpl_element || xmlStrcmp(cpl_element->name, "CompositionPlaylist")) { 678cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "The root element of the CPL is not CompositionPlaylist\n"); 679cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 680cabdff1aSopenharmony_ci goto cleanup; 681cabdff1aSopenharmony_ci } 682cabdff1aSopenharmony_ci 683cabdff1aSopenharmony_ci if ((ret = fill_content_title(cpl_element, *cpl))) 684cabdff1aSopenharmony_ci goto cleanup; 685cabdff1aSopenharmony_ci if ((ret = fill_id(cpl_element, *cpl))) 686cabdff1aSopenharmony_ci goto cleanup; 687cabdff1aSopenharmony_ci if ((ret = fill_edit_rate(cpl_element, *cpl))) 688cabdff1aSopenharmony_ci goto cleanup; 689cabdff1aSopenharmony_ci if ((ret = fill_virtual_tracks(cpl_element, *cpl))) 690cabdff1aSopenharmony_ci goto cleanup; 691cabdff1aSopenharmony_ci 692cabdff1aSopenharmony_cicleanup: 693cabdff1aSopenharmony_ci if (*cpl && ret) { 694cabdff1aSopenharmony_ci ff_imf_cpl_free(*cpl); 695cabdff1aSopenharmony_ci *cpl = NULL; 696cabdff1aSopenharmony_ci } 697cabdff1aSopenharmony_ci return ret; 698cabdff1aSopenharmony_ci} 699cabdff1aSopenharmony_ci 700cabdff1aSopenharmony_cistatic void imf_marker_free(FFIMFMarker *marker) 701cabdff1aSopenharmony_ci{ 702cabdff1aSopenharmony_ci if (!marker) 703cabdff1aSopenharmony_ci return; 704cabdff1aSopenharmony_ci xmlFree(marker->label_utf8); 705cabdff1aSopenharmony_ci xmlFree(marker->scope_utf8); 706cabdff1aSopenharmony_ci} 707cabdff1aSopenharmony_ci 708cabdff1aSopenharmony_cistatic void imf_marker_resource_free(FFIMFMarkerResource *rsrc) 709cabdff1aSopenharmony_ci{ 710cabdff1aSopenharmony_ci if (!rsrc) 711cabdff1aSopenharmony_ci return; 712cabdff1aSopenharmony_ci for (uint32_t i = 0; i < rsrc->marker_count; i++) 713cabdff1aSopenharmony_ci imf_marker_free(&rsrc->markers[i]); 714cabdff1aSopenharmony_ci av_freep(&rsrc->markers); 715cabdff1aSopenharmony_ci} 716cabdff1aSopenharmony_ci 717cabdff1aSopenharmony_cistatic void imf_marker_virtual_track_free(FFIMFMarkerVirtualTrack *vt) 718cabdff1aSopenharmony_ci{ 719cabdff1aSopenharmony_ci if (!vt) 720cabdff1aSopenharmony_ci return; 721cabdff1aSopenharmony_ci for (uint32_t i = 0; i < vt->resource_count; i++) 722cabdff1aSopenharmony_ci imf_marker_resource_free(&vt->resources[i]); 723cabdff1aSopenharmony_ci av_freep(&vt->resources); 724cabdff1aSopenharmony_ci} 725cabdff1aSopenharmony_ci 726cabdff1aSopenharmony_cistatic void imf_trackfile_virtual_track_free(FFIMFTrackFileVirtualTrack *vt) 727cabdff1aSopenharmony_ci{ 728cabdff1aSopenharmony_ci if (!vt) 729cabdff1aSopenharmony_ci return; 730cabdff1aSopenharmony_ci av_freep(&vt->resources); 731cabdff1aSopenharmony_ci} 732cabdff1aSopenharmony_ci 733cabdff1aSopenharmony_cistatic void imf_cpl_init(FFIMFCPL *cpl) 734cabdff1aSopenharmony_ci{ 735cabdff1aSopenharmony_ci av_uuid_nil(cpl->id_uuid); 736cabdff1aSopenharmony_ci cpl->content_title_utf8 = NULL; 737cabdff1aSopenharmony_ci cpl->edit_rate = av_make_q(0, 1); 738cabdff1aSopenharmony_ci cpl->main_markers_track = NULL; 739cabdff1aSopenharmony_ci cpl->main_image_2d_track = NULL; 740cabdff1aSopenharmony_ci cpl->main_audio_track_count = 0; 741cabdff1aSopenharmony_ci cpl->main_audio_tracks = NULL; 742cabdff1aSopenharmony_ci} 743cabdff1aSopenharmony_ci 744cabdff1aSopenharmony_ciFFIMFCPL *ff_imf_cpl_alloc(void) 745cabdff1aSopenharmony_ci{ 746cabdff1aSopenharmony_ci FFIMFCPL *cpl; 747cabdff1aSopenharmony_ci 748cabdff1aSopenharmony_ci cpl = av_malloc(sizeof(FFIMFCPL)); 749cabdff1aSopenharmony_ci if (!cpl) 750cabdff1aSopenharmony_ci return NULL; 751cabdff1aSopenharmony_ci imf_cpl_init(cpl); 752cabdff1aSopenharmony_ci return cpl; 753cabdff1aSopenharmony_ci} 754cabdff1aSopenharmony_ci 755cabdff1aSopenharmony_civoid ff_imf_cpl_free(FFIMFCPL *cpl) 756cabdff1aSopenharmony_ci{ 757cabdff1aSopenharmony_ci if (!cpl) 758cabdff1aSopenharmony_ci return; 759cabdff1aSopenharmony_ci 760cabdff1aSopenharmony_ci xmlFree(cpl->content_title_utf8); 761cabdff1aSopenharmony_ci 762cabdff1aSopenharmony_ci imf_marker_virtual_track_free(cpl->main_markers_track); 763cabdff1aSopenharmony_ci 764cabdff1aSopenharmony_ci if (cpl->main_markers_track) 765cabdff1aSopenharmony_ci av_freep(&cpl->main_markers_track); 766cabdff1aSopenharmony_ci 767cabdff1aSopenharmony_ci imf_trackfile_virtual_track_free(cpl->main_image_2d_track); 768cabdff1aSopenharmony_ci 769cabdff1aSopenharmony_ci if (cpl->main_image_2d_track) 770cabdff1aSopenharmony_ci av_freep(&cpl->main_image_2d_track); 771cabdff1aSopenharmony_ci 772cabdff1aSopenharmony_ci for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) 773cabdff1aSopenharmony_ci imf_trackfile_virtual_track_free(&cpl->main_audio_tracks[i]); 774cabdff1aSopenharmony_ci 775cabdff1aSopenharmony_ci if (cpl->main_audio_tracks) 776cabdff1aSopenharmony_ci av_freep(&cpl->main_audio_tracks); 777cabdff1aSopenharmony_ci 778cabdff1aSopenharmony_ci av_freep(&cpl); 779cabdff1aSopenharmony_ci} 780cabdff1aSopenharmony_ci 781cabdff1aSopenharmony_ciint ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) 782cabdff1aSopenharmony_ci{ 783cabdff1aSopenharmony_ci AVBPrint buf; 784cabdff1aSopenharmony_ci xmlDoc *doc = NULL; 785cabdff1aSopenharmony_ci int ret = 0; 786cabdff1aSopenharmony_ci 787cabdff1aSopenharmony_ci av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer length 788cabdff1aSopenharmony_ci 789cabdff1aSopenharmony_ci ret = avio_read_to_bprint(in, &buf, SIZE_MAX); 790cabdff1aSopenharmony_ci if (ret < 0 || !avio_feof(in)) { 791cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Cannot read IMF CPL\n"); 792cabdff1aSopenharmony_ci if (ret == 0) 793cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 794cabdff1aSopenharmony_ci goto clean_up; 795cabdff1aSopenharmony_ci } 796cabdff1aSopenharmony_ci 797cabdff1aSopenharmony_ci LIBXML_TEST_VERSION 798cabdff1aSopenharmony_ci 799cabdff1aSopenharmony_ci doc = xmlReadMemory(buf.str, buf.len, NULL, NULL, 0); 800cabdff1aSopenharmony_ci if (!doc) { 801cabdff1aSopenharmony_ci av_log(NULL, 802cabdff1aSopenharmony_ci AV_LOG_ERROR, 803cabdff1aSopenharmony_ci "XML parsing failed when reading the IMF CPL\n"); 804cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 805cabdff1aSopenharmony_ci goto clean_up; 806cabdff1aSopenharmony_ci } 807cabdff1aSopenharmony_ci 808cabdff1aSopenharmony_ci if ((ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl))) { 809cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Cannot parse IMF CPL\n"); 810cabdff1aSopenharmony_ci } else { 811cabdff1aSopenharmony_ci av_log(NULL, 812cabdff1aSopenharmony_ci AV_LOG_INFO, 813cabdff1aSopenharmony_ci "IMF CPL ContentTitle: %s\n", 814cabdff1aSopenharmony_ci (*cpl)->content_title_utf8); 815cabdff1aSopenharmony_ci av_log(NULL, 816cabdff1aSopenharmony_ci AV_LOG_INFO, 817cabdff1aSopenharmony_ci "IMF CPL Id: " AV_PRI_UUID "\n", 818cabdff1aSopenharmony_ci AV_UUID_ARG((*cpl)->id_uuid)); 819cabdff1aSopenharmony_ci } 820cabdff1aSopenharmony_ci 821cabdff1aSopenharmony_ci xmlFreeDoc(doc); 822cabdff1aSopenharmony_ci 823cabdff1aSopenharmony_ciclean_up: 824cabdff1aSopenharmony_ci av_bprint_finalize(&buf, NULL); 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_ci return ret; 827cabdff1aSopenharmony_ci} 828