1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * "NUT" Container Format demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2004-2006 Michael Niedermayer 4cabdff1aSopenharmony_ci * Copyright (c) 2003 Alex Beregszaszi 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 24cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 25cabdff1aSopenharmony_ci#include "libavutil/bswap.h" 26cabdff1aSopenharmony_ci#include "libavutil/dict.h" 27cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 28cabdff1aSopenharmony_ci#include "libavutil/mathematics.h" 29cabdff1aSopenharmony_ci#include "libavutil/tree.h" 30cabdff1aSopenharmony_ci#include "libavcodec/bytestream.h" 31cabdff1aSopenharmony_ci#include "avio_internal.h" 32cabdff1aSopenharmony_ci#include "demux.h" 33cabdff1aSopenharmony_ci#include "isom.h" 34cabdff1aSopenharmony_ci#include "nut.h" 35cabdff1aSopenharmony_ci#include "riff.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci#define NUT_MAX_STREAMS 256 /* arbitrary sanity check value */ 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_cistatic int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, 40cabdff1aSopenharmony_ci int64_t *pos_arg, int64_t pos_limit); 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_cistatic int get_str(AVIOContext *bc, char *string, unsigned int maxlen) 43cabdff1aSopenharmony_ci{ 44cabdff1aSopenharmony_ci unsigned int len = ffio_read_varlen(bc); 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci if (len && maxlen) 47cabdff1aSopenharmony_ci avio_read(bc, string, FFMIN(len, maxlen)); 48cabdff1aSopenharmony_ci while (len > maxlen) { 49cabdff1aSopenharmony_ci avio_r8(bc); 50cabdff1aSopenharmony_ci len--; 51cabdff1aSopenharmony_ci if (bc->eof_reached) 52cabdff1aSopenharmony_ci len = maxlen; 53cabdff1aSopenharmony_ci } 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci if (maxlen) 56cabdff1aSopenharmony_ci string[FFMIN(len, maxlen - 1)] = 0; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci if (bc->eof_reached) 59cabdff1aSopenharmony_ci return AVERROR_EOF; 60cabdff1aSopenharmony_ci if (maxlen == len) 61cabdff1aSopenharmony_ci return -1; 62cabdff1aSopenharmony_ci else 63cabdff1aSopenharmony_ci return 0; 64cabdff1aSopenharmony_ci} 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_cistatic int64_t get_s(AVIOContext *bc) 67cabdff1aSopenharmony_ci{ 68cabdff1aSopenharmony_ci int64_t v = ffio_read_varlen(bc) + 1; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci if (v & 1) 71cabdff1aSopenharmony_ci return -(v >> 1); 72cabdff1aSopenharmony_ci else 73cabdff1aSopenharmony_ci return (v >> 1); 74cabdff1aSopenharmony_ci} 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_cistatic uint64_t get_fourcc(AVIOContext *bc) 77cabdff1aSopenharmony_ci{ 78cabdff1aSopenharmony_ci unsigned int len = ffio_read_varlen(bc); 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci if (len == 2) 81cabdff1aSopenharmony_ci return avio_rl16(bc); 82cabdff1aSopenharmony_ci else if (len == 4) 83cabdff1aSopenharmony_ci return avio_rl32(bc); 84cabdff1aSopenharmony_ci else { 85cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Unsupported fourcc length %d\n", len); 86cabdff1aSopenharmony_ci return -1; 87cabdff1aSopenharmony_ci } 88cabdff1aSopenharmony_ci} 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_cistatic int get_packetheader(NUTContext *nut, AVIOContext *bc, 91cabdff1aSopenharmony_ci int calculate_checksum, uint64_t startcode) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci int64_t size; 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci startcode = av_be2ne64(startcode); 96cabdff1aSopenharmony_ci startcode = ff_crc04C11DB7_update(0, (uint8_t*) &startcode, 8); 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci ffio_init_checksum(bc, ff_crc04C11DB7_update, startcode); 99cabdff1aSopenharmony_ci size = ffio_read_varlen(bc); 100cabdff1aSopenharmony_ci if (size > 4096) 101cabdff1aSopenharmony_ci avio_rb32(bc); 102cabdff1aSopenharmony_ci if (ffio_get_checksum(bc) && size > 4096) 103cabdff1aSopenharmony_ci return -1; 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci ffio_init_checksum(bc, calculate_checksum ? ff_crc04C11DB7_update : NULL, 0); 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci return size; 108cabdff1aSopenharmony_ci} 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_cistatic uint64_t find_any_startcode(AVIOContext *bc, int64_t pos) 111cabdff1aSopenharmony_ci{ 112cabdff1aSopenharmony_ci uint64_t state = 0; 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_ci if (pos >= 0) 115cabdff1aSopenharmony_ci /* Note, this may fail if the stream is not seekable, but that should 116cabdff1aSopenharmony_ci * not matter, as in this case we simply start where we currently are */ 117cabdff1aSopenharmony_ci avio_seek(bc, pos, SEEK_SET); 118cabdff1aSopenharmony_ci while (!avio_feof(bc)) { 119cabdff1aSopenharmony_ci state = (state << 8) | avio_r8(bc); 120cabdff1aSopenharmony_ci if ((state >> 56) != 'N') 121cabdff1aSopenharmony_ci continue; 122cabdff1aSopenharmony_ci switch (state) { 123cabdff1aSopenharmony_ci case MAIN_STARTCODE: 124cabdff1aSopenharmony_ci case STREAM_STARTCODE: 125cabdff1aSopenharmony_ci case SYNCPOINT_STARTCODE: 126cabdff1aSopenharmony_ci case INFO_STARTCODE: 127cabdff1aSopenharmony_ci case INDEX_STARTCODE: 128cabdff1aSopenharmony_ci return state; 129cabdff1aSopenharmony_ci } 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci return 0; 133cabdff1aSopenharmony_ci} 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci/** 136cabdff1aSopenharmony_ci * Find the given startcode. 137cabdff1aSopenharmony_ci * @param code the startcode 138cabdff1aSopenharmony_ci * @param pos the start position of the search, or -1 if the current position 139cabdff1aSopenharmony_ci * @return the position of the startcode or -1 if not found 140cabdff1aSopenharmony_ci */ 141cabdff1aSopenharmony_cistatic int64_t find_startcode(AVIOContext *bc, uint64_t code, int64_t pos) 142cabdff1aSopenharmony_ci{ 143cabdff1aSopenharmony_ci for (;;) { 144cabdff1aSopenharmony_ci uint64_t startcode = find_any_startcode(bc, pos); 145cabdff1aSopenharmony_ci if (startcode == code) 146cabdff1aSopenharmony_ci return avio_tell(bc) - 8; 147cabdff1aSopenharmony_ci else if (startcode == 0) 148cabdff1aSopenharmony_ci return -1; 149cabdff1aSopenharmony_ci pos = -1; 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci} 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_cistatic int nut_probe(const AVProbeData *p) 154cabdff1aSopenharmony_ci{ 155cabdff1aSopenharmony_ci int i; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci for (i = 0; i < p->buf_size-8; i++) { 158cabdff1aSopenharmony_ci if (AV_RB32(p->buf+i) != MAIN_STARTCODE>>32) 159cabdff1aSopenharmony_ci continue; 160cabdff1aSopenharmony_ci if (AV_RB32(p->buf+i+4) == (MAIN_STARTCODE & 0xFFFFFFFF)) 161cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci return 0; 164cabdff1aSopenharmony_ci} 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci#define GET_V(dst, check) \ 167cabdff1aSopenharmony_ci do { \ 168cabdff1aSopenharmony_ci tmp = ffio_read_varlen(bc); \ 169cabdff1aSopenharmony_ci if (!(check)) { \ 170cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp); \ 171cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; \ 172cabdff1aSopenharmony_ci goto fail; \ 173cabdff1aSopenharmony_ci } \ 174cabdff1aSopenharmony_ci dst = tmp; \ 175cabdff1aSopenharmony_ci } while (0) 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_cistatic int skip_reserved(AVIOContext *bc, int64_t pos) 178cabdff1aSopenharmony_ci{ 179cabdff1aSopenharmony_ci pos -= avio_tell(bc); 180cabdff1aSopenharmony_ci if (pos < 0) { 181cabdff1aSopenharmony_ci avio_seek(bc, pos, SEEK_CUR); 182cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 183cabdff1aSopenharmony_ci } else { 184cabdff1aSopenharmony_ci while (pos--) { 185cabdff1aSopenharmony_ci if (bc->eof_reached) 186cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 187cabdff1aSopenharmony_ci avio_r8(bc); 188cabdff1aSopenharmony_ci } 189cabdff1aSopenharmony_ci return 0; 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci} 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_cistatic int decode_main_header(NUTContext *nut) 194cabdff1aSopenharmony_ci{ 195cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 196cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 197cabdff1aSopenharmony_ci uint64_t tmp, end, length; 198cabdff1aSopenharmony_ci unsigned int stream_count; 199cabdff1aSopenharmony_ci int i, j, count, ret; 200cabdff1aSopenharmony_ci int tmp_stream, tmp_mul, tmp_pts, tmp_size, tmp_res, tmp_head_idx; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci length = get_packetheader(nut, bc, 1, MAIN_STARTCODE); 203cabdff1aSopenharmony_ci if (length == (uint64_t)-1) 204cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 205cabdff1aSopenharmony_ci end = length + avio_tell(bc); 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci nut->version = ffio_read_varlen(bc); 208cabdff1aSopenharmony_ci if (nut->version < NUT_MIN_VERSION || 209cabdff1aSopenharmony_ci nut->version > NUT_MAX_VERSION) { 210cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Version %d not supported.\n", 211cabdff1aSopenharmony_ci nut->version); 212cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 213cabdff1aSopenharmony_ci } 214cabdff1aSopenharmony_ci if (nut->version > 3) 215cabdff1aSopenharmony_ci nut->minor_version = ffio_read_varlen(bc); 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS); 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci nut->max_distance = ffio_read_varlen(bc); 220cabdff1aSopenharmony_ci if (nut->max_distance > 65536) { 221cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "max_distance %d\n", nut->max_distance); 222cabdff1aSopenharmony_ci nut->max_distance = 65536; 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci GET_V(nut->time_base_count, tmp > 0 && tmp < INT_MAX / sizeof(AVRational) && tmp < length/2); 226cabdff1aSopenharmony_ci nut->time_base = av_malloc_array(nut->time_base_count, sizeof(AVRational)); 227cabdff1aSopenharmony_ci if (!nut->time_base) 228cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci for (i = 0; i < nut->time_base_count; i++) { 231cabdff1aSopenharmony_ci GET_V(nut->time_base[i].num, tmp > 0 && tmp < (1ULL << 31)); 232cabdff1aSopenharmony_ci GET_V(nut->time_base[i].den, tmp > 0 && tmp < (1ULL << 31)); 233cabdff1aSopenharmony_ci if (av_gcd(nut->time_base[i].num, nut->time_base[i].den) != 1) { 234cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid time base %d/%d\n", 235cabdff1aSopenharmony_ci nut->time_base[i].num, 236cabdff1aSopenharmony_ci nut->time_base[i].den); 237cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 238cabdff1aSopenharmony_ci goto fail; 239cabdff1aSopenharmony_ci } 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci tmp_pts = 0; 242cabdff1aSopenharmony_ci tmp_mul = 1; 243cabdff1aSopenharmony_ci tmp_stream = 0; 244cabdff1aSopenharmony_ci tmp_head_idx = 0; 245cabdff1aSopenharmony_ci for (i = 0; i < 256;) { 246cabdff1aSopenharmony_ci int tmp_flags = ffio_read_varlen(bc); 247cabdff1aSopenharmony_ci int tmp_fields = ffio_read_varlen(bc); 248cabdff1aSopenharmony_ci if (tmp_fields < 0) { 249cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "fields %d is invalid\n", tmp_fields); 250cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 251cabdff1aSopenharmony_ci goto fail; 252cabdff1aSopenharmony_ci } 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_ci if (tmp_fields > 0) 255cabdff1aSopenharmony_ci tmp_pts = get_s(bc); 256cabdff1aSopenharmony_ci if (tmp_fields > 1) 257cabdff1aSopenharmony_ci tmp_mul = ffio_read_varlen(bc); 258cabdff1aSopenharmony_ci if (tmp_fields > 2) 259cabdff1aSopenharmony_ci tmp_stream = ffio_read_varlen(bc); 260cabdff1aSopenharmony_ci if (tmp_fields > 3) 261cabdff1aSopenharmony_ci tmp_size = ffio_read_varlen(bc); 262cabdff1aSopenharmony_ci else 263cabdff1aSopenharmony_ci tmp_size = 0; 264cabdff1aSopenharmony_ci if (tmp_fields > 4) 265cabdff1aSopenharmony_ci tmp_res = ffio_read_varlen(bc); 266cabdff1aSopenharmony_ci else 267cabdff1aSopenharmony_ci tmp_res = 0; 268cabdff1aSopenharmony_ci if (tmp_fields > 5) 269cabdff1aSopenharmony_ci count = ffio_read_varlen(bc); 270cabdff1aSopenharmony_ci else 271cabdff1aSopenharmony_ci count = tmp_mul - (unsigned)tmp_size; 272cabdff1aSopenharmony_ci if (tmp_fields > 6) 273cabdff1aSopenharmony_ci get_s(bc); 274cabdff1aSopenharmony_ci if (tmp_fields > 7) 275cabdff1aSopenharmony_ci tmp_head_idx = ffio_read_varlen(bc); 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_ci while (tmp_fields-- > 8) { 278cabdff1aSopenharmony_ci if (bc->eof_reached) { 279cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "reached EOF while decoding main header\n"); 280cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 281cabdff1aSopenharmony_ci goto fail; 282cabdff1aSopenharmony_ci } 283cabdff1aSopenharmony_ci ffio_read_varlen(bc); 284cabdff1aSopenharmony_ci } 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_ci if (count <= 0 || count > 256 - (i <= 'N') - i) { 287cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "illegal count %d at %d\n", count, i); 288cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 289cabdff1aSopenharmony_ci goto fail; 290cabdff1aSopenharmony_ci } 291cabdff1aSopenharmony_ci if (tmp_stream >= stream_count) { 292cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "illegal stream number %d >= %d\n", 293cabdff1aSopenharmony_ci tmp_stream, stream_count); 294cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 295cabdff1aSopenharmony_ci goto fail; 296cabdff1aSopenharmony_ci } 297cabdff1aSopenharmony_ci if (tmp_size < 0 || tmp_size > INT_MAX - count) { 298cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "illegal size\n"); 299cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 300cabdff1aSopenharmony_ci goto fail; 301cabdff1aSopenharmony_ci } 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci for (j = 0; j < count; j++, i++) { 304cabdff1aSopenharmony_ci if (i == 'N') { 305cabdff1aSopenharmony_ci nut->frame_code[i].flags = FLAG_INVALID; 306cabdff1aSopenharmony_ci j--; 307cabdff1aSopenharmony_ci continue; 308cabdff1aSopenharmony_ci } 309cabdff1aSopenharmony_ci nut->frame_code[i].flags = tmp_flags; 310cabdff1aSopenharmony_ci nut->frame_code[i].pts_delta = tmp_pts; 311cabdff1aSopenharmony_ci nut->frame_code[i].stream_id = tmp_stream; 312cabdff1aSopenharmony_ci nut->frame_code[i].size_mul = tmp_mul; 313cabdff1aSopenharmony_ci nut->frame_code[i].size_lsb = tmp_size + j; 314cabdff1aSopenharmony_ci nut->frame_code[i].reserved_count = tmp_res; 315cabdff1aSopenharmony_ci nut->frame_code[i].header_idx = tmp_head_idx; 316cabdff1aSopenharmony_ci } 317cabdff1aSopenharmony_ci } 318cabdff1aSopenharmony_ci av_assert0(nut->frame_code['N'].flags == FLAG_INVALID); 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_ci if (end > avio_tell(bc) + 4) { 321cabdff1aSopenharmony_ci int rem = 1024; 322cabdff1aSopenharmony_ci GET_V(nut->header_count, tmp < 128U); 323cabdff1aSopenharmony_ci nut->header_count++; 324cabdff1aSopenharmony_ci for (i = 1; i < nut->header_count; i++) { 325cabdff1aSopenharmony_ci uint8_t *hdr; 326cabdff1aSopenharmony_ci GET_V(nut->header_len[i], tmp > 0 && tmp < 256); 327cabdff1aSopenharmony_ci if (rem < nut->header_len[i]) { 328cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 329cabdff1aSopenharmony_ci "invalid elision header %d : %d > %d\n", 330cabdff1aSopenharmony_ci i, nut->header_len[i], rem); 331cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 332cabdff1aSopenharmony_ci goto fail; 333cabdff1aSopenharmony_ci } 334cabdff1aSopenharmony_ci rem -= nut->header_len[i]; 335cabdff1aSopenharmony_ci hdr = av_malloc(nut->header_len[i]); 336cabdff1aSopenharmony_ci if (!hdr) { 337cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 338cabdff1aSopenharmony_ci goto fail; 339cabdff1aSopenharmony_ci } 340cabdff1aSopenharmony_ci avio_read(bc, hdr, nut->header_len[i]); 341cabdff1aSopenharmony_ci nut->header[i] = hdr; 342cabdff1aSopenharmony_ci } 343cabdff1aSopenharmony_ci av_assert0(nut->header_len[0] == 0); 344cabdff1aSopenharmony_ci } 345cabdff1aSopenharmony_ci 346cabdff1aSopenharmony_ci // flags had been effectively introduced in version 4 347cabdff1aSopenharmony_ci if (nut->version > 3 && end > avio_tell(bc) + 4) { 348cabdff1aSopenharmony_ci nut->flags = ffio_read_varlen(bc); 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ci if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { 352cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n"); 353cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 354cabdff1aSopenharmony_ci goto fail; 355cabdff1aSopenharmony_ci } 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci nut->stream = av_calloc(stream_count, sizeof(StreamContext)); 358cabdff1aSopenharmony_ci if (!nut->stream) { 359cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 360cabdff1aSopenharmony_ci goto fail; 361cabdff1aSopenharmony_ci } 362cabdff1aSopenharmony_ci for (i = 0; i < stream_count; i++) { 363cabdff1aSopenharmony_ci if (!avformat_new_stream(s, NULL)) { 364cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 365cabdff1aSopenharmony_ci goto fail; 366cabdff1aSopenharmony_ci } 367cabdff1aSopenharmony_ci } 368cabdff1aSopenharmony_ci 369cabdff1aSopenharmony_ci return 0; 370cabdff1aSopenharmony_cifail: 371cabdff1aSopenharmony_ci av_freep(&nut->time_base); 372cabdff1aSopenharmony_ci for (i = 1; i < nut->header_count; i++) { 373cabdff1aSopenharmony_ci av_freep(&nut->header[i]); 374cabdff1aSopenharmony_ci } 375cabdff1aSopenharmony_ci nut->header_count = 0; 376cabdff1aSopenharmony_ci return ret; 377cabdff1aSopenharmony_ci} 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_cistatic int decode_stream_header(NUTContext *nut) 380cabdff1aSopenharmony_ci{ 381cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 382cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 383cabdff1aSopenharmony_ci StreamContext *stc; 384cabdff1aSopenharmony_ci int class, stream_id, ret; 385cabdff1aSopenharmony_ci uint64_t tmp, end; 386cabdff1aSopenharmony_ci AVStream *st = NULL; 387cabdff1aSopenharmony_ci 388cabdff1aSopenharmony_ci end = get_packetheader(nut, bc, 1, STREAM_STARTCODE); 389cabdff1aSopenharmony_ci end += avio_tell(bc); 390cabdff1aSopenharmony_ci 391cabdff1aSopenharmony_ci GET_V(stream_id, tmp < s->nb_streams && !nut->stream[tmp].time_base); 392cabdff1aSopenharmony_ci stc = &nut->stream[stream_id]; 393cabdff1aSopenharmony_ci st = s->streams[stream_id]; 394cabdff1aSopenharmony_ci if (!st) 395cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 396cabdff1aSopenharmony_ci 397cabdff1aSopenharmony_ci class = ffio_read_varlen(bc); 398cabdff1aSopenharmony_ci tmp = get_fourcc(bc); 399cabdff1aSopenharmony_ci st->codecpar->codec_tag = tmp; 400cabdff1aSopenharmony_ci switch (class) { 401cabdff1aSopenharmony_ci case 0: 402cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 403cabdff1aSopenharmony_ci st->codecpar->codec_id = av_codec_get_id((const AVCodecTag * const []) { 404cabdff1aSopenharmony_ci ff_nut_video_tags, 405cabdff1aSopenharmony_ci ff_codec_bmp_tags, 406cabdff1aSopenharmony_ci ff_codec_movvideo_tags, 407cabdff1aSopenharmony_ci 0 408cabdff1aSopenharmony_ci }, 409cabdff1aSopenharmony_ci tmp); 410cabdff1aSopenharmony_ci break; 411cabdff1aSopenharmony_ci case 1: 412cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 413cabdff1aSopenharmony_ci st->codecpar->codec_id = av_codec_get_id((const AVCodecTag * const []) { 414cabdff1aSopenharmony_ci ff_nut_audio_tags, 415cabdff1aSopenharmony_ci ff_codec_wav_tags, 416cabdff1aSopenharmony_ci ff_nut_audio_extra_tags, 417cabdff1aSopenharmony_ci 0 418cabdff1aSopenharmony_ci }, 419cabdff1aSopenharmony_ci tmp); 420cabdff1aSopenharmony_ci break; 421cabdff1aSopenharmony_ci case 2: 422cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; 423cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_nut_subtitle_tags, tmp); 424cabdff1aSopenharmony_ci break; 425cabdff1aSopenharmony_ci case 3: 426cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_DATA; 427cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_nut_data_tags, tmp); 428cabdff1aSopenharmony_ci break; 429cabdff1aSopenharmony_ci default: 430cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class); 431cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 432cabdff1aSopenharmony_ci } 433cabdff1aSopenharmony_ci if (class < 3 && st->codecpar->codec_id == AV_CODEC_ID_NONE) 434cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 435cabdff1aSopenharmony_ci "Unknown codec tag '0x%04x' for stream number %d\n", 436cabdff1aSopenharmony_ci (unsigned int) tmp, stream_id); 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_ci GET_V(stc->time_base_id, tmp < nut->time_base_count); 439cabdff1aSopenharmony_ci GET_V(stc->msb_pts_shift, tmp < 16); 440cabdff1aSopenharmony_ci stc->max_pts_distance = ffio_read_varlen(bc); 441cabdff1aSopenharmony_ci GET_V(stc->decode_delay, tmp < 1000); // sanity limit, raise this if Moore's law is true 442cabdff1aSopenharmony_ci st->codecpar->video_delay = stc->decode_delay; 443cabdff1aSopenharmony_ci ffio_read_varlen(bc); // stream flags 444cabdff1aSopenharmony_ci 445cabdff1aSopenharmony_ci GET_V(st->codecpar->extradata_size, tmp < (1 << 30)); 446cabdff1aSopenharmony_ci if (st->codecpar->extradata_size) { 447cabdff1aSopenharmony_ci ret = ff_get_extradata(s, st->codecpar, bc, 448cabdff1aSopenharmony_ci st->codecpar->extradata_size); 449cabdff1aSopenharmony_ci if (ret < 0) 450cabdff1aSopenharmony_ci return ret; 451cabdff1aSopenharmony_ci } 452cabdff1aSopenharmony_ci 453cabdff1aSopenharmony_ci if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { 454cabdff1aSopenharmony_ci GET_V(st->codecpar->width, tmp > 0); 455cabdff1aSopenharmony_ci GET_V(st->codecpar->height, tmp > 0); 456cabdff1aSopenharmony_ci st->sample_aspect_ratio.num = ffio_read_varlen(bc); 457cabdff1aSopenharmony_ci st->sample_aspect_ratio.den = ffio_read_varlen(bc); 458cabdff1aSopenharmony_ci if ((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)) { 459cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", 460cabdff1aSopenharmony_ci st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); 461cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 462cabdff1aSopenharmony_ci goto fail; 463cabdff1aSopenharmony_ci } 464cabdff1aSopenharmony_ci ffio_read_varlen(bc); /* csp type */ 465cabdff1aSopenharmony_ci } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { 466cabdff1aSopenharmony_ci GET_V(st->codecpar->sample_rate, tmp > 0); 467cabdff1aSopenharmony_ci ffio_read_varlen(bc); // samplerate_den 468cabdff1aSopenharmony_ci GET_V(st->codecpar->ch_layout.nb_channels, tmp > 0); 469cabdff1aSopenharmony_ci } 470cabdff1aSopenharmony_ci if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { 471cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 472cabdff1aSopenharmony_ci "stream header %d checksum mismatch\n", stream_id); 473cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 474cabdff1aSopenharmony_ci goto fail; 475cabdff1aSopenharmony_ci } 476cabdff1aSopenharmony_ci stc->time_base = &nut->time_base[stc->time_base_id]; 477cabdff1aSopenharmony_ci avpriv_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, 478cabdff1aSopenharmony_ci stc->time_base->den); 479cabdff1aSopenharmony_ci return 0; 480cabdff1aSopenharmony_cifail: 481cabdff1aSopenharmony_ci if (st && st->codecpar) { 482cabdff1aSopenharmony_ci av_freep(&st->codecpar->extradata); 483cabdff1aSopenharmony_ci st->codecpar->extradata_size = 0; 484cabdff1aSopenharmony_ci } 485cabdff1aSopenharmony_ci return ret; 486cabdff1aSopenharmony_ci} 487cabdff1aSopenharmony_ci 488cabdff1aSopenharmony_cistatic void set_disposition_bits(AVFormatContext *avf, char *value, 489cabdff1aSopenharmony_ci int stream_id) 490cabdff1aSopenharmony_ci{ 491cabdff1aSopenharmony_ci int flag = 0, i; 492cabdff1aSopenharmony_ci 493cabdff1aSopenharmony_ci for (i = 0; ff_nut_dispositions[i].flag; ++i) 494cabdff1aSopenharmony_ci if (!strcmp(ff_nut_dispositions[i].str, value)) 495cabdff1aSopenharmony_ci flag = ff_nut_dispositions[i].flag; 496cabdff1aSopenharmony_ci if (!flag) 497cabdff1aSopenharmony_ci av_log(avf, AV_LOG_INFO, "unknown disposition type '%s'\n", value); 498cabdff1aSopenharmony_ci for (i = 0; i < avf->nb_streams; ++i) 499cabdff1aSopenharmony_ci if (stream_id == i || stream_id == -1) 500cabdff1aSopenharmony_ci avf->streams[i]->disposition |= flag; 501cabdff1aSopenharmony_ci} 502cabdff1aSopenharmony_ci 503cabdff1aSopenharmony_cistatic int decode_info_header(NUTContext *nut) 504cabdff1aSopenharmony_ci{ 505cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 506cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 507cabdff1aSopenharmony_ci uint64_t tmp, chapter_start, chapter_len; 508cabdff1aSopenharmony_ci unsigned int stream_id_plus1, count; 509cabdff1aSopenharmony_ci int i, ret = 0; 510cabdff1aSopenharmony_ci int64_t chapter_id, value, end; 511cabdff1aSopenharmony_ci char name[256], str_value[1024], type_str[256]; 512cabdff1aSopenharmony_ci const char *type; 513cabdff1aSopenharmony_ci int *event_flags = NULL; 514cabdff1aSopenharmony_ci AVChapter *chapter = NULL; 515cabdff1aSopenharmony_ci AVStream *st = NULL; 516cabdff1aSopenharmony_ci AVDictionary **metadata = NULL; 517cabdff1aSopenharmony_ci int metadata_flag = 0; 518cabdff1aSopenharmony_ci 519cabdff1aSopenharmony_ci end = get_packetheader(nut, bc, 1, INFO_STARTCODE); 520cabdff1aSopenharmony_ci end += avio_tell(bc); 521cabdff1aSopenharmony_ci 522cabdff1aSopenharmony_ci GET_V(stream_id_plus1, tmp <= s->nb_streams); 523cabdff1aSopenharmony_ci chapter_id = get_s(bc); 524cabdff1aSopenharmony_ci chapter_start = ffio_read_varlen(bc); 525cabdff1aSopenharmony_ci chapter_len = ffio_read_varlen(bc); 526cabdff1aSopenharmony_ci count = ffio_read_varlen(bc); 527cabdff1aSopenharmony_ci 528cabdff1aSopenharmony_ci if (chapter_id && !stream_id_plus1) { 529cabdff1aSopenharmony_ci int64_t start = chapter_start / nut->time_base_count; 530cabdff1aSopenharmony_ci chapter = avpriv_new_chapter(s, chapter_id, 531cabdff1aSopenharmony_ci nut->time_base[chapter_start % 532cabdff1aSopenharmony_ci nut->time_base_count], 533cabdff1aSopenharmony_ci start, start + chapter_len, NULL); 534cabdff1aSopenharmony_ci if (!chapter) { 535cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Could not create chapter.\n"); 536cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 537cabdff1aSopenharmony_ci } 538cabdff1aSopenharmony_ci metadata = &chapter->metadata; 539cabdff1aSopenharmony_ci } else if (stream_id_plus1) { 540cabdff1aSopenharmony_ci st = s->streams[stream_id_plus1 - 1]; 541cabdff1aSopenharmony_ci metadata = &st->metadata; 542cabdff1aSopenharmony_ci event_flags = &st->event_flags; 543cabdff1aSopenharmony_ci metadata_flag = AVSTREAM_EVENT_FLAG_METADATA_UPDATED; 544cabdff1aSopenharmony_ci } else { 545cabdff1aSopenharmony_ci metadata = &s->metadata; 546cabdff1aSopenharmony_ci event_flags = &s->event_flags; 547cabdff1aSopenharmony_ci metadata_flag = AVFMT_EVENT_FLAG_METADATA_UPDATED; 548cabdff1aSopenharmony_ci } 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 551cabdff1aSopenharmony_ci ret = get_str(bc, name, sizeof(name)); 552cabdff1aSopenharmony_ci if (ret < 0) { 553cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "get_str failed while decoding info header\n"); 554cabdff1aSopenharmony_ci return ret; 555cabdff1aSopenharmony_ci } 556cabdff1aSopenharmony_ci value = get_s(bc); 557cabdff1aSopenharmony_ci str_value[0] = 0; 558cabdff1aSopenharmony_ci 559cabdff1aSopenharmony_ci if (value == -1) { 560cabdff1aSopenharmony_ci type = "UTF-8"; 561cabdff1aSopenharmony_ci ret = get_str(bc, str_value, sizeof(str_value)); 562cabdff1aSopenharmony_ci } else if (value == -2) { 563cabdff1aSopenharmony_ci ret = get_str(bc, type_str, sizeof(type_str)); 564cabdff1aSopenharmony_ci if (ret < 0) { 565cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "get_str failed while decoding info header\n"); 566cabdff1aSopenharmony_ci return ret; 567cabdff1aSopenharmony_ci } 568cabdff1aSopenharmony_ci type = type_str; 569cabdff1aSopenharmony_ci ret = get_str(bc, str_value, sizeof(str_value)); 570cabdff1aSopenharmony_ci } else if (value == -3) { 571cabdff1aSopenharmony_ci type = "s"; 572cabdff1aSopenharmony_ci value = get_s(bc); 573cabdff1aSopenharmony_ci } else if (value == -4) { 574cabdff1aSopenharmony_ci type = "t"; 575cabdff1aSopenharmony_ci value = ffio_read_varlen(bc); 576cabdff1aSopenharmony_ci } else if (value < -4) { 577cabdff1aSopenharmony_ci type = "r"; 578cabdff1aSopenharmony_ci get_s(bc); 579cabdff1aSopenharmony_ci } else { 580cabdff1aSopenharmony_ci type = "v"; 581cabdff1aSopenharmony_ci } 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_ci if (ret < 0) { 584cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "get_str failed while decoding info header\n"); 585cabdff1aSopenharmony_ci return ret; 586cabdff1aSopenharmony_ci } 587cabdff1aSopenharmony_ci 588cabdff1aSopenharmony_ci if (stream_id_plus1 > s->nb_streams) { 589cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 590cabdff1aSopenharmony_ci "invalid stream id %d for info packet\n", 591cabdff1aSopenharmony_ci stream_id_plus1); 592cabdff1aSopenharmony_ci continue; 593cabdff1aSopenharmony_ci } 594cabdff1aSopenharmony_ci 595cabdff1aSopenharmony_ci if (!strcmp(type, "UTF-8")) { 596cabdff1aSopenharmony_ci if (chapter_id == 0 && !strcmp(name, "Disposition")) { 597cabdff1aSopenharmony_ci set_disposition_bits(s, str_value, stream_id_plus1 - 1); 598cabdff1aSopenharmony_ci continue; 599cabdff1aSopenharmony_ci } 600cabdff1aSopenharmony_ci 601cabdff1aSopenharmony_ci if (stream_id_plus1 && !strcmp(name, "r_frame_rate")) { 602cabdff1aSopenharmony_ci sscanf(str_value, "%d/%d", &st->r_frame_rate.num, &st->r_frame_rate.den); 603cabdff1aSopenharmony_ci if (st->r_frame_rate.num >= 1000LL*st->r_frame_rate.den || 604cabdff1aSopenharmony_ci st->r_frame_rate.num < 0 || st->r_frame_rate.den < 0) 605cabdff1aSopenharmony_ci st->r_frame_rate.num = st->r_frame_rate.den = 0; 606cabdff1aSopenharmony_ci continue; 607cabdff1aSopenharmony_ci } 608cabdff1aSopenharmony_ci 609cabdff1aSopenharmony_ci if (metadata && av_strcasecmp(name, "Uses") && 610cabdff1aSopenharmony_ci av_strcasecmp(name, "Depends") && av_strcasecmp(name, "Replaces")) { 611cabdff1aSopenharmony_ci if (event_flags) 612cabdff1aSopenharmony_ci *event_flags |= metadata_flag; 613cabdff1aSopenharmony_ci av_dict_set(metadata, name, str_value, 0); 614cabdff1aSopenharmony_ci } 615cabdff1aSopenharmony_ci } 616cabdff1aSopenharmony_ci } 617cabdff1aSopenharmony_ci 618cabdff1aSopenharmony_ci if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { 619cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n"); 620cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 621cabdff1aSopenharmony_ci } 622cabdff1aSopenharmony_cifail: 623cabdff1aSopenharmony_ci return FFMIN(ret, 0); 624cabdff1aSopenharmony_ci} 625cabdff1aSopenharmony_ci 626cabdff1aSopenharmony_cistatic int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr) 627cabdff1aSopenharmony_ci{ 628cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 629cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 630cabdff1aSopenharmony_ci int64_t end; 631cabdff1aSopenharmony_ci uint64_t tmp; 632cabdff1aSopenharmony_ci int ret; 633cabdff1aSopenharmony_ci 634cabdff1aSopenharmony_ci nut->last_syncpoint_pos = avio_tell(bc) - 8; 635cabdff1aSopenharmony_ci 636cabdff1aSopenharmony_ci end = get_packetheader(nut, bc, 1, SYNCPOINT_STARTCODE); 637cabdff1aSopenharmony_ci end += avio_tell(bc); 638cabdff1aSopenharmony_ci 639cabdff1aSopenharmony_ci tmp = ffio_read_varlen(bc); 640cabdff1aSopenharmony_ci *back_ptr = nut->last_syncpoint_pos - 16 * ffio_read_varlen(bc); 641cabdff1aSopenharmony_ci if (*back_ptr < 0) 642cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 643cabdff1aSopenharmony_ci 644cabdff1aSopenharmony_ci ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], 645cabdff1aSopenharmony_ci tmp / nut->time_base_count); 646cabdff1aSopenharmony_ci 647cabdff1aSopenharmony_ci if (nut->flags & NUT_BROADCAST) { 648cabdff1aSopenharmony_ci tmp = ffio_read_varlen(bc); 649cabdff1aSopenharmony_ci av_log(s, AV_LOG_VERBOSE, "Syncpoint wallclock %"PRId64"\n", 650cabdff1aSopenharmony_ci av_rescale_q(tmp / nut->time_base_count, 651cabdff1aSopenharmony_ci nut->time_base[tmp % nut->time_base_count], 652cabdff1aSopenharmony_ci AV_TIME_BASE_Q)); 653cabdff1aSopenharmony_ci } 654cabdff1aSopenharmony_ci 655cabdff1aSopenharmony_ci if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { 656cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n"); 657cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 658cabdff1aSopenharmony_ci } 659cabdff1aSopenharmony_ci 660cabdff1aSopenharmony_ci *ts = tmp / nut->time_base_count * 661cabdff1aSopenharmony_ci av_q2d(nut->time_base[tmp % nut->time_base_count]) * AV_TIME_BASE; 662cabdff1aSopenharmony_ci 663cabdff1aSopenharmony_ci if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts)) < 0) 664cabdff1aSopenharmony_ci return ret; 665cabdff1aSopenharmony_ci 666cabdff1aSopenharmony_ci return 0; 667cabdff1aSopenharmony_ci} 668cabdff1aSopenharmony_ci 669cabdff1aSopenharmony_ci//FIXME calculate exactly, this is just a good approximation. 670cabdff1aSopenharmony_cistatic int64_t find_duration(NUTContext *nut, int64_t filesize) 671cabdff1aSopenharmony_ci{ 672cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 673cabdff1aSopenharmony_ci int64_t duration = 0; 674cabdff1aSopenharmony_ci 675cabdff1aSopenharmony_ci ff_find_last_ts(s, -1, &duration, NULL, nut_read_timestamp); 676cabdff1aSopenharmony_ci 677cabdff1aSopenharmony_ci if(duration > 0) 678cabdff1aSopenharmony_ci s->duration_estimation_method = AVFMT_DURATION_FROM_PTS; 679cabdff1aSopenharmony_ci return duration; 680cabdff1aSopenharmony_ci} 681cabdff1aSopenharmony_ci 682cabdff1aSopenharmony_cistatic int find_and_decode_index(NUTContext *nut) 683cabdff1aSopenharmony_ci{ 684cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 685cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 686cabdff1aSopenharmony_ci uint64_t tmp, end; 687cabdff1aSopenharmony_ci int i, j, syncpoint_count; 688cabdff1aSopenharmony_ci int64_t filesize = avio_size(bc); 689cabdff1aSopenharmony_ci int64_t *syncpoints = NULL; 690cabdff1aSopenharmony_ci uint64_t max_pts; 691cabdff1aSopenharmony_ci int8_t *has_keyframe = NULL; 692cabdff1aSopenharmony_ci int ret = AVERROR_INVALIDDATA; 693cabdff1aSopenharmony_ci 694cabdff1aSopenharmony_ci if(filesize <= 0) 695cabdff1aSopenharmony_ci return -1; 696cabdff1aSopenharmony_ci 697cabdff1aSopenharmony_ci avio_seek(bc, filesize - 12, SEEK_SET); 698cabdff1aSopenharmony_ci avio_seek(bc, filesize - avio_rb64(bc), SEEK_SET); 699cabdff1aSopenharmony_ci if (avio_rb64(bc) != INDEX_STARTCODE) { 700cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "no index at the end\n"); 701cabdff1aSopenharmony_ci 702cabdff1aSopenharmony_ci if(s->duration<=0) 703cabdff1aSopenharmony_ci s->duration = find_duration(nut, filesize); 704cabdff1aSopenharmony_ci return ret; 705cabdff1aSopenharmony_ci } 706cabdff1aSopenharmony_ci 707cabdff1aSopenharmony_ci end = get_packetheader(nut, bc, 1, INDEX_STARTCODE); 708cabdff1aSopenharmony_ci end += avio_tell(bc); 709cabdff1aSopenharmony_ci 710cabdff1aSopenharmony_ci max_pts = ffio_read_varlen(bc); 711cabdff1aSopenharmony_ci s->duration = av_rescale_q(max_pts / nut->time_base_count, 712cabdff1aSopenharmony_ci nut->time_base[max_pts % nut->time_base_count], 713cabdff1aSopenharmony_ci AV_TIME_BASE_Q); 714cabdff1aSopenharmony_ci s->duration_estimation_method = AVFMT_DURATION_FROM_PTS; 715cabdff1aSopenharmony_ci 716cabdff1aSopenharmony_ci GET_V(syncpoint_count, tmp < INT_MAX / 8 && tmp > 0); 717cabdff1aSopenharmony_ci syncpoints = av_malloc_array(syncpoint_count, sizeof(int64_t)); 718cabdff1aSopenharmony_ci has_keyframe = av_malloc_array(syncpoint_count + 1, sizeof(int8_t)); 719cabdff1aSopenharmony_ci if (!syncpoints || !has_keyframe) { 720cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 721cabdff1aSopenharmony_ci goto fail; 722cabdff1aSopenharmony_ci } 723cabdff1aSopenharmony_ci for (i = 0; i < syncpoint_count; i++) { 724cabdff1aSopenharmony_ci syncpoints[i] = ffio_read_varlen(bc); 725cabdff1aSopenharmony_ci if (syncpoints[i] <= 0) 726cabdff1aSopenharmony_ci goto fail; 727cabdff1aSopenharmony_ci if (i) 728cabdff1aSopenharmony_ci syncpoints[i] += syncpoints[i - 1]; 729cabdff1aSopenharmony_ci } 730cabdff1aSopenharmony_ci 731cabdff1aSopenharmony_ci for (i = 0; i < s->nb_streams; i++) { 732cabdff1aSopenharmony_ci int64_t last_pts = -1; 733cabdff1aSopenharmony_ci for (j = 0; j < syncpoint_count;) { 734cabdff1aSopenharmony_ci uint64_t x = ffio_read_varlen(bc); 735cabdff1aSopenharmony_ci int type = x & 1; 736cabdff1aSopenharmony_ci int n = j; 737cabdff1aSopenharmony_ci x >>= 1; 738cabdff1aSopenharmony_ci if (type) { 739cabdff1aSopenharmony_ci int flag = x & 1; 740cabdff1aSopenharmony_ci x >>= 1; 741cabdff1aSopenharmony_ci if (n + x >= syncpoint_count + 1) { 742cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "index overflow A %d + %"PRIu64" >= %d\n", n, x, syncpoint_count + 1); 743cabdff1aSopenharmony_ci goto fail; 744cabdff1aSopenharmony_ci } 745cabdff1aSopenharmony_ci while (x--) 746cabdff1aSopenharmony_ci has_keyframe[n++] = flag; 747cabdff1aSopenharmony_ci has_keyframe[n++] = !flag; 748cabdff1aSopenharmony_ci } else { 749cabdff1aSopenharmony_ci if (x <= 1) { 750cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "index: x %"PRIu64" is invalid\n", x); 751cabdff1aSopenharmony_ci goto fail; 752cabdff1aSopenharmony_ci } 753cabdff1aSopenharmony_ci while (x != 1) { 754cabdff1aSopenharmony_ci if (n >= syncpoint_count + 1) { 755cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "index overflow B\n"); 756cabdff1aSopenharmony_ci goto fail; 757cabdff1aSopenharmony_ci } 758cabdff1aSopenharmony_ci has_keyframe[n++] = x & 1; 759cabdff1aSopenharmony_ci x >>= 1; 760cabdff1aSopenharmony_ci } 761cabdff1aSopenharmony_ci } 762cabdff1aSopenharmony_ci if (has_keyframe[0]) { 763cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "keyframe before first syncpoint in index\n"); 764cabdff1aSopenharmony_ci goto fail; 765cabdff1aSopenharmony_ci } 766cabdff1aSopenharmony_ci av_assert0(n <= syncpoint_count + 1); 767cabdff1aSopenharmony_ci for (; j < n && j < syncpoint_count; j++) { 768cabdff1aSopenharmony_ci if (has_keyframe[j]) { 769cabdff1aSopenharmony_ci uint64_t B, A = ffio_read_varlen(bc); 770cabdff1aSopenharmony_ci if (!A) { 771cabdff1aSopenharmony_ci A = ffio_read_varlen(bc); 772cabdff1aSopenharmony_ci B = ffio_read_varlen(bc); 773cabdff1aSopenharmony_ci // eor_pts[j][i] = last_pts + A + B 774cabdff1aSopenharmony_ci } else 775cabdff1aSopenharmony_ci B = 0; 776cabdff1aSopenharmony_ci av_add_index_entry(s->streams[i], 16 * syncpoints[j - 1], 777cabdff1aSopenharmony_ci last_pts + A, 0, 0, AVINDEX_KEYFRAME); 778cabdff1aSopenharmony_ci last_pts += A + B; 779cabdff1aSopenharmony_ci } 780cabdff1aSopenharmony_ci } 781cabdff1aSopenharmony_ci } 782cabdff1aSopenharmony_ci } 783cabdff1aSopenharmony_ci 784cabdff1aSopenharmony_ci if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { 785cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "index checksum mismatch\n"); 786cabdff1aSopenharmony_ci goto fail; 787cabdff1aSopenharmony_ci } 788cabdff1aSopenharmony_ci ret = 0; 789cabdff1aSopenharmony_ci 790cabdff1aSopenharmony_cifail: 791cabdff1aSopenharmony_ci av_free(syncpoints); 792cabdff1aSopenharmony_ci av_free(has_keyframe); 793cabdff1aSopenharmony_ci return ret; 794cabdff1aSopenharmony_ci} 795cabdff1aSopenharmony_ci 796cabdff1aSopenharmony_cistatic int nut_read_close(AVFormatContext *s) 797cabdff1aSopenharmony_ci{ 798cabdff1aSopenharmony_ci NUTContext *nut = s->priv_data; 799cabdff1aSopenharmony_ci int i; 800cabdff1aSopenharmony_ci 801cabdff1aSopenharmony_ci av_freep(&nut->time_base); 802cabdff1aSopenharmony_ci av_freep(&nut->stream); 803cabdff1aSopenharmony_ci ff_nut_free_sp(nut); 804cabdff1aSopenharmony_ci for (i = 1; i < nut->header_count; i++) 805cabdff1aSopenharmony_ci av_freep(&nut->header[i]); 806cabdff1aSopenharmony_ci 807cabdff1aSopenharmony_ci return 0; 808cabdff1aSopenharmony_ci} 809cabdff1aSopenharmony_ci 810cabdff1aSopenharmony_cistatic int nut_read_header(AVFormatContext *s) 811cabdff1aSopenharmony_ci{ 812cabdff1aSopenharmony_ci NUTContext *nut = s->priv_data; 813cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 814cabdff1aSopenharmony_ci int64_t pos; 815cabdff1aSopenharmony_ci int initialized_stream_count, ret; 816cabdff1aSopenharmony_ci 817cabdff1aSopenharmony_ci nut->avf = s; 818cabdff1aSopenharmony_ci 819cabdff1aSopenharmony_ci /* main header */ 820cabdff1aSopenharmony_ci pos = 0; 821cabdff1aSopenharmony_ci ret = 0; 822cabdff1aSopenharmony_ci do { 823cabdff1aSopenharmony_ci if (ret == AVERROR(ENOMEM)) 824cabdff1aSopenharmony_ci return ret; 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_ci pos = find_startcode(bc, MAIN_STARTCODE, pos) + 1; 827cabdff1aSopenharmony_ci if (pos < 0 + 1) { 828cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "No main startcode found.\n"); 829cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 830cabdff1aSopenharmony_ci } 831cabdff1aSopenharmony_ci } while ((ret = decode_main_header(nut)) < 0); 832cabdff1aSopenharmony_ci 833cabdff1aSopenharmony_ci /* stream headers */ 834cabdff1aSopenharmony_ci pos = 0; 835cabdff1aSopenharmony_ci for (initialized_stream_count = 0; initialized_stream_count < s->nb_streams;) { 836cabdff1aSopenharmony_ci pos = find_startcode(bc, STREAM_STARTCODE, pos) + 1; 837cabdff1aSopenharmony_ci if (pos < 0 + 1) { 838cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Not all stream headers found.\n"); 839cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 840cabdff1aSopenharmony_ci } 841cabdff1aSopenharmony_ci if (decode_stream_header(nut) >= 0) 842cabdff1aSopenharmony_ci initialized_stream_count++; 843cabdff1aSopenharmony_ci } 844cabdff1aSopenharmony_ci 845cabdff1aSopenharmony_ci /* info headers */ 846cabdff1aSopenharmony_ci pos = 0; 847cabdff1aSopenharmony_ci for (;;) { 848cabdff1aSopenharmony_ci uint64_t startcode = find_any_startcode(bc, pos); 849cabdff1aSopenharmony_ci pos = avio_tell(bc); 850cabdff1aSopenharmony_ci 851cabdff1aSopenharmony_ci if (startcode == 0) { 852cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "EOF before video frames\n"); 853cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 854cabdff1aSopenharmony_ci } else if (startcode == SYNCPOINT_STARTCODE) { 855cabdff1aSopenharmony_ci nut->next_startcode = startcode; 856cabdff1aSopenharmony_ci break; 857cabdff1aSopenharmony_ci } else if (startcode != INFO_STARTCODE) { 858cabdff1aSopenharmony_ci continue; 859cabdff1aSopenharmony_ci } 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_ci decode_info_header(nut); 862cabdff1aSopenharmony_ci } 863cabdff1aSopenharmony_ci 864cabdff1aSopenharmony_ci ffformatcontext(s)->data_offset = pos - 8; 865cabdff1aSopenharmony_ci 866cabdff1aSopenharmony_ci if (bc->seekable & AVIO_SEEKABLE_NORMAL) { 867cabdff1aSopenharmony_ci int64_t orig_pos = avio_tell(bc); 868cabdff1aSopenharmony_ci find_and_decode_index(nut); 869cabdff1aSopenharmony_ci avio_seek(bc, orig_pos, SEEK_SET); 870cabdff1aSopenharmony_ci } 871cabdff1aSopenharmony_ci av_assert0(nut->next_startcode == SYNCPOINT_STARTCODE); 872cabdff1aSopenharmony_ci 873cabdff1aSopenharmony_ci ff_metadata_conv_ctx(s, NULL, ff_nut_metadata_conv); 874cabdff1aSopenharmony_ci 875cabdff1aSopenharmony_ci return 0; 876cabdff1aSopenharmony_ci} 877cabdff1aSopenharmony_ci 878cabdff1aSopenharmony_cistatic int read_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int is_meta, int64_t maxpos) 879cabdff1aSopenharmony_ci{ 880cabdff1aSopenharmony_ci int count = ffio_read_varlen(bc); 881cabdff1aSopenharmony_ci int skip_start = 0; 882cabdff1aSopenharmony_ci int skip_end = 0; 883cabdff1aSopenharmony_ci int channels = 0; 884cabdff1aSopenharmony_ci int64_t channel_layout = 0; 885cabdff1aSopenharmony_ci int sample_rate = 0; 886cabdff1aSopenharmony_ci int width = 0; 887cabdff1aSopenharmony_ci int height = 0; 888cabdff1aSopenharmony_ci int i, ret; 889cabdff1aSopenharmony_ci 890cabdff1aSopenharmony_ci for (i=0; i<count; i++) { 891cabdff1aSopenharmony_ci uint8_t name[256], str_value[256], type_str[256]; 892cabdff1aSopenharmony_ci int value; 893cabdff1aSopenharmony_ci if (avio_tell(bc) >= maxpos) 894cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 895cabdff1aSopenharmony_ci ret = get_str(bc, name, sizeof(name)); 896cabdff1aSopenharmony_ci if (ret < 0) { 897cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "get_str failed while reading sm data\n"); 898cabdff1aSopenharmony_ci return ret; 899cabdff1aSopenharmony_ci } 900cabdff1aSopenharmony_ci value = get_s(bc); 901cabdff1aSopenharmony_ci 902cabdff1aSopenharmony_ci if (value == -1) { 903cabdff1aSopenharmony_ci ret = get_str(bc, str_value, sizeof(str_value)); 904cabdff1aSopenharmony_ci if (ret < 0) { 905cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "get_str failed while reading sm data\n"); 906cabdff1aSopenharmony_ci return ret; 907cabdff1aSopenharmony_ci } 908cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Unknown string %s / %s\n", name, str_value); 909cabdff1aSopenharmony_ci } else if (value == -2) { 910cabdff1aSopenharmony_ci uint8_t *dst = NULL; 911cabdff1aSopenharmony_ci int64_t v64, value_len; 912cabdff1aSopenharmony_ci 913cabdff1aSopenharmony_ci ret = get_str(bc, type_str, sizeof(type_str)); 914cabdff1aSopenharmony_ci if (ret < 0) { 915cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "get_str failed while reading sm data\n"); 916cabdff1aSopenharmony_ci return ret; 917cabdff1aSopenharmony_ci } 918cabdff1aSopenharmony_ci value_len = ffio_read_varlen(bc); 919cabdff1aSopenharmony_ci if (value_len < 0 || value_len >= maxpos - avio_tell(bc)) 920cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 921cabdff1aSopenharmony_ci if (!strcmp(name, "Palette")) { 922cabdff1aSopenharmony_ci dst = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, value_len); 923cabdff1aSopenharmony_ci } else if (!strcmp(name, "Extradata")) { 924cabdff1aSopenharmony_ci dst = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, value_len); 925cabdff1aSopenharmony_ci } else if (sscanf(name, "CodecSpecificSide%"SCNd64"", &v64) == 1) { 926cabdff1aSopenharmony_ci dst = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, value_len + 8); 927cabdff1aSopenharmony_ci if(!dst) 928cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 929cabdff1aSopenharmony_ci AV_WB64(dst, v64); 930cabdff1aSopenharmony_ci dst += 8; 931cabdff1aSopenharmony_ci } else if (!strcmp(name, "ChannelLayout") && value_len == 8) { 932cabdff1aSopenharmony_ci channel_layout = avio_rl64(bc); 933cabdff1aSopenharmony_ci continue; 934cabdff1aSopenharmony_ci } else { 935cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Unknown data %s / %s\n", name, type_str); 936cabdff1aSopenharmony_ci avio_skip(bc, value_len); 937cabdff1aSopenharmony_ci continue; 938cabdff1aSopenharmony_ci } 939cabdff1aSopenharmony_ci if(!dst) 940cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 941cabdff1aSopenharmony_ci avio_read(bc, dst, value_len); 942cabdff1aSopenharmony_ci } else if (value == -3) { 943cabdff1aSopenharmony_ci value = get_s(bc); 944cabdff1aSopenharmony_ci } else if (value == -4) { 945cabdff1aSopenharmony_ci value = ffio_read_varlen(bc); 946cabdff1aSopenharmony_ci } else if (value < -4) { 947cabdff1aSopenharmony_ci get_s(bc); 948cabdff1aSopenharmony_ci } else { 949cabdff1aSopenharmony_ci if (!strcmp(name, "SkipStart")) { 950cabdff1aSopenharmony_ci skip_start = value; 951cabdff1aSopenharmony_ci } else if (!strcmp(name, "SkipEnd")) { 952cabdff1aSopenharmony_ci skip_end = value; 953cabdff1aSopenharmony_ci } else if (!strcmp(name, "Channels")) { 954cabdff1aSopenharmony_ci channels = value; 955cabdff1aSopenharmony_ci } else if (!strcmp(name, "SampleRate")) { 956cabdff1aSopenharmony_ci sample_rate = value; 957cabdff1aSopenharmony_ci } else if (!strcmp(name, "Width")) { 958cabdff1aSopenharmony_ci width = value; 959cabdff1aSopenharmony_ci } else if (!strcmp(name, "Height")) { 960cabdff1aSopenharmony_ci height = value; 961cabdff1aSopenharmony_ci } else { 962cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Unknown integer %s\n", name); 963cabdff1aSopenharmony_ci } 964cabdff1aSopenharmony_ci } 965cabdff1aSopenharmony_ci } 966cabdff1aSopenharmony_ci 967cabdff1aSopenharmony_ci if (channels || channel_layout || sample_rate || width || height) { 968cabdff1aSopenharmony_ci uint8_t *dst = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, 28); 969cabdff1aSopenharmony_ci if (!dst) 970cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 971cabdff1aSopenharmony_ci bytestream_put_le32(&dst, 972cabdff1aSopenharmony_ci#if FF_API_OLD_CHANNEL_LAYOUT 973cabdff1aSopenharmony_ci AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT*(!!channels) + 974cabdff1aSopenharmony_ci AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT*(!!channel_layout) + 975cabdff1aSopenharmony_ci#endif 976cabdff1aSopenharmony_ci AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE*(!!sample_rate) + 977cabdff1aSopenharmony_ci AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS*(!!(width|height)) 978cabdff1aSopenharmony_ci ); 979cabdff1aSopenharmony_ci if (channels) 980cabdff1aSopenharmony_ci bytestream_put_le32(&dst, channels); 981cabdff1aSopenharmony_ci if (channel_layout) 982cabdff1aSopenharmony_ci bytestream_put_le64(&dst, channel_layout); 983cabdff1aSopenharmony_ci if (sample_rate) 984cabdff1aSopenharmony_ci bytestream_put_le32(&dst, sample_rate); 985cabdff1aSopenharmony_ci if (width || height){ 986cabdff1aSopenharmony_ci bytestream_put_le32(&dst, width); 987cabdff1aSopenharmony_ci bytestream_put_le32(&dst, height); 988cabdff1aSopenharmony_ci } 989cabdff1aSopenharmony_ci } 990cabdff1aSopenharmony_ci 991cabdff1aSopenharmony_ci if (skip_start || skip_end) { 992cabdff1aSopenharmony_ci uint8_t *dst = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); 993cabdff1aSopenharmony_ci if (!dst) 994cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 995cabdff1aSopenharmony_ci AV_WL32(dst, skip_start); 996cabdff1aSopenharmony_ci AV_WL32(dst+4, skip_end); 997cabdff1aSopenharmony_ci } 998cabdff1aSopenharmony_ci 999cabdff1aSopenharmony_ci if (avio_tell(bc) >= maxpos) 1000cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1001cabdff1aSopenharmony_ci 1002cabdff1aSopenharmony_ci return 0; 1003cabdff1aSopenharmony_ci} 1004cabdff1aSopenharmony_ci 1005cabdff1aSopenharmony_cistatic int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, 1006cabdff1aSopenharmony_ci uint8_t *header_idx, int frame_code) 1007cabdff1aSopenharmony_ci{ 1008cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 1009cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 1010cabdff1aSopenharmony_ci StreamContext *stc; 1011cabdff1aSopenharmony_ci int size, flags, size_mul, pts_delta, i, reserved_count, ret; 1012cabdff1aSopenharmony_ci uint64_t tmp; 1013cabdff1aSopenharmony_ci 1014cabdff1aSopenharmony_ci if (!(nut->flags & NUT_PIPE) && 1015cabdff1aSopenharmony_ci avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) { 1016cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 1017cabdff1aSopenharmony_ci "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n", 1018cabdff1aSopenharmony_ci avio_tell(bc), nut->last_syncpoint_pos, nut->max_distance); 1019cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1020cabdff1aSopenharmony_ci } 1021cabdff1aSopenharmony_ci 1022cabdff1aSopenharmony_ci flags = nut->frame_code[frame_code].flags; 1023cabdff1aSopenharmony_ci size_mul = nut->frame_code[frame_code].size_mul; 1024cabdff1aSopenharmony_ci size = nut->frame_code[frame_code].size_lsb; 1025cabdff1aSopenharmony_ci *stream_id = nut->frame_code[frame_code].stream_id; 1026cabdff1aSopenharmony_ci pts_delta = nut->frame_code[frame_code].pts_delta; 1027cabdff1aSopenharmony_ci reserved_count = nut->frame_code[frame_code].reserved_count; 1028cabdff1aSopenharmony_ci *header_idx = nut->frame_code[frame_code].header_idx; 1029cabdff1aSopenharmony_ci 1030cabdff1aSopenharmony_ci if (flags & FLAG_INVALID) 1031cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1032cabdff1aSopenharmony_ci if (flags & FLAG_CODED) 1033cabdff1aSopenharmony_ci flags ^= ffio_read_varlen(bc); 1034cabdff1aSopenharmony_ci if (flags & FLAG_STREAM_ID) { 1035cabdff1aSopenharmony_ci GET_V(*stream_id, tmp < s->nb_streams); 1036cabdff1aSopenharmony_ci } 1037cabdff1aSopenharmony_ci stc = &nut->stream[*stream_id]; 1038cabdff1aSopenharmony_ci if (flags & FLAG_CODED_PTS) { 1039cabdff1aSopenharmony_ci int64_t coded_pts = ffio_read_varlen(bc); 1040cabdff1aSopenharmony_ci // FIXME check last_pts validity? 1041cabdff1aSopenharmony_ci if (coded_pts < (1LL << stc->msb_pts_shift)) { 1042cabdff1aSopenharmony_ci *pts = ff_lsb2full(stc, coded_pts); 1043cabdff1aSopenharmony_ci } else 1044cabdff1aSopenharmony_ci *pts = coded_pts - (1LL << stc->msb_pts_shift); 1045cabdff1aSopenharmony_ci } else 1046cabdff1aSopenharmony_ci *pts = stc->last_pts + pts_delta; 1047cabdff1aSopenharmony_ci if (flags & FLAG_SIZE_MSB) 1048cabdff1aSopenharmony_ci size += size_mul * ffio_read_varlen(bc); 1049cabdff1aSopenharmony_ci if (flags & FLAG_MATCH_TIME) 1050cabdff1aSopenharmony_ci get_s(bc); 1051cabdff1aSopenharmony_ci if (flags & FLAG_HEADER_IDX) 1052cabdff1aSopenharmony_ci *header_idx = ffio_read_varlen(bc); 1053cabdff1aSopenharmony_ci if (flags & FLAG_RESERVED) 1054cabdff1aSopenharmony_ci reserved_count = ffio_read_varlen(bc); 1055cabdff1aSopenharmony_ci for (i = 0; i < reserved_count; i++) { 1056cabdff1aSopenharmony_ci if (bc->eof_reached) { 1057cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "reached EOF while decoding frame header\n"); 1058cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1059cabdff1aSopenharmony_ci } 1060cabdff1aSopenharmony_ci ffio_read_varlen(bc); 1061cabdff1aSopenharmony_ci } 1062cabdff1aSopenharmony_ci 1063cabdff1aSopenharmony_ci if (*header_idx >= (unsigned)nut->header_count) { 1064cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "header_idx invalid\n"); 1065cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1066cabdff1aSopenharmony_ci } 1067cabdff1aSopenharmony_ci if (size > 4096) 1068cabdff1aSopenharmony_ci *header_idx = 0; 1069cabdff1aSopenharmony_ci size -= nut->header_len[*header_idx]; 1070cabdff1aSopenharmony_ci 1071cabdff1aSopenharmony_ci if (flags & FLAG_CHECKSUM) { 1072cabdff1aSopenharmony_ci avio_rb32(bc); // FIXME check this 1073cabdff1aSopenharmony_ci } else if (!(nut->flags & NUT_PIPE) && 1074cabdff1aSopenharmony_ci size > 2 * nut->max_distance || 1075cabdff1aSopenharmony_ci FFABS(stc->last_pts - *pts) > stc->max_pts_distance) { 1076cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n"); 1077cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1078cabdff1aSopenharmony_ci } 1079cabdff1aSopenharmony_ci 1080cabdff1aSopenharmony_ci stc->last_pts = *pts; 1081cabdff1aSopenharmony_ci stc->last_flags = flags; 1082cabdff1aSopenharmony_ci 1083cabdff1aSopenharmony_ci return size; 1084cabdff1aSopenharmony_cifail: 1085cabdff1aSopenharmony_ci return ret; 1086cabdff1aSopenharmony_ci} 1087cabdff1aSopenharmony_ci 1088cabdff1aSopenharmony_cistatic int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code) 1089cabdff1aSopenharmony_ci{ 1090cabdff1aSopenharmony_ci AVFormatContext *s = nut->avf; 1091cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 1092cabdff1aSopenharmony_ci int size, stream_id, discard, ret; 1093cabdff1aSopenharmony_ci int64_t pts, last_IP_pts; 1094cabdff1aSopenharmony_ci StreamContext *stc; 1095cabdff1aSopenharmony_ci uint8_t header_idx; 1096cabdff1aSopenharmony_ci 1097cabdff1aSopenharmony_ci size = decode_frame_header(nut, &pts, &stream_id, &header_idx, frame_code); 1098cabdff1aSopenharmony_ci if (size < 0) 1099cabdff1aSopenharmony_ci return size; 1100cabdff1aSopenharmony_ci 1101cabdff1aSopenharmony_ci stc = &nut->stream[stream_id]; 1102cabdff1aSopenharmony_ci 1103cabdff1aSopenharmony_ci if (stc->last_flags & FLAG_KEY) 1104cabdff1aSopenharmony_ci stc->skip_until_key_frame = 0; 1105cabdff1aSopenharmony_ci 1106cabdff1aSopenharmony_ci discard = s->streams[stream_id]->discard; 1107cabdff1aSopenharmony_ci last_IP_pts = ffstream(s->streams[stream_id])->last_IP_pts; 1108cabdff1aSopenharmony_ci if ((discard >= AVDISCARD_NONKEY && !(stc->last_flags & FLAG_KEY)) || 1109cabdff1aSopenharmony_ci (discard >= AVDISCARD_BIDIR && last_IP_pts != AV_NOPTS_VALUE && 1110cabdff1aSopenharmony_ci last_IP_pts > pts) || 1111cabdff1aSopenharmony_ci discard >= AVDISCARD_ALL || 1112cabdff1aSopenharmony_ci stc->skip_until_key_frame) { 1113cabdff1aSopenharmony_ci avio_skip(bc, size); 1114cabdff1aSopenharmony_ci return 1; 1115cabdff1aSopenharmony_ci } 1116cabdff1aSopenharmony_ci 1117cabdff1aSopenharmony_ci ret = av_new_packet(pkt, size + nut->header_len[header_idx]); 1118cabdff1aSopenharmony_ci if (ret < 0) 1119cabdff1aSopenharmony_ci return ret; 1120cabdff1aSopenharmony_ci if (nut->header[header_idx]) 1121cabdff1aSopenharmony_ci memcpy(pkt->data, nut->header[header_idx], nut->header_len[header_idx]); 1122cabdff1aSopenharmony_ci pkt->pos = avio_tell(bc); // FIXME 1123cabdff1aSopenharmony_ci if (stc->last_flags & FLAG_SM_DATA) { 1124cabdff1aSopenharmony_ci int sm_size; 1125cabdff1aSopenharmony_ci if (read_sm_data(s, bc, pkt, 0, pkt->pos + size) < 0) { 1126cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 1127cabdff1aSopenharmony_ci goto fail; 1128cabdff1aSopenharmony_ci } 1129cabdff1aSopenharmony_ci if (read_sm_data(s, bc, pkt, 1, pkt->pos + size) < 0) { 1130cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 1131cabdff1aSopenharmony_ci goto fail; 1132cabdff1aSopenharmony_ci } 1133cabdff1aSopenharmony_ci sm_size = avio_tell(bc) - pkt->pos; 1134cabdff1aSopenharmony_ci size -= sm_size; 1135cabdff1aSopenharmony_ci pkt->size -= sm_size; 1136cabdff1aSopenharmony_ci } 1137cabdff1aSopenharmony_ci 1138cabdff1aSopenharmony_ci ret = avio_read(bc, pkt->data + nut->header_len[header_idx], size); 1139cabdff1aSopenharmony_ci if (ret != size) { 1140cabdff1aSopenharmony_ci if (ret < 0) 1141cabdff1aSopenharmony_ci goto fail; 1142cabdff1aSopenharmony_ci } 1143cabdff1aSopenharmony_ci av_shrink_packet(pkt, nut->header_len[header_idx] + ret); 1144cabdff1aSopenharmony_ci 1145cabdff1aSopenharmony_ci pkt->stream_index = stream_id; 1146cabdff1aSopenharmony_ci if (stc->last_flags & FLAG_KEY) 1147cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 1148cabdff1aSopenharmony_ci pkt->pts = pts; 1149cabdff1aSopenharmony_ci 1150cabdff1aSopenharmony_ci return 0; 1151cabdff1aSopenharmony_cifail: 1152cabdff1aSopenharmony_ci av_packet_unref(pkt); 1153cabdff1aSopenharmony_ci return ret; 1154cabdff1aSopenharmony_ci} 1155cabdff1aSopenharmony_ci 1156cabdff1aSopenharmony_cistatic int nut_read_packet(AVFormatContext *s, AVPacket *pkt) 1157cabdff1aSopenharmony_ci{ 1158cabdff1aSopenharmony_ci NUTContext *nut = s->priv_data; 1159cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 1160cabdff1aSopenharmony_ci int i, frame_code = 0, ret, skip; 1161cabdff1aSopenharmony_ci int64_t ts, back_ptr; 1162cabdff1aSopenharmony_ci 1163cabdff1aSopenharmony_ci for (;;) { 1164cabdff1aSopenharmony_ci int64_t pos = avio_tell(bc); 1165cabdff1aSopenharmony_ci uint64_t tmp = nut->next_startcode; 1166cabdff1aSopenharmony_ci nut->next_startcode = 0; 1167cabdff1aSopenharmony_ci 1168cabdff1aSopenharmony_ci if (tmp) { 1169cabdff1aSopenharmony_ci pos -= 8; 1170cabdff1aSopenharmony_ci } else { 1171cabdff1aSopenharmony_ci frame_code = avio_r8(bc); 1172cabdff1aSopenharmony_ci if (avio_feof(bc)) 1173cabdff1aSopenharmony_ci return AVERROR_EOF; 1174cabdff1aSopenharmony_ci if (frame_code == 'N') { 1175cabdff1aSopenharmony_ci tmp = frame_code; 1176cabdff1aSopenharmony_ci for (i = 1; i < 8; i++) 1177cabdff1aSopenharmony_ci tmp = (tmp << 8) + avio_r8(bc); 1178cabdff1aSopenharmony_ci } 1179cabdff1aSopenharmony_ci } 1180cabdff1aSopenharmony_ci switch (tmp) { 1181cabdff1aSopenharmony_ci case MAIN_STARTCODE: 1182cabdff1aSopenharmony_ci case STREAM_STARTCODE: 1183cabdff1aSopenharmony_ci case INDEX_STARTCODE: 1184cabdff1aSopenharmony_ci skip = get_packetheader(nut, bc, 0, tmp); 1185cabdff1aSopenharmony_ci avio_skip(bc, skip); 1186cabdff1aSopenharmony_ci break; 1187cabdff1aSopenharmony_ci case INFO_STARTCODE: 1188cabdff1aSopenharmony_ci if (decode_info_header(nut) < 0) 1189cabdff1aSopenharmony_ci goto resync; 1190cabdff1aSopenharmony_ci break; 1191cabdff1aSopenharmony_ci case SYNCPOINT_STARTCODE: 1192cabdff1aSopenharmony_ci if (decode_syncpoint(nut, &ts, &back_ptr) < 0) 1193cabdff1aSopenharmony_ci goto resync; 1194cabdff1aSopenharmony_ci frame_code = avio_r8(bc); 1195cabdff1aSopenharmony_ci case 0: 1196cabdff1aSopenharmony_ci ret = decode_frame(nut, pkt, frame_code); 1197cabdff1aSopenharmony_ci if (ret == 0) 1198cabdff1aSopenharmony_ci return 0; 1199cabdff1aSopenharmony_ci else if (ret == 1) // OK but discard packet 1200cabdff1aSopenharmony_ci break; 1201cabdff1aSopenharmony_ci default: 1202cabdff1aSopenharmony_ciresync: 1203cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "syncing from %"PRId64"\n", pos); 1204cabdff1aSopenharmony_ci tmp = find_any_startcode(bc, FFMAX(nut->last_syncpoint_pos, nut->last_resync_pos) + 1); 1205cabdff1aSopenharmony_ci nut->last_resync_pos = avio_tell(bc); 1206cabdff1aSopenharmony_ci if (tmp == 0) 1207cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1208cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "sync\n"); 1209cabdff1aSopenharmony_ci nut->next_startcode = tmp; 1210cabdff1aSopenharmony_ci } 1211cabdff1aSopenharmony_ci } 1212cabdff1aSopenharmony_ci} 1213cabdff1aSopenharmony_ci 1214cabdff1aSopenharmony_cistatic int64_t nut_read_timestamp(AVFormatContext *s, int stream_index, 1215cabdff1aSopenharmony_ci int64_t *pos_arg, int64_t pos_limit) 1216cabdff1aSopenharmony_ci{ 1217cabdff1aSopenharmony_ci NUTContext *nut = s->priv_data; 1218cabdff1aSopenharmony_ci AVIOContext *bc = s->pb; 1219cabdff1aSopenharmony_ci int64_t pos, pts, back_ptr; 1220cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "read_timestamp(X,%d,%"PRId64",%"PRId64")\n", 1221cabdff1aSopenharmony_ci stream_index, *pos_arg, pos_limit); 1222cabdff1aSopenharmony_ci 1223cabdff1aSopenharmony_ci pos = *pos_arg; 1224cabdff1aSopenharmony_ci do { 1225cabdff1aSopenharmony_ci pos = find_startcode(bc, SYNCPOINT_STARTCODE, pos) + 1; 1226cabdff1aSopenharmony_ci if (pos < 1) { 1227cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "read_timestamp failed.\n"); 1228cabdff1aSopenharmony_ci return AV_NOPTS_VALUE; 1229cabdff1aSopenharmony_ci } 1230cabdff1aSopenharmony_ci } while (decode_syncpoint(nut, &pts, &back_ptr) < 0); 1231cabdff1aSopenharmony_ci *pos_arg = pos - 1; 1232cabdff1aSopenharmony_ci av_assert0(nut->last_syncpoint_pos == *pos_arg); 1233cabdff1aSopenharmony_ci 1234cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "return %"PRId64" %"PRId64"\n", pts, back_ptr); 1235cabdff1aSopenharmony_ci if (stream_index == -2) 1236cabdff1aSopenharmony_ci return back_ptr; 1237cabdff1aSopenharmony_ci av_assert0(stream_index == -1); 1238cabdff1aSopenharmony_ci return pts; 1239cabdff1aSopenharmony_ci} 1240cabdff1aSopenharmony_ci 1241cabdff1aSopenharmony_cistatic int read_seek(AVFormatContext *s, int stream_index, 1242cabdff1aSopenharmony_ci int64_t pts, int flags) 1243cabdff1aSopenharmony_ci{ 1244cabdff1aSopenharmony_ci NUTContext *nut = s->priv_data; 1245cabdff1aSopenharmony_ci AVStream *st = s->streams[stream_index]; 1246cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 1247cabdff1aSopenharmony_ci Syncpoint dummy = { .ts = pts * av_q2d(st->time_base) * AV_TIME_BASE }; 1248cabdff1aSopenharmony_ci Syncpoint nopts_sp = { .ts = AV_NOPTS_VALUE, .back_ptr = AV_NOPTS_VALUE }; 1249cabdff1aSopenharmony_ci Syncpoint *sp, *next_node[2] = { &nopts_sp, &nopts_sp }; 1250cabdff1aSopenharmony_ci int64_t pos, pos2, ts; 1251cabdff1aSopenharmony_ci int i; 1252cabdff1aSopenharmony_ci 1253cabdff1aSopenharmony_ci if (nut->flags & NUT_PIPE) { 1254cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 1255cabdff1aSopenharmony_ci } 1256cabdff1aSopenharmony_ci 1257cabdff1aSopenharmony_ci if (sti->index_entries) { 1258cabdff1aSopenharmony_ci int index = av_index_search_timestamp(st, pts, flags); 1259cabdff1aSopenharmony_ci if (index < 0) 1260cabdff1aSopenharmony_ci index = av_index_search_timestamp(st, pts, flags ^ AVSEEK_FLAG_BACKWARD); 1261cabdff1aSopenharmony_ci if (index < 0) 1262cabdff1aSopenharmony_ci return -1; 1263cabdff1aSopenharmony_ci 1264cabdff1aSopenharmony_ci pos2 = sti->index_entries[index].pos; 1265cabdff1aSopenharmony_ci ts = sti->index_entries[index].timestamp; 1266cabdff1aSopenharmony_ci } else { 1267cabdff1aSopenharmony_ci av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pts_cmp, 1268cabdff1aSopenharmony_ci (void **) next_node); 1269cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%"PRIu64"-%"PRIu64" %"PRId64"-%"PRId64"\n", 1270cabdff1aSopenharmony_ci next_node[0]->pos, next_node[1]->pos, next_node[0]->ts, 1271cabdff1aSopenharmony_ci next_node[1]->ts); 1272cabdff1aSopenharmony_ci pos = ff_gen_search(s, -1, dummy.ts, next_node[0]->pos, 1273cabdff1aSopenharmony_ci next_node[1]->pos, next_node[1]->pos, 1274cabdff1aSopenharmony_ci next_node[0]->ts, next_node[1]->ts, 1275cabdff1aSopenharmony_ci AVSEEK_FLAG_BACKWARD, &ts, nut_read_timestamp); 1276cabdff1aSopenharmony_ci if (pos < 0) 1277cabdff1aSopenharmony_ci return pos; 1278cabdff1aSopenharmony_ci 1279cabdff1aSopenharmony_ci if (!(flags & AVSEEK_FLAG_BACKWARD)) { 1280cabdff1aSopenharmony_ci dummy.pos = pos + 16; 1281cabdff1aSopenharmony_ci next_node[1] = &nopts_sp; 1282cabdff1aSopenharmony_ci av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, 1283cabdff1aSopenharmony_ci (void **) next_node); 1284cabdff1aSopenharmony_ci pos2 = ff_gen_search(s, -2, dummy.pos, next_node[0]->pos, 1285cabdff1aSopenharmony_ci next_node[1]->pos, next_node[1]->pos, 1286cabdff1aSopenharmony_ci next_node[0]->back_ptr, next_node[1]->back_ptr, 1287cabdff1aSopenharmony_ci flags, &ts, nut_read_timestamp); 1288cabdff1aSopenharmony_ci if (pos2 >= 0) 1289cabdff1aSopenharmony_ci pos = pos2; 1290cabdff1aSopenharmony_ci // FIXME dir but I think it does not matter 1291cabdff1aSopenharmony_ci } 1292cabdff1aSopenharmony_ci dummy.pos = pos; 1293cabdff1aSopenharmony_ci sp = av_tree_find(nut->syncpoints, &dummy, ff_nut_sp_pos_cmp, 1294cabdff1aSopenharmony_ci NULL); 1295cabdff1aSopenharmony_ci 1296cabdff1aSopenharmony_ci av_assert0(sp); 1297cabdff1aSopenharmony_ci pos2 = sp->back_ptr - 15; 1298cabdff1aSopenharmony_ci } 1299cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos2); 1300cabdff1aSopenharmony_ci pos = find_startcode(s->pb, SYNCPOINT_STARTCODE, pos2); 1301cabdff1aSopenharmony_ci avio_seek(s->pb, pos, SEEK_SET); 1302cabdff1aSopenharmony_ci nut->last_syncpoint_pos = pos; 1303cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "SP: %"PRId64"\n", pos); 1304cabdff1aSopenharmony_ci if (pos2 > pos || pos2 + 15 < pos) 1305cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "no syncpoint at backptr pos\n"); 1306cabdff1aSopenharmony_ci for (i = 0; i < s->nb_streams; i++) 1307cabdff1aSopenharmony_ci nut->stream[i].skip_until_key_frame = 1; 1308cabdff1aSopenharmony_ci 1309cabdff1aSopenharmony_ci nut->last_resync_pos = 0; 1310cabdff1aSopenharmony_ci 1311cabdff1aSopenharmony_ci return 0; 1312cabdff1aSopenharmony_ci} 1313cabdff1aSopenharmony_ci 1314cabdff1aSopenharmony_ciconst AVInputFormat ff_nut_demuxer = { 1315cabdff1aSopenharmony_ci .name = "nut", 1316cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("NUT"), 1317cabdff1aSopenharmony_ci .flags = AVFMT_SEEK_TO_PTS, 1318cabdff1aSopenharmony_ci .priv_data_size = sizeof(NUTContext), 1319cabdff1aSopenharmony_ci .flags_internal = FF_FMT_INIT_CLEANUP, 1320cabdff1aSopenharmony_ci .read_probe = nut_probe, 1321cabdff1aSopenharmony_ci .read_header = nut_read_header, 1322cabdff1aSopenharmony_ci .read_packet = nut_read_packet, 1323cabdff1aSopenharmony_ci .read_close = nut_read_close, 1324cabdff1aSopenharmony_ci .read_seek = read_seek, 1325cabdff1aSopenharmony_ci .extensions = "nut", 1326cabdff1aSopenharmony_ci .codec_tag = ff_nut_codec_tags, 1327cabdff1aSopenharmony_ci}; 1328