| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * MPEG-2 transport stream (aka DVB) demuxer | ||
| 3 | * Copyright (c) 2002-2003 Fabrice Bellard | ||
| 4 | * | ||
| 5 | * This file is part of FFmpeg. | ||
| 6 | * | ||
| 7 | * FFmpeg is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with FFmpeg; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "config_components.h" | ||
| 23 | |||
| 24 | #include "libavutil/attributes_internal.h" | ||
| 25 | #include "libavutil/buffer.h" | ||
| 26 | #include "libavutil/crc.h" | ||
| 27 | #include "libavutil/internal.h" | ||
| 28 | #include "libavutil/intreadwrite.h" | ||
| 29 | #include "libavutil/log.h" | ||
| 30 | #include "libavutil/dict.h" | ||
| 31 | #include "libavutil/mem.h" | ||
| 32 | #include "libavutil/opt.h" | ||
| 33 | #include "libavutil/avassert.h" | ||
| 34 | #include "libavutil/dovi_meta.h" | ||
| 35 | #include "libavcodec/bytestream.h" | ||
| 36 | #include "libavcodec/defs.h" | ||
| 37 | #include "libavcodec/get_bits.h" | ||
| 38 | #include "libavcodec/opus/opus.h" | ||
| 39 | #include "avformat.h" | ||
| 40 | #include "mpegts.h" | ||
| 41 | #include "internal.h" | ||
| 42 | #include "avio_internal.h" | ||
| 43 | #include "demux.h" | ||
| 44 | #include "mpeg.h" | ||
| 45 | #include "isom.h" | ||
| 46 | #if CONFIG_ICONV | ||
| 47 | #include <iconv.h> | ||
| 48 | #endif | ||
| 49 | |||
| 50 | /* maximum size in which we look for synchronization if | ||
| 51 | * synchronization is lost */ | ||
| 52 | #define MAX_RESYNC_SIZE 65536 | ||
| 53 | |||
| 54 | #define MAX_MP4_DESCR_COUNT 16 | ||
| 55 | |||
| 56 | #define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend) \ | ||
| 57 | do { \ | ||
| 58 | if ((prev_dividend) == 0 || (dividend) - (prev_dividend) != (divisor)) \ | ||
| 59 | (modulus) = (dividend) % (divisor); \ | ||
| 60 | (prev_dividend) = (dividend); \ | ||
| 61 | } while (0) | ||
| 62 | |||
| 63 | #define PROBE_PACKET_MAX_BUF 8192 | ||
| 64 | #define PROBE_PACKET_MARGIN 5 | ||
| 65 | |||
| 66 | enum MpegTSFilterType { | ||
| 67 | MPEGTS_PES, | ||
| 68 | MPEGTS_SECTION, | ||
| 69 | MPEGTS_PCR, | ||
| 70 | }; | ||
| 71 | |||
| 72 | typedef struct MpegTSFilter MpegTSFilter; | ||
| 73 | |||
| 74 | typedef int PESCallback (MpegTSFilter *f, const uint8_t *buf, int len, | ||
| 75 | int is_start, int64_t pos); | ||
| 76 | |||
| 77 | typedef struct MpegTSPESFilter { | ||
| 78 | PESCallback *pes_cb; | ||
| 79 | void *opaque; | ||
| 80 | } MpegTSPESFilter; | ||
| 81 | |||
| 82 | typedef void SectionCallback (MpegTSFilter *f, const uint8_t *buf, int len); | ||
| 83 | |||
| 84 | typedef void SetServiceCallback (void *opaque, int ret); | ||
| 85 | |||
| 86 | typedef struct MpegTSSectionFilter { | ||
| 87 | int section_index; | ||
| 88 | int section_h_size; | ||
| 89 | int last_ver; | ||
| 90 | unsigned crc; | ||
| 91 | unsigned last_crc; | ||
| 92 | uint8_t *section_buf; | ||
| 93 | unsigned int check_crc : 1; | ||
| 94 | unsigned int end_of_section_reached : 1; | ||
| 95 | SectionCallback *section_cb; | ||
| 96 | void *opaque; | ||
| 97 | } MpegTSSectionFilter; | ||
| 98 | |||
| 99 | struct MpegTSFilter { | ||
| 100 | int pid; | ||
| 101 | int es_id; | ||
| 102 | int last_cc; /* last cc code (-1 if first packet) */ | ||
| 103 | int64_t last_pcr; | ||
| 104 | int discard; | ||
| 105 | enum MpegTSFilterType type; | ||
| 106 | union { | ||
| 107 | MpegTSPESFilter pes_filter; | ||
| 108 | MpegTSSectionFilter section_filter; | ||
| 109 | } u; | ||
| 110 | }; | ||
| 111 | |||
| 112 | struct Stream { | ||
| 113 | int idx; | ||
| 114 | int stream_identifier; | ||
| 115 | }; | ||
| 116 | |||
| 117 | #define MAX_STREAMS_PER_PROGRAM 128 | ||
| 118 | #define MAX_PIDS_PER_PROGRAM (MAX_STREAMS_PER_PROGRAM + 2) | ||
| 119 | |||
| 120 | struct StreamGroup { | ||
| 121 | enum AVStreamGroupParamsType type; | ||
| 122 | int id; | ||
| 123 | unsigned int nb_streams; | ||
| 124 | AVStream *streams[MAX_STREAMS_PER_PROGRAM]; | ||
| 125 | }; | ||
| 126 | |||
| 127 | struct Program { | ||
| 128 | unsigned int id; // program id/service id | ||
| 129 | unsigned int nb_pids; | ||
| 130 | unsigned int pids[MAX_PIDS_PER_PROGRAM]; | ||
| 131 | unsigned int nb_streams; | ||
| 132 | struct Stream streams[MAX_STREAMS_PER_PROGRAM]; | ||
| 133 | unsigned int nb_stream_groups; | ||
| 134 | struct StreamGroup stream_groups[MAX_STREAMS_PER_PROGRAM]; | ||
| 135 | |||
| 136 | /** have we found pmt for this program */ | ||
| 137 | int pmt_found; | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct MpegTSContext { | ||
| 141 | const AVClass *class; | ||
| 142 | /* user data */ | ||
| 143 | AVFormatContext *stream; | ||
| 144 | /** raw packet size, including FEC if present */ | ||
| 145 | int raw_packet_size; | ||
| 146 | |||
| 147 | int64_t pos47_full; | ||
| 148 | |||
| 149 | /** if true, all pids are analyzed to find streams */ | ||
| 150 | int auto_guess; | ||
| 151 | |||
| 152 | /** compute exact PCR for each transport stream packet */ | ||
| 153 | int mpeg2ts_compute_pcr; | ||
| 154 | |||
| 155 | /** fix dvb teletext pts */ | ||
| 156 | int fix_teletext_pts; | ||
| 157 | |||
| 158 | int64_t cur_pcr; /**< used to estimate the exact PCR */ | ||
| 159 | int64_t pcr_incr; /**< used to estimate the exact PCR */ | ||
| 160 | |||
| 161 | /* data needed to handle file based ts */ | ||
| 162 | /** stop parsing loop */ | ||
| 163 | int stop_parse; | ||
| 164 | /** packet containing Audio/Video data */ | ||
| 165 | AVPacket *pkt; | ||
| 166 | /** to detect seek */ | ||
| 167 | int64_t last_pos; | ||
| 168 | |||
| 169 | int skip_changes; | ||
| 170 | int skip_clear; | ||
| 171 | int skip_unknown_pmt; | ||
| 172 | |||
| 173 | int scan_all_pmts; | ||
| 174 | |||
| 175 | int resync_size; | ||
| 176 | int merge_pmt_versions; | ||
| 177 | int max_packet_size; | ||
| 178 | |||
| 179 | int id; | ||
| 180 | |||
| 181 | /******************************************/ | ||
| 182 | /* private mpegts data */ | ||
| 183 | /* scan context */ | ||
| 184 | /** structure to keep track of Program->pids mapping */ | ||
| 185 | unsigned int nb_prg; | ||
| 186 | struct Program *prg; | ||
| 187 | |||
| 188 | int8_t crc_validity[NB_PID_MAX]; | ||
| 189 | /** filters for various streams specified by PMT + for the PAT and PMT */ | ||
| 190 | MpegTSFilter *pids[NB_PID_MAX]; | ||
| 191 | int current_pid; | ||
| 192 | |||
| 193 | AVStream *epg_stream; | ||
| 194 | AVBufferPool* pools[32]; | ||
| 195 | }; | ||
| 196 | |||
| 197 | #define MPEGTS_OPTIONS \ | ||
| 198 | { "resync_size", "set size limit for looking up a new synchronization", \ | ||
| 199 | offsetof(MpegTSContext, resync_size), AV_OPT_TYPE_INT, \ | ||
| 200 | { .i64 = MAX_RESYNC_SIZE}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, \ | ||
| 201 | { "ts_id", "transport stream id", \ | ||
| 202 | offsetof(MpegTSContext, id), AV_OPT_TYPE_INT, \ | ||
| 203 | { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, \ | ||
| 204 | { "ts_packetsize", "output option carrying the raw packet size", \ | ||
| 205 | offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT, \ | ||
| 206 | { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY } | ||
| 207 | |||
| 208 | static const AVOption options[] = { | ||
| 209 | MPEGTS_OPTIONS, | ||
| 210 | {"fix_teletext_pts", "try to fix pts values of dvb teletext streams", offsetof(MpegTSContext, fix_teletext_pts), AV_OPT_TYPE_BOOL, | ||
| 211 | {.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 212 | {"scan_all_pmts", "scan and combine all PMTs", offsetof(MpegTSContext, scan_all_pmts), AV_OPT_TYPE_BOOL, | ||
| 213 | {.i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 214 | {"skip_unknown_pmt", "skip PMTs for programs not advertised in the PAT", offsetof(MpegTSContext, skip_unknown_pmt), AV_OPT_TYPE_BOOL, | ||
| 215 | {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 216 | {"merge_pmt_versions", "reuse streams when PMT's version/pids change", offsetof(MpegTSContext, merge_pmt_versions), AV_OPT_TYPE_BOOL, | ||
| 217 | {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 218 | {"skip_changes", "skip changing / adding streams / programs", offsetof(MpegTSContext, skip_changes), AV_OPT_TYPE_BOOL, | ||
| 219 | {.i64 = 0}, 0, 1, 0 }, | ||
| 220 | {"skip_clear", "skip clearing programs", offsetof(MpegTSContext, skip_clear), AV_OPT_TYPE_BOOL, | ||
| 221 | {.i64 = 0}, 0, 1, 0 }, | ||
| 222 | {"max_packet_size", "maximum size of emitted packet", offsetof(MpegTSContext, max_packet_size), AV_OPT_TYPE_INT, | ||
| 223 | {.i64 = 204800}, 1, INT_MAX/2, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 224 | { NULL }, | ||
| 225 | }; | ||
| 226 | |||
| 227 | static const AVClass mpegts_class = { | ||
| 228 | .class_name = "mpegts demuxer", | ||
| 229 | .item_name = av_default_item_name, | ||
| 230 | .option = options, | ||
| 231 | .version = LIBAVUTIL_VERSION_INT, | ||
| 232 | }; | ||
| 233 | |||
| 234 | static const AVOption raw_options[] = { | ||
| 235 | MPEGTS_OPTIONS, | ||
| 236 | { "compute_pcr", "compute exact PCR for each transport stream packet", | ||
| 237 | offsetof(MpegTSContext, mpeg2ts_compute_pcr), AV_OPT_TYPE_BOOL, | ||
| 238 | { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, | ||
| 239 | { NULL }, | ||
| 240 | }; | ||
| 241 | |||
| 242 | static const AVClass mpegtsraw_class = { | ||
| 243 | .class_name = "mpegtsraw demuxer", | ||
| 244 | .item_name = av_default_item_name, | ||
| 245 | .option = raw_options, | ||
| 246 | .version = LIBAVUTIL_VERSION_INT, | ||
| 247 | }; | ||
| 248 | |||
| 249 | /* TS stream handling */ | ||
| 250 | |||
| 251 | enum MpegTSState { | ||
| 252 | MPEGTS_HEADER = 0, | ||
| 253 | MPEGTS_PESHEADER, | ||
| 254 | MPEGTS_PESHEADER_FILL, | ||
| 255 | MPEGTS_PAYLOAD, | ||
| 256 | MPEGTS_SKIP, | ||
| 257 | }; | ||
| 258 | |||
| 259 | /* enough for PES header + length */ | ||
| 260 | #define PES_START_SIZE 6 | ||
| 261 | #define PES_HEADER_SIZE 9 | ||
| 262 | #define MAX_PES_HEADER_SIZE (9 + 255) | ||
| 263 | |||
| 264 | typedef struct PESContext { | ||
| 265 | int pid; | ||
| 266 | int pcr_pid; /**< if -1 then all packets containing PCR are considered */ | ||
| 267 | int stream_type; | ||
| 268 | MpegTSContext *ts; | ||
| 269 | AVFormatContext *stream; | ||
| 270 | AVStream *st; | ||
| 271 | AVStream *sub_st; /**< stream for the embedded AC3 stream in HDMV TrueHD */ | ||
| 272 | enum MpegTSState state; | ||
| 273 | /* used to get the format */ | ||
| 274 | int data_index; | ||
| 275 | int flags; /**< copied to the AVPacket flags */ | ||
| 276 | int PES_packet_length; | ||
| 277 | int pes_header_size; | ||
| 278 | int extended_stream_id; | ||
| 279 | uint8_t stream_id; | ||
| 280 | int64_t pts, dts; | ||
| 281 | int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */ | ||
| 282 | uint8_t header[MAX_PES_HEADER_SIZE]; | ||
| 283 | AVBufferRef *buffer; | ||
| 284 | SLConfigDescr sl; | ||
| 285 | int merged_st; | ||
| 286 | } PESContext; | ||
| 287 | |||
| 288 | EXTERN const FFInputFormat ff_mpegts_demuxer; | ||
| 289 | |||
| 290 | 714 | static struct Program * get_program(MpegTSContext *ts, unsigned int programid) | |
| 291 | { | ||
| 292 | int i; | ||
| 293 |
2/2✓ Branch 0 taken 638 times.
✓ Branch 1 taken 76 times.
|
714 | for (i = 0; i < ts->nb_prg; i++) { |
| 294 |
1/2✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
|
638 | if (ts->prg[i].id == programid) { |
| 295 | 638 | return &ts->prg[i]; | |
| 296 | } | ||
| 297 | } | ||
| 298 | 76 | return NULL; | |
| 299 | } | ||
| 300 | |||
| 301 | 212 | static void clear_avprogram(MpegTSContext *ts, unsigned int programid) | |
| 302 | { | ||
| 303 | 212 | AVProgram *prg = NULL; | |
| 304 | int i; | ||
| 305 | |||
| 306 |
1/2✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
|
212 | for (i = 0; i < ts->stream->nb_programs; i++) |
| 307 |
1/2✓ Branch 0 taken 212 times.
✗ Branch 1 not taken.
|
212 | if (ts->stream->programs[i]->id == programid) { |
| 308 | 212 | prg = ts->stream->programs[i]; | |
| 309 | 212 | break; | |
| 310 | } | ||
| 311 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
|
212 | if (!prg) |
| 312 | ✗ | return; | |
| 313 | 212 | prg->nb_stream_indexes = 0; | |
| 314 | } | ||
| 315 | |||
| 316 | 427 | static void clear_program(struct Program *p) | |
| 317 | { | ||
| 318 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 427 times.
|
427 | if (!p) |
| 319 | ✗ | return; | |
| 320 | 427 | p->nb_pids = 0; | |
| 321 | 427 | p->nb_streams = 0; | |
| 322 | 427 | p->nb_stream_groups = 0; | |
| 323 | 427 | memset(p->stream_groups, 0, sizeof(p->stream_groups)); | |
| 324 | 427 | p->pmt_found = 0; | |
| 325 | } | ||
| 326 | |||
| 327 | 76 | static void clear_programs(MpegTSContext *ts) | |
| 328 | { | ||
| 329 | 76 | av_freep(&ts->prg); | |
| 330 | 76 | ts->nb_prg = 0; | |
| 331 | 76 | } | |
| 332 | |||
| 333 | 273 | static struct Program * add_program(MpegTSContext *ts, unsigned int programid) | |
| 334 | { | ||
| 335 | 273 | struct Program *p = get_program(ts, programid); | |
| 336 |
2/2✓ Branch 0 taken 197 times.
✓ Branch 1 taken 76 times.
|
273 | if (p) |
| 337 | 197 | return p; | |
| 338 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
|
76 | if (av_reallocp_array(&ts->prg, ts->nb_prg + 1, sizeof(*ts->prg)) < 0) { |
| 339 | ✗ | ts->nb_prg = 0; | |
| 340 | ✗ | return NULL; | |
| 341 | } | ||
| 342 | 76 | p = &ts->prg[ts->nb_prg]; | |
| 343 | 76 | p->id = programid; | |
| 344 | 76 | clear_program(p); | |
| 345 | 76 | ts->nb_prg++; | |
| 346 | 76 | return p; | |
| 347 | } | ||
| 348 | |||
| 349 | 1635 | static void add_pid_to_program(struct Program *p, unsigned int pid) | |
| 350 | { | ||
| 351 | int i; | ||
| 352 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1635 times.
|
1635 | if (!p) |
| 353 | ✗ | return; | |
| 354 | |||
| 355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1635 times.
|
1635 | if (p->nb_pids >= MAX_PIDS_PER_PROGRAM) |
| 356 | ✗ | return; | |
| 357 | |||
| 358 |
2/2✓ Branch 0 taken 2080 times.
✓ Branch 1 taken 1081 times.
|
3161 | for (i = 0; i < p->nb_pids; i++) |
| 359 |
2/2✓ Branch 0 taken 554 times.
✓ Branch 1 taken 1526 times.
|
2080 | if (p->pids[i] == pid) |
| 360 | 554 | return; | |
| 361 | |||
| 362 | 1081 | p->pids[p->nb_pids++] = pid; | |
| 363 | } | ||
| 364 | |||
| 365 | 351 | static void update_av_program_info(AVFormatContext *s, unsigned int programid, | |
| 366 | unsigned int pid, int version) | ||
| 367 | { | ||
| 368 | int i; | ||
| 369 |
1/2✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
|
351 | for (i = 0; i < s->nb_programs; i++) { |
| 370 | 351 | AVProgram *program = s->programs[i]; | |
| 371 |
1/2✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
|
351 | if (program->id == programid) { |
| 372 | 351 | int old_pcr_pid = program->pcr_pid, | |
| 373 | 351 | old_version = program->pmt_version; | |
| 374 | 351 | program->pcr_pid = pid; | |
| 375 | 351 | program->pmt_version = version; | |
| 376 | |||
| 377 |
4/4✓ Branch 0 taken 275 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 257 times.
|
351 | if (old_version != -1 && old_version != version) { |
| 378 | 18 | av_log(s, AV_LOG_VERBOSE, | |
| 379 | "detected PMT change (program=%d, version=%d/%d, pcr_pid=0x%x/0x%x)\n", | ||
| 380 | programid, old_version, version, old_pcr_pid, pid); | ||
| 381 | } | ||
| 382 | 351 | break; | |
| 383 | } | ||
| 384 | } | ||
| 385 | 351 | } | |
| 386 | |||
| 387 | /** | ||
| 388 | * @brief discard_pid() decides if the pid is to be discarded according | ||
| 389 | * to caller's programs selection | ||
| 390 | * @param ts : - TS context | ||
| 391 | * @param pid : - pid | ||
| 392 | * @return 1 if the pid is only comprised in programs that have .discard=AVDISCARD_ALL | ||
| 393 | * 0 otherwise | ||
| 394 | */ | ||
| 395 | 43024 | static int discard_pid(MpegTSContext *ts, unsigned int pid) | |
| 396 | { | ||
| 397 | int i, j, k; | ||
| 398 | 43024 | int used = 0, discarded = 0; | |
| 399 | struct Program *p; | ||
| 400 | |||
| 401 |
2/2✓ Branch 0 taken 3687 times.
✓ Branch 1 taken 39337 times.
|
43024 | if (pid == PAT_PID) |
| 402 | 3687 | return 0; | |
| 403 | |||
| 404 | /* If none of the programs have .discard=AVDISCARD_ALL then there's | ||
| 405 | * no way we have to discard this packet */ | ||
| 406 |
2/2✓ Branch 0 taken 39290 times.
✓ Branch 1 taken 39337 times.
|
78627 | for (k = 0; k < ts->stream->nb_programs; k++) |
| 407 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39290 times.
|
39290 | if (ts->stream->programs[k]->discard == AVDISCARD_ALL) |
| 408 | ✗ | break; | |
| 409 |
1/2✓ Branch 0 taken 39337 times.
✗ Branch 1 not taken.
|
39337 | if (k == ts->stream->nb_programs) |
| 410 | 39337 | return 0; | |
| 411 | |||
| 412 | ✗ | for (i = 0; i < ts->nb_prg; i++) { | |
| 413 | ✗ | p = &ts->prg[i]; | |
| 414 | ✗ | for (j = 0; j < p->nb_pids; j++) { | |
| 415 | ✗ | if (p->pids[j] != pid) | |
| 416 | ✗ | continue; | |
| 417 | // is program with id p->id set to be discarded? | ||
| 418 | ✗ | for (k = 0; k < ts->stream->nb_programs; k++) { | |
| 419 | ✗ | if (ts->stream->programs[k]->id == p->id) { | |
| 420 | ✗ | if (ts->stream->programs[k]->discard == AVDISCARD_ALL) | |
| 421 | ✗ | discarded++; | |
| 422 | else | ||
| 423 | ✗ | used++; | |
| 424 | } | ||
| 425 | } | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | ✗ | return !used && discarded; | |
| 430 | } | ||
| 431 | |||
| 432 | /** | ||
| 433 | * Assemble PES packets out of TS packets, and then call the "section_cb" | ||
| 434 | * function when they are complete. | ||
| 435 | */ | ||
| 436 | 7985 | static void write_section_data(MpegTSContext *ts, MpegTSFilter *tss1, | |
| 437 | const uint8_t *buf, int buf_size, int is_start) | ||
| 438 | { | ||
| 439 | 7985 | MpegTSSectionFilter *tss = &tss1->u.section_filter; | |
| 440 | 7985 | uint8_t *cur_section_buf = NULL; | |
| 441 | int len, offset; | ||
| 442 | |||
| 443 |
2/2✓ Branch 0 taken 7950 times.
✓ Branch 1 taken 35 times.
|
7985 | if (is_start) { |
| 444 | 7950 | memcpy(tss->section_buf, buf, buf_size); | |
| 445 | 7950 | tss->section_index = buf_size; | |
| 446 | 7950 | tss->section_h_size = -1; | |
| 447 | 7950 | tss->end_of_section_reached = 0; | |
| 448 | } else { | ||
| 449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | if (tss->end_of_section_reached) |
| 450 | ✗ | return; | |
| 451 | 35 | len = MAX_SECTION_SIZE - tss->section_index; | |
| 452 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35 | if (buf_size < len) |
| 453 | 35 | len = buf_size; | |
| 454 | 35 | memcpy(tss->section_buf + tss->section_index, buf, len); | |
| 455 | 35 | tss->section_index += len; | |
| 456 | } | ||
| 457 | |||
| 458 | 7985 | offset = 0; | |
| 459 | 7985 | cur_section_buf = tss->section_buf; | |
| 460 |
3/4✓ Branch 0 taken 15935 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8193 times.
✓ Branch 3 taken 7742 times.
|
15935 | while (cur_section_buf - tss->section_buf < MAX_SECTION_SIZE && cur_section_buf[0] != STUFFING_BYTE) { |
| 461 | /* compute section length if possible */ | ||
| 462 |
3/4✓ Branch 0 taken 8193 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7985 times.
✓ Branch 3 taken 208 times.
|
8193 | if (tss->section_h_size == -1 && tss->section_index - offset >= 3) { |
| 463 | 7985 | len = (AV_RB16(cur_section_buf + 1) & 0xfff) + 3; | |
| 464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7985 times.
|
7985 | if (len > MAX_SECTION_SIZE) |
| 465 | ✗ | return; | |
| 466 | 7985 | tss->section_h_size = len; | |
| 467 | } | ||
| 468 | |||
| 469 |
2/2✓ Branch 0 taken 7985 times.
✓ Branch 1 taken 208 times.
|
8193 | if (tss->section_h_size != -1 && |
| 470 |
2/2✓ Branch 0 taken 7950 times.
✓ Branch 1 taken 35 times.
|
7985 | tss->section_index >= offset + tss->section_h_size) { |
| 471 | 7950 | int crc_valid = 1; | |
| 472 | 7950 | tss->end_of_section_reached = 1; | |
| 473 | |||
| 474 |
1/2✓ Branch 0 taken 7950 times.
✗ Branch 1 not taken.
|
7950 | if (tss->check_crc) { |
| 475 | 7950 | crc_valid = !av_crc(av_crc_get_table(AV_CRC_32_IEEE), -1, cur_section_buf, tss->section_h_size); | |
| 476 |
1/2✓ Branch 0 taken 7950 times.
✗ Branch 1 not taken.
|
7950 | if (tss->section_h_size >= 4) |
| 477 | 7950 | tss->crc = AV_RB32(cur_section_buf + tss->section_h_size - 4); | |
| 478 | |||
| 479 |
1/2✓ Branch 0 taken 7950 times.
✗ Branch 1 not taken.
|
7950 | if (crc_valid) { |
| 480 | 7950 | ts->crc_validity[ tss1->pid ] = 100; | |
| 481 | ✗ | }else if (ts->crc_validity[ tss1->pid ] > -10) { | |
| 482 | ✗ | ts->crc_validity[ tss1->pid ]--; | |
| 483 | }else | ||
| 484 | ✗ | crc_valid = 2; | |
| 485 | } | ||
| 486 |
1/2✓ Branch 0 taken 7950 times.
✗ Branch 1 not taken.
|
7950 | if (crc_valid) { |
| 487 | 7950 | tss->section_cb(tss1, cur_section_buf, tss->section_h_size); | |
| 488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7950 times.
|
7950 | if (crc_valid != 1) |
| 489 | ✗ | tss->last_ver = -1; | |
| 490 | } | ||
| 491 | |||
| 492 | 7950 | cur_section_buf += tss->section_h_size; | |
| 493 | 7950 | offset += tss->section_h_size; | |
| 494 | 7950 | tss->section_h_size = -1; | |
| 495 | } else { | ||
| 496 | 243 | tss->section_h_size = -1; | |
| 497 | 243 | tss->end_of_section_reached = 0; | |
| 498 | 243 | break; | |
| 499 | } | ||
| 500 | } | ||
| 501 | } | ||
| 502 | |||
| 503 | 465 | static MpegTSFilter *mpegts_open_filter(MpegTSContext *ts, unsigned int pid, | |
| 504 | enum MpegTSFilterType type) | ||
| 505 | { | ||
| 506 | MpegTSFilter *filter; | ||
| 507 | |||
| 508 | 465 | av_log(ts->stream, AV_LOG_TRACE, "Filter: pid=0x%x type=%d\n", pid, type); | |
| 509 | |||
| 510 |
2/4✓ Branch 0 taken 465 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 465 times.
|
465 | if (pid >= NB_PID_MAX || ts->pids[pid]) |
| 511 | ✗ | return NULL; | |
| 512 | 465 | filter = av_mallocz(sizeof(MpegTSFilter)); | |
| 513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 465 times.
|
465 | if (!filter) |
| 514 | ✗ | return NULL; | |
| 515 | 465 | ts->pids[pid] = filter; | |
| 516 | |||
| 517 | 465 | filter->type = type; | |
| 518 | 465 | filter->pid = pid; | |
| 519 | 465 | filter->es_id = -1; | |
| 520 | 465 | filter->last_cc = -1; | |
| 521 | 465 | filter->last_pcr= -1; | |
| 522 | |||
| 523 | 465 | return filter; | |
| 524 | } | ||
| 525 | |||
| 526 | 311 | static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, | |
| 527 | unsigned int pid, | ||
| 528 | SectionCallback *section_cb, | ||
| 529 | void *opaque, | ||
| 530 | int check_crc) | ||
| 531 | { | ||
| 532 | MpegTSFilter *filter; | ||
| 533 | MpegTSSectionFilter *sec; | ||
| 534 | 311 | uint8_t *section_buf = av_mallocz(MAX_SECTION_SIZE); | |
| 535 | |||
| 536 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 311 times.
|
311 | if (!section_buf) |
| 537 | ✗ | return NULL; | |
| 538 | |||
| 539 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 311 times.
|
311 | if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_SECTION))) { |
| 540 | ✗ | av_free(section_buf); | |
| 541 | ✗ | return NULL; | |
| 542 | } | ||
| 543 | 311 | sec = &filter->u.section_filter; | |
| 544 | 311 | sec->section_cb = section_cb; | |
| 545 | 311 | sec->opaque = opaque; | |
| 546 | 311 | sec->section_buf = section_buf; | |
| 547 | 311 | sec->check_crc = check_crc; | |
| 548 | 311 | sec->last_ver = -1; | |
| 549 | |||
| 550 | 311 | return filter; | |
| 551 | } | ||
| 552 | |||
| 553 | 154 | static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid, | |
| 554 | PESCallback *pes_cb, | ||
| 555 | void *opaque) | ||
| 556 | { | ||
| 557 | MpegTSFilter *filter; | ||
| 558 | MpegTSPESFilter *pes; | ||
| 559 | |||
| 560 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
|
154 | if (!(filter = mpegts_open_filter(ts, pid, MPEGTS_PES))) |
| 561 | ✗ | return NULL; | |
| 562 | |||
| 563 | 154 | pes = &filter->u.pes_filter; | |
| 564 | 154 | pes->pes_cb = pes_cb; | |
| 565 | 154 | pes->opaque = opaque; | |
| 566 | 154 | return filter; | |
| 567 | } | ||
| 568 | |||
| 569 | ✗ | static MpegTSFilter *mpegts_open_pcr_filter(MpegTSContext *ts, unsigned int pid) | |
| 570 | { | ||
| 571 | ✗ | return mpegts_open_filter(ts, pid, MPEGTS_PCR); | |
| 572 | } | ||
| 573 | |||
| 574 | 465 | static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) | |
| 575 | { | ||
| 576 | int pid; | ||
| 577 | |||
| 578 | 465 | pid = filter->pid; | |
| 579 |
2/2✓ Branch 0 taken 311 times.
✓ Branch 1 taken 154 times.
|
465 | if (filter->type == MPEGTS_SECTION) |
| 580 | 311 | av_freep(&filter->u.section_filter.section_buf); | |
| 581 |
1/2✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
|
154 | else if (filter->type == MPEGTS_PES) { |
| 582 | 154 | PESContext *pes = filter->u.pes_filter.opaque; | |
| 583 | 154 | av_buffer_unref(&pes->buffer); | |
| 584 | /* referenced private data will be freed later in | ||
| 585 | * avformat_close_input (pes->st->priv_data == pes) */ | ||
| 586 |
4/4✓ Branch 0 taken 136 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 132 times.
|
154 | if (!pes->st || pes->merged_st) { |
| 587 | 22 | av_freep(&filter->u.pes_filter.opaque); | |
| 588 | } | ||
| 589 | } | ||
| 590 | |||
| 591 | 465 | av_free(filter); | |
| 592 | 465 | ts->pids[pid] = NULL; | |
| 593 | 465 | } | |
| 594 | |||
| 595 | 77661 | static int analyze(const uint8_t *buf, int size, int packet_size, | |
| 596 | int probe) | ||
| 597 | { | ||
| 598 | int stat[TS_MAX_PACKET_SIZE]; | ||
| 599 | 77661 | int stat_all = 0; | |
| 600 | int i; | ||
| 601 | 77661 | int best_score = 0; | |
| 602 | |||
| 603 | 77661 | memset(stat, 0, packet_size * sizeof(*stat)); | |
| 604 | |||
| 605 |
2/2✓ Branch 0 taken 1197986865 times.
✓ Branch 1 taken 77661 times.
|
1198064526 | for (i = 0; i < size - 3; i++) { |
| 606 |
2/2✓ Branch 0 taken 2125681 times.
✓ Branch 1 taken 1195861184 times.
|
1197986865 | if (buf[i] == SYNC_BYTE) { |
| 607 | 2125681 | int pid = AV_RB16(buf+1) & 0x1FFF; | |
| 608 | 2125681 | int asc = buf[i + 3] & 0x30; | |
| 609 |
6/6✓ Branch 0 taken 2098384 times.
✓ Branch 1 taken 27297 times.
✓ Branch 2 taken 2096523 times.
✓ Branch 3 taken 1861 times.
✓ Branch 4 taken 1729411 times.
✓ Branch 5 taken 367112 times.
|
2125681 | if (!probe || pid == 0x1FFF || asc) { |
| 610 | 1758569 | int x = i % packet_size; | |
| 611 | 1758569 | stat[x]++; | |
| 612 | 1758569 | stat_all++; | |
| 613 |
2/2✓ Branch 0 taken 130416 times.
✓ Branch 1 taken 1628153 times.
|
1758569 | if (stat[x] > best_score) { |
| 614 | 130416 | best_score = stat[x]; | |
| 615 | } | ||
| 616 | } | ||
| 617 | } | ||
| 618 | } | ||
| 619 | |||
| 620 | 77661 | return best_score - FFMAX(stat_all - 10*best_score, 0)/10; | |
| 621 | } | ||
| 622 | |||
| 623 | /* autodetect fec presence */ | ||
| 624 | 142 | static int get_packet_size(AVFormatContext* s) | |
| 625 | { | ||
| 626 | int score, fec_score, dvhs_score; | ||
| 627 | int margin; | ||
| 628 | int ret; | ||
| 629 | |||
| 630 | /*init buffer to store stream for probing */ | ||
| 631 | 142 | uint8_t buf[PROBE_PACKET_MAX_BUF] = {0}; | |
| 632 | 142 | int buf_size = 0; | |
| 633 | 142 | int max_iterations = 16; | |
| 634 | |||
| 635 |
2/4✓ Branch 0 taken 142 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✗ Branch 3 not taken.
|
142 | while (buf_size < PROBE_PACKET_MAX_BUF && max_iterations--) { |
| 636 | 142 | ret = avio_read_partial(s->pb, buf + buf_size, PROBE_PACKET_MAX_BUF - buf_size); | |
| 637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
|
142 | if (ret < 0) |
| 638 | ✗ | return AVERROR_INVALIDDATA; | |
| 639 | 142 | buf_size += ret; | |
| 640 | |||
| 641 | 142 | score = analyze(buf, buf_size, TS_PACKET_SIZE, 0); | |
| 642 | 142 | dvhs_score = analyze(buf, buf_size, TS_DVHS_PACKET_SIZE, 0); | |
| 643 | 142 | fec_score = analyze(buf, buf_size, TS_FEC_PACKET_SIZE, 0); | |
| 644 | 142 | av_log(s, AV_LOG_TRACE, "Probe: %d, score: %d, dvhs_score: %d, fec_score: %d \n", | |
| 645 | buf_size, score, dvhs_score, fec_score); | ||
| 646 | |||
| 647 | 142 | margin = mid_pred(score, fec_score, dvhs_score); | |
| 648 | |||
| 649 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 141 times.
|
142 | if (buf_size < PROBE_PACKET_MAX_BUF) |
| 650 | 1 | margin += PROBE_PACKET_MARGIN; /*if buffer not filled */ | |
| 651 | |||
| 652 |
2/2✓ Branch 0 taken 132 times.
✓ Branch 1 taken 10 times.
|
142 | if (score > margin) |
| 653 | 132 | return TS_PACKET_SIZE; | |
| 654 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | else if (dvhs_score > margin) |
| 655 | 10 | return TS_DVHS_PACKET_SIZE; | |
| 656 | ✗ | else if (fec_score > margin) | |
| 657 | ✗ | return TS_FEC_PACKET_SIZE; | |
| 658 | } | ||
| 659 | ✗ | return AVERROR_INVALIDDATA; | |
| 660 | } | ||
| 661 | |||
| 662 | typedef struct SectionHeader { | ||
| 663 | uint8_t tid; | ||
| 664 | uint16_t id; | ||
| 665 | uint8_t version; | ||
| 666 | uint8_t current_next; | ||
| 667 | uint8_t sec_num; | ||
| 668 | uint8_t last_sec_num; | ||
| 669 | } SectionHeader; | ||
| 670 | |||
| 671 | 7061 | static int skip_identical(const SectionHeader *h, MpegTSSectionFilter *tssf) | |
| 672 | { | ||
| 673 |
3/4✓ Branch 0 taken 6280 times.
✓ Branch 1 taken 781 times.
✓ Branch 2 taken 6280 times.
✗ Branch 3 not taken.
|
7061 | if (h->version == tssf->last_ver && tssf->last_crc == tssf->crc) |
| 674 | 6280 | return 1; | |
| 675 | |||
| 676 | 781 | tssf->last_ver = h->version; | |
| 677 | 781 | tssf->last_crc = tssf->crc; | |
| 678 | |||
| 679 | 781 | return 0; | |
| 680 | } | ||
| 681 | |||
| 682 | 39262 | static inline int get8(const uint8_t **pp, const uint8_t *p_end) | |
| 683 | { | ||
| 684 | const uint8_t *p; | ||
| 685 | int c; | ||
| 686 | |||
| 687 | 39262 | p = *pp; | |
| 688 |
2/2✓ Branch 0 taken 1776 times.
✓ Branch 1 taken 37486 times.
|
39262 | if (p >= p_end) |
| 689 | 1776 | return AVERROR_INVALIDDATA; | |
| 690 | 37486 | c = *p++; | |
| 691 | 37486 | *pp = p; | |
| 692 | 37486 | return c; | |
| 693 | } | ||
| 694 | |||
| 695 | 12081 | static inline int get16(const uint8_t **pp, const uint8_t *p_end) | |
| 696 | { | ||
| 697 | const uint8_t *p; | ||
| 698 | int c; | ||
| 699 | |||
| 700 | 12081 | p = *pp; | |
| 701 |
2/2✓ Branch 0 taken 430 times.
✓ Branch 1 taken 11651 times.
|
12081 | if (1 >= p_end - p) |
| 702 | 430 | return AVERROR_INVALIDDATA; | |
| 703 | 11651 | c = AV_RB16(p); | |
| 704 | 11651 | p += 2; | |
| 705 | 11651 | *pp = p; | |
| 706 | 11651 | return c; | |
| 707 | } | ||
| 708 | |||
| 709 | /* read and allocate a DVB string preceded by its length */ | ||
| 710 | 314 | static char *getstr8(const uint8_t **pp, const uint8_t *p_end) | |
| 711 | { | ||
| 712 | int len; | ||
| 713 | const uint8_t *p; | ||
| 714 | char *str; | ||
| 715 | |||
| 716 | 314 | p = *pp; | |
| 717 | 314 | len = get8(&p, p_end); | |
| 718 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | if (len < 0) |
| 719 | ✗ | return NULL; | |
| 720 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | if (len > p_end - p) |
| 721 | ✗ | return NULL; | |
| 722 | #if CONFIG_ICONV | ||
| 723 |
1/2✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
|
314 | if (len) { |
| 724 | 314 | const char *encodings[] = { | |
| 725 | "ISO6937", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", | ||
| 726 | "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", | ||
| 727 | "", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "", "", "", "", | ||
| 728 | "", "UCS-2BE", "KSC_5601", "GB2312", "UCS-2BE", "UTF-8", "", "", | ||
| 729 | "", "", "", "", "", "", "", "" | ||
| 730 | }; | ||
| 731 | iconv_t cd; | ||
| 732 | char *in, *out; | ||
| 733 | 314 | size_t inlen = len, outlen = inlen * 6 + 1; | |
| 734 |
2/12✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 314 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
314 | if (len >= 3 && p[0] == 0x10 && !p[1] && p[2] && p[2] <= 0xf && p[2] != 0xc) { |
| 735 | char iso8859[12]; | ||
| 736 | ✗ | snprintf(iso8859, sizeof(iso8859), "ISO-8859-%d", p[2]); | |
| 737 | ✗ | inlen -= 3; | |
| 738 | ✗ | in = (char *)p + 3; | |
| 739 | ✗ | cd = iconv_open("UTF-8", iso8859); | |
| 740 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 306 times.
|
314 | } else if (p[0] < 0x20) { |
| 741 | 8 | inlen -= 1; | |
| 742 | 8 | in = (char *)p + 1; | |
| 743 | 8 | cd = iconv_open("UTF-8", encodings[*p]); | |
| 744 | } else { | ||
| 745 | 306 | in = (char *)p; | |
| 746 | 306 | cd = iconv_open("UTF-8", encodings[0]); | |
| 747 | } | ||
| 748 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | if (cd == (iconv_t)-1) |
| 749 | ✗ | goto no_iconv; | |
| 750 | 314 | str = out = av_malloc(outlen); | |
| 751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | if (!str) { |
| 752 | ✗ | iconv_close(cd); | |
| 753 | 314 | return NULL; | |
| 754 | } | ||
| 755 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 314 times.
|
314 | if (iconv(cd, &in, &inlen, &out, &outlen) == -1) { |
| 756 | ✗ | iconv_close(cd); | |
| 757 | ✗ | av_freep(&str); | |
| 758 | ✗ | goto no_iconv; | |
| 759 | } | ||
| 760 | 314 | iconv_close(cd); | |
| 761 | 314 | *out = 0; | |
| 762 | 314 | *pp = p + len; | |
| 763 | 314 | return str; | |
| 764 | } | ||
| 765 | ✗ | no_iconv: | |
| 766 | #endif | ||
| 767 | ✗ | str = av_malloc(len + 1); | |
| 768 | ✗ | if (!str) | |
| 769 | ✗ | return NULL; | |
| 770 | ✗ | memcpy(str, p, len); | |
| 771 | ✗ | str[len] = '\0'; | |
| 772 | ✗ | p += len; | |
| 773 | ✗ | *pp = p; | |
| 774 | ✗ | return str; | |
| 775 | } | ||
| 776 | |||
| 777 | 7948 | static int parse_section_header(SectionHeader *h, | |
| 778 | const uint8_t **pp, const uint8_t *p_end) | ||
| 779 | { | ||
| 780 | int val; | ||
| 781 | |||
| 782 | 7948 | val = get8(pp, p_end); | |
| 783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7948 times.
|
7948 | if (val < 0) |
| 784 | ✗ | return val; | |
| 785 | 7948 | h->tid = val; | |
| 786 | 7948 | *pp += 2; | |
| 787 | 7948 | val = get16(pp, p_end); | |
| 788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7948 times.
|
7948 | if (val < 0) |
| 789 | ✗ | return val; | |
| 790 | 7948 | h->id = val; | |
| 791 | 7948 | val = get8(pp, p_end); | |
| 792 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7948 times.
|
7948 | if (val < 0) |
| 793 | ✗ | return val; | |
| 794 | 7948 | h->version = (val >> 1) & 0x1f; | |
| 795 | 7948 | h->current_next = val & 0x01; | |
| 796 | 7948 | val = get8(pp, p_end); | |
| 797 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7948 times.
|
7948 | if (val < 0) |
| 798 | ✗ | return val; | |
| 799 | 7948 | h->sec_num = val; | |
| 800 | 7948 | val = get8(pp, p_end); | |
| 801 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7948 times.
|
7948 | if (val < 0) |
| 802 | ✗ | return val; | |
| 803 | 7948 | h->last_sec_num = val; | |
| 804 | 7948 | return 0; | |
| 805 | } | ||
| 806 | |||
| 807 | typedef struct StreamType { | ||
| 808 | uint32_t stream_type; | ||
| 809 | enum AVMediaType codec_type; | ||
| 810 | enum AVCodecID codec_id; | ||
| 811 | } StreamType; | ||
| 812 | |||
| 813 | static const StreamType ISO_types[] = { | ||
| 814 | { STREAM_TYPE_VIDEO_MPEG1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO }, | ||
| 815 | { STREAM_TYPE_VIDEO_MPEG2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO }, | ||
| 816 | { STREAM_TYPE_AUDIO_MPEG1, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 }, | ||
| 817 | { STREAM_TYPE_AUDIO_MPEG2, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3 }, | ||
| 818 | { STREAM_TYPE_AUDIO_AAC, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, | ||
| 819 | { STREAM_TYPE_VIDEO_MPEG4, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, | ||
| 820 | /* Makito encoder sets stream type 0x11 for AAC, | ||
| 821 | * so auto-detect LOAS/LATM instead of hardcoding it. */ | ||
| 822 | #if !CONFIG_LOAS_DEMUXER | ||
| 823 | { STREAM_TYPE_AUDIO_AAC_LATM, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM }, /* LATM syntax */ | ||
| 824 | #endif | ||
| 825 | { STREAM_TYPE_VIDEO_H264, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, | ||
| 826 | { STREAM_TYPE_AUDIO_MPEG4, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, | ||
| 827 | { STREAM_TYPE_VIDEO_MVC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, | ||
| 828 | { STREAM_TYPE_VIDEO_JPEG2000, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000 }, | ||
| 829 | { STREAM_TYPE_VIDEO_HEVC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, | ||
| 830 | { STREAM_TYPE_VIDEO_JPEGXS, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEGXS }, | ||
| 831 | { STREAM_TYPE_VIDEO_LCEVC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_LCEVC }, | ||
| 832 | { STREAM_TYPE_VIDEO_VVC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VVC }, | ||
| 833 | { STREAM_TYPE_VIDEO_CAVS, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, | ||
| 834 | { STREAM_TYPE_VIDEO_DIRAC, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, | ||
| 835 | { STREAM_TYPE_VIDEO_AVS2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS2 }, | ||
| 836 | { STREAM_TYPE_VIDEO_AVS3, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS3 }, | ||
| 837 | { STREAM_TYPE_VIDEO_VC1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, | ||
| 838 | { 0 }, | ||
| 839 | }; | ||
| 840 | |||
| 841 | static const StreamType HDMV_types[] = { | ||
| 842 | { STREAM_TYPE_BLURAY_AUDIO_PCM_BLURAY, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_BLURAY }, | ||
| 843 | { STREAM_TYPE_BLURAY_AUDIO_AC3, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, | ||
| 844 | { STREAM_TYPE_BLURAY_AUDIO_DTS, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 845 | { STREAM_TYPE_BLURAY_AUDIO_TRUEHD, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_TRUEHD }, | ||
| 846 | { STREAM_TYPE_BLURAY_AUDIO_EAC3, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, | ||
| 847 | { STREAM_TYPE_BLURAY_AUDIO_DTS_HD, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 848 | { STREAM_TYPE_BLURAY_AUDIO_DTS_HD_MASTER, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 849 | { STREAM_TYPE_BLURAY_AUDIO_EAC3_SECONDARY, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, | ||
| 850 | { STREAM_TYPE_BLURAY_AUDIO_DTS_EXPRESS_SECONDARY, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 851 | { STREAM_TYPE_BLURAY_SUBTITLE_PGS, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_HDMV_PGS_SUBTITLE }, | ||
| 852 | { STREAM_TYPE_BLURAY_SUBTITLE_TEXT, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_HDMV_TEXT_SUBTITLE }, | ||
| 853 | { 0 }, | ||
| 854 | }; | ||
| 855 | |||
| 856 | /* SCTE types */ | ||
| 857 | static const StreamType SCTE_types[] = { | ||
| 858 | { STREAM_TYPE_SCTE_DATA_SCTE_35, AVMEDIA_TYPE_DATA, AV_CODEC_ID_SCTE_35 }, | ||
| 859 | { 0 }, | ||
| 860 | }; | ||
| 861 | |||
| 862 | /* ATSC ? */ | ||
| 863 | static const StreamType MISC_types[] = { | ||
| 864 | { STREAM_TYPE_ATSC_AUDIO_AC3, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, | ||
| 865 | { STREAM_TYPE_ATSC_AUDIO_EAC3, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, | ||
| 866 | { 0x8a, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 867 | { 0 }, | ||
| 868 | }; | ||
| 869 | |||
| 870 | /* HLS Sample Encryption Types */ | ||
| 871 | static const StreamType HLS_SAMPLE_ENC_types[] = { | ||
| 872 | { STREAM_TYPE_HLS_SE_VIDEO_H264, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264}, | ||
| 873 | { STREAM_TYPE_HLS_SE_AUDIO_AAC, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, | ||
| 874 | { STREAM_TYPE_HLS_SE_AUDIO_AC3, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, | ||
| 875 | { STREAM_TYPE_HLS_SE_AUDIO_EAC3, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3}, | ||
| 876 | { 0 }, | ||
| 877 | }; | ||
| 878 | |||
| 879 | static const StreamType REGD_types[] = { | ||
| 880 | { MKTAG('d', 'r', 'a', 'c'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, | ||
| 881 | { MKTAG('A', 'C', '-', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, | ||
| 882 | { MKTAG('A', 'C', '-', '4'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC4 }, | ||
| 883 | { MKTAG('B', 'S', 'S', 'D'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_S302M }, | ||
| 884 | { MKTAG('D', 'T', 'S', '1'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 885 | { MKTAG('D', 'T', 'S', '2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 886 | { MKTAG('D', 'T', 'S', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 887 | { MKTAG('E', 'A', 'C', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, | ||
| 888 | { MKTAG('H', 'E', 'V', 'C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC }, | ||
| 889 | { MKTAG('V', 'V', 'C', ' '), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VVC }, | ||
| 890 | { MKTAG('K', 'L', 'V', 'A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV }, | ||
| 891 | { MKTAG('V', 'A', 'N', 'C'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_2038 }, | ||
| 892 | { MKTAG('I', 'D', '3', ' '), AVMEDIA_TYPE_DATA, AV_CODEC_ID_TIMED_ID3 }, | ||
| 893 | { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, | ||
| 894 | { MKTAG('O', 'p', 'u', 's'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_OPUS }, | ||
| 895 | { 0 }, | ||
| 896 | }; | ||
| 897 | |||
| 898 | static const StreamType METADATA_types[] = { | ||
| 899 | { MKTAG('K','L','V','A'), AVMEDIA_TYPE_DATA, AV_CODEC_ID_SMPTE_KLV }, | ||
| 900 | { MKTAG('I','D','3',' '), AVMEDIA_TYPE_DATA, AV_CODEC_ID_TIMED_ID3 }, | ||
| 901 | { 0 }, | ||
| 902 | }; | ||
| 903 | |||
| 904 | /* descriptor present */ | ||
| 905 | static const StreamType DESC_types[] = { | ||
| 906 | { AC3_DESCRIPTOR, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AC3 }, | ||
| 907 | { ENHANCED_AC3_DESCRIPTOR, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3 }, | ||
| 908 | { DTS_DESCRIPTOR, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS }, | ||
| 909 | { TELETEXT_DESCRIPTOR, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_TELETEXT }, | ||
| 910 | { SUBTITLING_DESCRIPTOR, AVMEDIA_TYPE_SUBTITLE, AV_CODEC_ID_DVB_SUBTITLE }, | ||
| 911 | { 0 }, | ||
| 912 | }; | ||
| 913 | |||
| 914 | 224 | static void mpegts_find_stream_type(AVStream *st, | |
| 915 | uint32_t stream_type, | ||
| 916 | const StreamType *types) | ||
| 917 | { | ||
| 918 | 224 | FFStream *const sti = ffstream(st); | |
| 919 |
2/2✓ Branch 0 taken 1469 times.
✓ Branch 1 taken 77 times.
|
1546 | for (; types->stream_type; types++) |
| 920 |
2/2✓ Branch 0 taken 147 times.
✓ Branch 1 taken 1322 times.
|
1469 | if (stream_type == types->stream_type) { |
| 921 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 133 times.
|
147 | if (st->codecpar->codec_type != types->codec_type || |
| 922 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
|
14 | st->codecpar->codec_id != types->codec_id) { |
| 923 | 146 | st->codecpar->codec_type = types->codec_type; | |
| 924 | 146 | st->codecpar->codec_id = types->codec_id; | |
| 925 | 146 | sti->need_context_update = 1; | |
| 926 | } | ||
| 927 | 147 | sti->request_probe = 0; | |
| 928 | 147 | return; | |
| 929 | } | ||
| 930 | } | ||
| 931 | |||
| 932 | 142 | static int mpegts_set_stream_info(AVStream *st, PESContext *pes, | |
| 933 | uint32_t stream_type, uint32_t prog_reg_desc) | ||
| 934 | { | ||
| 935 | 142 | FFStream *const sti = ffstream(st); | |
| 936 | 142 | int old_codec_type = st->codecpar->codec_type; | |
| 937 | 142 | int old_codec_id = st->codecpar->codec_id; | |
| 938 | 142 | int old_codec_tag = st->codecpar->codec_tag; | |
| 939 | |||
| 940 | 142 | avpriv_set_pts_info(st, 33, 1, 90000); | |
| 941 | 142 | st->priv_data = pes; | |
| 942 | 142 | st->codecpar->codec_type = AVMEDIA_TYPE_DATA; | |
| 943 | 142 | st->codecpar->codec_id = AV_CODEC_ID_NONE; | |
| 944 | 142 | sti->need_parsing = AVSTREAM_PARSE_FULL; | |
| 945 | 142 | pes->st = st; | |
| 946 | 142 | pes->stream_type = stream_type; | |
| 947 | |||
| 948 | 142 | av_log(pes->stream, AV_LOG_DEBUG, | |
| 949 | "stream=%d stream_type=%x pid=%x prog_reg_desc=%.4s\n", | ||
| 950 | st->index, pes->stream_type, pes->pid, (char *)&prog_reg_desc); | ||
| 951 | |||
| 952 | 142 | st->codecpar->codec_tag = pes->stream_type; | |
| 953 | |||
| 954 | 142 | mpegts_find_stream_type(st, pes->stream_type, ISO_types); | |
| 955 |
4/4✓ Branch 0 taken 134 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 131 times.
|
142 | if (pes->stream_type == STREAM_TYPE_AUDIO_MPEG2 || pes->stream_type == STREAM_TYPE_AUDIO_AAC) |
| 956 | 11 | sti->request_probe = 50; | |
| 957 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 131 times.
|
142 | if (pes->stream_type == STREAM_TYPE_PRIVATE_DATA) |
| 958 | 11 | sti->request_probe = AVPROBE_SCORE_STREAM_RETRY; | |
| 959 |
2/2✓ Branch 0 taken 136 times.
✓ Branch 1 taken 6 times.
|
142 | if ((prog_reg_desc == AV_RL32("HDMV") || |
| 960 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
|
136 | prog_reg_desc == AV_RL32("HDPR")) && |
| 961 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | st->codecpar->codec_id == AV_CODEC_ID_NONE) { |
| 962 | 6 | mpegts_find_stream_type(st, pes->stream_type, HDMV_types); | |
| 963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (pes->stream_type == STREAM_TYPE_BLURAY_AUDIO_TRUEHD) { |
| 964 | // HDMV TrueHD streams also contain an AC3 coded version of the | ||
| 965 | // audio track - add a second stream for this | ||
| 966 | AVStream *sub_st; | ||
| 967 | // priv_data cannot be shared between streams | ||
| 968 | ✗ | PESContext *sub_pes = av_memdup(pes, sizeof(*sub_pes)); | |
| 969 | ✗ | if (!sub_pes) | |
| 970 | ✗ | return AVERROR(ENOMEM); | |
| 971 | |||
| 972 | ✗ | sub_st = avformat_new_stream(pes->stream, NULL); | |
| 973 | ✗ | if (!sub_st) { | |
| 974 | ✗ | av_free(sub_pes); | |
| 975 | ✗ | return AVERROR(ENOMEM); | |
| 976 | } | ||
| 977 | |||
| 978 | ✗ | sub_st->id = pes->pid; | |
| 979 | ✗ | avpriv_set_pts_info(sub_st, 33, 1, 90000); | |
| 980 | ✗ | sub_st->priv_data = sub_pes; | |
| 981 | ✗ | sub_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; | |
| 982 | ✗ | sub_st->codecpar->codec_id = AV_CODEC_ID_AC3; | |
| 983 | ✗ | ffstream(sub_st)->need_parsing = AVSTREAM_PARSE_FULL; | |
| 984 | ✗ | sub_pes->sub_st = pes->sub_st = sub_st; | |
| 985 | } | ||
| 986 | } | ||
| 987 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 107 times.
|
142 | if (st->codecpar->codec_id == AV_CODEC_ID_NONE) |
| 988 | 35 | mpegts_find_stream_type(st, pes->stream_type, MISC_types); | |
| 989 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 128 times.
|
142 | if (st->codecpar->codec_id == AV_CODEC_ID_NONE) |
| 990 | 14 | mpegts_find_stream_type(st, pes->stream_type, HLS_SAMPLE_ENC_types); | |
| 991 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 128 times.
|
142 | if (st->codecpar->codec_id == AV_CODEC_ID_NONE) { |
| 992 | 14 | st->codecpar->codec_id = old_codec_id; | |
| 993 | 14 | st->codecpar->codec_type = old_codec_type; | |
| 994 | } | ||
| 995 |
2/2✓ Branch 0 taken 134 times.
✓ Branch 1 taken 8 times.
|
142 | if ((st->codecpar->codec_id == AV_CODEC_ID_NONE || |
| 996 |
3/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
134 | (sti->request_probe > 0 && sti->request_probe < AVPROBE_SCORE_STREAM_RETRY / 5)) && |
| 997 |
3/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
|
8 | sti->probe_packets > 0 && |
| 998 | stream_type == STREAM_TYPE_PRIVATE_DATA) { | ||
| 999 | 5 | st->codecpar->codec_type = AVMEDIA_TYPE_DATA; | |
| 1000 | 5 | st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA; | |
| 1001 | 5 | sti->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5; | |
| 1002 | } | ||
| 1003 | |||
| 1004 | /* queue a context update if properties changed */ | ||
| 1005 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 129 times.
|
142 | if (old_codec_type != st->codecpar->codec_type || |
| 1006 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4 times.
|
13 | old_codec_id != st->codecpar->codec_id || |
| 1007 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | old_codec_tag != st->codecpar->codec_tag) |
| 1008 | 142 | sti->need_context_update = 1; | |
| 1009 | |||
| 1010 | 142 | return 0; | |
| 1011 | } | ||
| 1012 | |||
| 1013 | 64909 | static void reset_pes_packet_state(PESContext *pes) | |
| 1014 | { | ||
| 1015 | 64909 | pes->pts = AV_NOPTS_VALUE; | |
| 1016 | 64909 | pes->dts = AV_NOPTS_VALUE; | |
| 1017 | 64909 | pes->data_index = 0; | |
| 1018 | 64909 | pes->flags = 0; | |
| 1019 | 64909 | av_buffer_unref(&pes->buffer); | |
| 1020 | 64909 | } | |
| 1021 | |||
| 1022 | 12 | static void new_data_packet(const uint8_t *buffer, int len, AVPacket *pkt) | |
| 1023 | { | ||
| 1024 | 12 | av_packet_unref(pkt); | |
| 1025 | 12 | pkt->data = (uint8_t *)buffer; | |
| 1026 | 12 | pkt->size = len; | |
| 1027 | 12 | } | |
| 1028 | |||
| 1029 | 34359 | static int new_pes_packet(PESContext *pes, AVPacket *pkt) | |
| 1030 | { | ||
| 1031 | uint8_t *sd; | ||
| 1032 | |||
| 1033 | 34359 | av_packet_unref(pkt); | |
| 1034 | |||
| 1035 | 34359 | pkt->buf = pes->buffer; | |
| 1036 | 34359 | pkt->data = pes->buffer->data; | |
| 1037 | 34359 | pkt->size = pes->data_index; | |
| 1038 | |||
| 1039 |
2/2✓ Branch 0 taken 29726 times.
✓ Branch 1 taken 4633 times.
|
34359 | if (pes->PES_packet_length && |
| 1040 |
2/2✓ Branch 0 taken 93 times.
✓ Branch 1 taken 29633 times.
|
29726 | pes->pes_header_size + pes->data_index != pes->PES_packet_length + |
| 1041 | PES_START_SIZE) { | ||
| 1042 | 93 | av_log(pes->stream, AV_LOG_WARNING, "PES packet size mismatch\n"); | |
| 1043 | 93 | pes->flags |= AV_PKT_FLAG_CORRUPT; | |
| 1044 | } | ||
| 1045 | |||
| 1046 | // JPEG-XS PES payload | ||
| 1047 |
3/4✓ Branch 0 taken 4160 times.
✓ Branch 1 taken 30199 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4160 times.
|
34359 | if (pes->stream_id == 0xbd && pes->stream_type == 0x32 && |
| 1048 | ✗ | pkt->size >= 8 && memcmp(pkt->data + 4, "jxes", 4) == 0) | |
| 1049 | { | ||
| 1050 | ✗ | uint32_t header_size = AV_RB32(pkt->data); | |
| 1051 | ✗ | if (header_size > pkt->size) { | |
| 1052 | ✗ | av_log(pes->stream, AV_LOG_WARNING, | |
| 1053 | "Invalid JPEG-XS header size %"PRIu32" > packet size %d\n", | ||
| 1054 | header_size, pkt->size); | ||
| 1055 | ✗ | pes->flags |= AV_PKT_FLAG_CORRUPT; | |
| 1056 | } else { | ||
| 1057 | ✗ | pkt->data += header_size; | |
| 1058 | ✗ | pkt->size -= header_size; | |
| 1059 | } | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | 34359 | memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
| 1063 | |||
| 1064 | // Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID | ||
| 1065 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 34359 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
34359 | if (pes->sub_st && pes->stream_type == STREAM_TYPE_BLURAY_AUDIO_TRUEHD && pes->extended_stream_id == 0x76) |
| 1066 | ✗ | pkt->stream_index = pes->sub_st->index; | |
| 1067 | else | ||
| 1068 | 34359 | pkt->stream_index = pes->st->index; | |
| 1069 | 34359 | pkt->pts = pes->pts; | |
| 1070 | 34359 | pkt->dts = pes->dts; | |
| 1071 | /* store position of first TS packet of this PES packet */ | ||
| 1072 | 34359 | pkt->pos = pes->ts_packet_pos; | |
| 1073 | 34359 | pkt->flags = pes->flags; | |
| 1074 | |||
| 1075 | 34359 | pes->buffer = NULL; | |
| 1076 | 34359 | reset_pes_packet_state(pes); | |
| 1077 | |||
| 1078 | 34359 | sd = av_packet_new_side_data(pkt, AV_PKT_DATA_MPEGTS_STREAM_ID, 1); | |
| 1079 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34359 times.
|
34359 | if (!sd) |
| 1080 | ✗ | return AVERROR(ENOMEM); | |
| 1081 | 34359 | *sd = pes->stream_id; | |
| 1082 | |||
| 1083 | 34359 | return 0; | |
| 1084 | } | ||
| 1085 | |||
| 1086 | ✗ | static uint64_t get_ts64(GetBitContext *gb, int bits) | |
| 1087 | { | ||
| 1088 | ✗ | if (get_bits_left(gb) < bits) | |
| 1089 | ✗ | return AV_NOPTS_VALUE; | |
| 1090 | ✗ | return get_bits64(gb, bits); | |
| 1091 | } | ||
| 1092 | |||
| 1093 | ✗ | static int read_sl_header(PESContext *pes, SLConfigDescr *sl, | |
| 1094 | const uint8_t *buf, int buf_size) | ||
| 1095 | { | ||
| 1096 | GetBitContext gb; | ||
| 1097 | ✗ | int au_start_flag = 0, au_end_flag = 0, ocr_flag = 0, idle_flag = 0; | |
| 1098 | ✗ | int padding_flag = 0, padding_bits = 0, inst_bitrate_flag = 0; | |
| 1099 | ✗ | int dts_flag = -1, cts_flag = -1; | |
| 1100 | ✗ | int64_t dts = AV_NOPTS_VALUE, cts = AV_NOPTS_VALUE; | |
| 1101 | uint8_t buf_padded[128 + AV_INPUT_BUFFER_PADDING_SIZE]; | ||
| 1102 | ✗ | int buf_padded_size = FFMIN(buf_size, sizeof(buf_padded) - AV_INPUT_BUFFER_PADDING_SIZE); | |
| 1103 | |||
| 1104 | ✗ | memcpy(buf_padded, buf, buf_padded_size); | |
| 1105 | |||
| 1106 | ✗ | init_get_bits(&gb, buf_padded, buf_padded_size * 8); | |
| 1107 | |||
| 1108 | ✗ | if (sl->use_au_start) | |
| 1109 | ✗ | au_start_flag = get_bits1(&gb); | |
| 1110 | ✗ | if (sl->use_au_end) | |
| 1111 | ✗ | au_end_flag = get_bits1(&gb); | |
| 1112 | ✗ | if (!sl->use_au_start && !sl->use_au_end) | |
| 1113 | ✗ | au_start_flag = au_end_flag = 1; | |
| 1114 | ✗ | if (sl->ocr_len > 0) | |
| 1115 | ✗ | ocr_flag = get_bits1(&gb); | |
| 1116 | ✗ | if (sl->use_idle) | |
| 1117 | ✗ | idle_flag = get_bits1(&gb); | |
| 1118 | ✗ | if (sl->use_padding) | |
| 1119 | ✗ | padding_flag = get_bits1(&gb); | |
| 1120 | ✗ | if (padding_flag) | |
| 1121 | ✗ | padding_bits = get_bits(&gb, 3); | |
| 1122 | |||
| 1123 | ✗ | if (!idle_flag && (!padding_flag || padding_bits != 0)) { | |
| 1124 | ✗ | if (sl->packet_seq_num_len) | |
| 1125 | ✗ | skip_bits_long(&gb, sl->packet_seq_num_len); | |
| 1126 | ✗ | if (sl->degr_prior_len) | |
| 1127 | ✗ | if (get_bits1(&gb)) | |
| 1128 | ✗ | skip_bits(&gb, sl->degr_prior_len); | |
| 1129 | ✗ | if (ocr_flag) | |
| 1130 | ✗ | skip_bits_long(&gb, sl->ocr_len); | |
| 1131 | ✗ | if (au_start_flag) { | |
| 1132 | ✗ | if (sl->use_rand_acc_pt) | |
| 1133 | ✗ | get_bits1(&gb); | |
| 1134 | ✗ | if (sl->au_seq_num_len > 0) | |
| 1135 | ✗ | skip_bits_long(&gb, sl->au_seq_num_len); | |
| 1136 | ✗ | if (sl->use_timestamps) { | |
| 1137 | ✗ | dts_flag = get_bits1(&gb); | |
| 1138 | ✗ | cts_flag = get_bits1(&gb); | |
| 1139 | } | ||
| 1140 | } | ||
| 1141 | ✗ | if (sl->inst_bitrate_len) | |
| 1142 | ✗ | inst_bitrate_flag = get_bits1(&gb); | |
| 1143 | ✗ | if (dts_flag == 1) | |
| 1144 | ✗ | dts = get_ts64(&gb, sl->timestamp_len); | |
| 1145 | ✗ | if (cts_flag == 1) | |
| 1146 | ✗ | cts = get_ts64(&gb, sl->timestamp_len); | |
| 1147 | ✗ | if (sl->au_len > 0) | |
| 1148 | ✗ | skip_bits_long(&gb, sl->au_len); | |
| 1149 | ✗ | if (inst_bitrate_flag) | |
| 1150 | ✗ | skip_bits_long(&gb, sl->inst_bitrate_len); | |
| 1151 | } | ||
| 1152 | |||
| 1153 | ✗ | if (dts != AV_NOPTS_VALUE) | |
| 1154 | ✗ | pes->dts = dts; | |
| 1155 | ✗ | if (cts != AV_NOPTS_VALUE) | |
| 1156 | ✗ | pes->pts = cts; | |
| 1157 | |||
| 1158 | ✗ | if (sl->timestamp_len && sl->timestamp_res) | |
| 1159 | ✗ | avpriv_set_pts_info(pes->st, sl->timestamp_len, 1, sl->timestamp_res); | |
| 1160 | |||
| 1161 | ✗ | return (get_bits_count(&gb) + 7) >> 3; | |
| 1162 | } | ||
| 1163 | |||
| 1164 | 34461 | static AVBufferRef *buffer_pool_get(MpegTSContext *ts, int size) | |
| 1165 | { | ||
| 1166 | 34461 | int index = av_log2(size + AV_INPUT_BUFFER_PADDING_SIZE); | |
| 1167 |
2/2✓ Branch 0 taken 184 times.
✓ Branch 1 taken 34277 times.
|
34461 | if (!ts->pools[index]) { |
| 1168 |
2/2✓ Branch 0 taken 146 times.
✓ Branch 1 taken 38 times.
|
184 | int pool_size = FFMIN(ts->max_packet_size + AV_INPUT_BUFFER_PADDING_SIZE, 2 << index); |
| 1169 | 184 | ts->pools[index] = av_buffer_pool_init(pool_size, NULL); | |
| 1170 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
|
184 | if (!ts->pools[index]) |
| 1171 | ✗ | return NULL; | |
| 1172 | } | ||
| 1173 | 34461 | return av_buffer_pool_get(ts->pools[index]); | |
| 1174 | } | ||
| 1175 | |||
| 1176 | /* return non zero if a packet could be constructed */ | ||
| 1177 | 428989 | static int mpegts_push_data(MpegTSFilter *filter, | |
| 1178 | const uint8_t *buf, int buf_size, int is_start, | ||
| 1179 | int64_t pos) | ||
| 1180 | { | ||
| 1181 | 428989 | PESContext *pes = filter->u.pes_filter.opaque; | |
| 1182 | 428989 | MpegTSContext *ts = pes->ts; | |
| 1183 | const uint8_t *p; | ||
| 1184 | int ret, len; | ||
| 1185 | |||
| 1186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 428989 times.
|
428989 | if (!ts->pkt) |
| 1187 | ✗ | return 0; | |
| 1188 | |||
| 1189 |
2/2✓ Branch 0 taken 35061 times.
✓ Branch 1 taken 393928 times.
|
428989 | if (is_start) { |
| 1190 |
3/4✓ Branch 0 taken 4511 times.
✓ Branch 1 taken 30550 times.
✓ Branch 2 taken 4511 times.
✗ Branch 3 not taken.
|
35061 | if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { |
| 1191 | 4511 | ret = new_pes_packet(pes, ts->pkt); | |
| 1192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4511 times.
|
4511 | if (ret < 0) |
| 1193 | ✗ | return ret; | |
| 1194 | 4511 | ts->stop_parse = 1; | |
| 1195 | } else { | ||
| 1196 | 30550 | reset_pes_packet_state(pes); | |
| 1197 | } | ||
| 1198 | 35061 | pes->state = MPEGTS_HEADER; | |
| 1199 | 35061 | pes->ts_packet_pos = pos; | |
| 1200 | } | ||
| 1201 | 428989 | p = buf; | |
| 1202 |
2/2✓ Branch 0 taken 532970 times.
✓ Branch 1 taken 428989 times.
|
1390948 | while (buf_size > 0) { |
| 1203 |
5/6✓ Branch 0 taken 35061 times.
✓ Branch 1 taken 34461 times.
✓ Branch 2 taken 34461 times.
✓ Branch 3 taken 410354 times.
✓ Branch 4 taken 18633 times.
✗ Branch 5 not taken.
|
532970 | switch (pes->state) { |
| 1204 | 35061 | case MPEGTS_HEADER: | |
| 1205 | 35061 | len = PES_START_SIZE - pes->data_index; | |
| 1206 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 35059 times.
|
35061 | if (len > buf_size) |
| 1207 | 2 | len = buf_size; | |
| 1208 | 35061 | memcpy(pes->header + pes->data_index, p, len); | |
| 1209 | 35061 | pes->data_index += len; | |
| 1210 | 35061 | p += len; | |
| 1211 | 35061 | buf_size -= len; | |
| 1212 |
2/2✓ Branch 0 taken 35059 times.
✓ Branch 1 taken 2 times.
|
35061 | if (pes->data_index == PES_START_SIZE) { |
| 1213 | /* we got all the PES or section header. We can now | ||
| 1214 | * decide */ | ||
| 1215 |
3/4✓ Branch 0 taken 35052 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 35052 times.
|
35059 | if (pes->header[0] == 0x00 && pes->header[1] == 0x00 && |
| 1216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35052 times.
|
35052 | pes->header[2] == 0x01) { |
| 1217 | /* it must be an MPEG-2 PES stream */ | ||
| 1218 | 35052 | pes->stream_id = pes->header[3]; | |
| 1219 | 35052 | av_log(pes->stream, AV_LOG_TRACE, "pid=%x stream_id=%#x\n", pes->pid, pes->stream_id); | |
| 1220 | |||
| 1221 |
3/4✓ Branch 0 taken 35052 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 591 times.
✓ Branch 3 taken 34461 times.
|
35052 | if ((pes->st && pes->st->discard == AVDISCARD_ALL && |
| 1222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 591 times.
|
591 | (!pes->sub_st || |
| 1223 | ✗ | pes->sub_st->discard == AVDISCARD_ALL)) || | |
| 1224 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | pes->stream_id == STREAM_ID_PADDING_STREAM) |
| 1225 | 591 | goto skip; | |
| 1226 | |||
| 1227 | /* stream not present in PMT */ | ||
| 1228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | if (!pes->st) { |
| 1229 | ✗ | if (ts->skip_changes) | |
| 1230 | ✗ | goto skip; | |
| 1231 | ✗ | if (ts->merge_pmt_versions) | |
| 1232 | ✗ | goto skip; /* wait for PMT to merge new stream */ | |
| 1233 | |||
| 1234 | ✗ | pes->st = avformat_new_stream(ts->stream, NULL); | |
| 1235 | ✗ | if (!pes->st) | |
| 1236 | ✗ | return AVERROR(ENOMEM); | |
| 1237 | ✗ | pes->st->id = pes->pid; | |
| 1238 | ✗ | mpegts_set_stream_info(pes->st, pes, 0, 0); | |
| 1239 | } | ||
| 1240 | |||
| 1241 | 34461 | pes->PES_packet_length = AV_RB16(pes->header + 4); | |
| 1242 | /* NOTE: zero length means the PES size is unbounded */ | ||
| 1243 | |||
| 1244 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | if (pes->stream_id != STREAM_ID_PROGRAM_STREAM_MAP && |
| 1245 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | pes->stream_id != STREAM_ID_PRIVATE_STREAM_2 && |
| 1246 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | pes->stream_id != STREAM_ID_ECM_STREAM && |
| 1247 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | pes->stream_id != STREAM_ID_EMM_STREAM && |
| 1248 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | pes->stream_id != STREAM_ID_PROGRAM_STREAM_DIRECTORY && |
| 1249 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | pes->stream_id != STREAM_ID_DSMCC_STREAM && |
| 1250 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
68922 | pes->stream_id != STREAM_ID_TYPE_E_STREAM) { |
| 1251 | 34461 | FFStream *const pes_sti = ffstream(pes->st); | |
| 1252 | 34461 | pes->state = MPEGTS_PESHEADER; | |
| 1253 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 34459 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
34461 | if (pes->st->codecpar->codec_id == AV_CODEC_ID_NONE && !pes_sti->request_probe) { |
| 1254 | 2 | av_log(pes->stream, AV_LOG_TRACE, | |
| 1255 | "pid=%x stream_type=%x probing\n", | ||
| 1256 | pes->pid, | ||
| 1257 | pes->stream_type); | ||
| 1258 | 2 | pes_sti->request_probe = 1; | |
| 1259 | } | ||
| 1260 | } else { | ||
| 1261 | ✗ | pes->pes_header_size = 6; | |
| 1262 | ✗ | pes->state = MPEGTS_PAYLOAD; | |
| 1263 | ✗ | pes->data_index = 0; | |
| 1264 | } | ||
| 1265 | } else { | ||
| 1266 | /* otherwise, it should be a table */ | ||
| 1267 | /* skip packet */ | ||
| 1268 | 7 | skip: | |
| 1269 | 598 | pes->state = MPEGTS_SKIP; | |
| 1270 | 598 | continue; | |
| 1271 | } | ||
| 1272 | } | ||
| 1273 | 34463 | break; | |
| 1274 | /**********************************************/ | ||
| 1275 | /* PES packing parsing */ | ||
| 1276 | 34461 | case MPEGTS_PESHEADER: | |
| 1277 | 34461 | len = PES_HEADER_SIZE - pes->data_index; | |
| 1278 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | if (len < 0) |
| 1279 | ✗ | return AVERROR_INVALIDDATA; | |
| 1280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | if (len > buf_size) |
| 1281 | ✗ | len = buf_size; | |
| 1282 | 34461 | memcpy(pes->header + pes->data_index, p, len); | |
| 1283 | 34461 | pes->data_index += len; | |
| 1284 | 34461 | p += len; | |
| 1285 | 34461 | buf_size -= len; | |
| 1286 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | if (pes->data_index == PES_HEADER_SIZE) { |
| 1287 | 34461 | pes->pes_header_size = pes->header[8] + 9; | |
| 1288 | 34461 | pes->state = MPEGTS_PESHEADER_FILL; | |
| 1289 | } | ||
| 1290 | 34461 | break; | |
| 1291 | 34461 | case MPEGTS_PESHEADER_FILL: | |
| 1292 | 34461 | len = pes->pes_header_size - pes->data_index; | |
| 1293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | if (len < 0) |
| 1294 | ✗ | return AVERROR_INVALIDDATA; | |
| 1295 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | if (len > buf_size) |
| 1296 | ✗ | len = buf_size; | |
| 1297 | 34461 | memcpy(pes->header + pes->data_index, p, len); | |
| 1298 | 34461 | pes->data_index += len; | |
| 1299 | 34461 | p += len; | |
| 1300 | 34461 | buf_size -= len; | |
| 1301 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | if (pes->data_index == pes->pes_header_size) { |
| 1302 | const uint8_t *r; | ||
| 1303 | unsigned int flags, pes_ext, skip; | ||
| 1304 | |||
| 1305 | 34461 | flags = pes->header[7]; | |
| 1306 | 34461 | r = pes->header + 9; | |
| 1307 | 34461 | pes->pts = AV_NOPTS_VALUE; | |
| 1308 | 34461 | pes->dts = AV_NOPTS_VALUE; | |
| 1309 |
2/2✓ Branch 0 taken 12876 times.
✓ Branch 1 taken 21585 times.
|
34461 | if ((flags & 0xc0) == 0x80) { |
| 1310 | 12876 | pes->dts = pes->pts = ff_parse_pes_pts(r); | |
| 1311 | 12876 | r += 5; | |
| 1312 |
2/2✓ Branch 0 taken 3096 times.
✓ Branch 1 taken 18489 times.
|
21585 | } else if ((flags & 0xc0) == 0xc0) { |
| 1313 | 3096 | pes->pts = ff_parse_pes_pts(r); | |
| 1314 | 3096 | r += 5; | |
| 1315 | 3096 | pes->dts = ff_parse_pes_pts(r); | |
| 1316 | 3096 | r += 5; | |
| 1317 | } | ||
| 1318 | 34461 | pes->extended_stream_id = -1; | |
| 1319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | if (flags & 0x01) { /* PES extension */ |
| 1320 | ✗ | pes_ext = *r++; | |
| 1321 | /* Skip PES private data, program packet sequence counter and P-STD buffer */ | ||
| 1322 | ✗ | skip = (pes_ext >> 4) & 0xb; | |
| 1323 | ✗ | skip += skip & 0x9; | |
| 1324 | ✗ | r += skip; | |
| 1325 | ✗ | if ((pes_ext & 0x41) == 0x01 && | |
| 1326 | ✗ | (r + 2) <= (pes->header + pes->pes_header_size)) { | |
| 1327 | /* PES extension 2 */ | ||
| 1328 | ✗ | if ((r[0] & 0x7f) > 0 && (r[1] & 0x80) == 0) | |
| 1329 | ✗ | pes->extended_stream_id = r[1]; | |
| 1330 | } | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | /* we got the full header. We parse it and get the payload */ | ||
| 1334 | 34461 | pes->state = MPEGTS_PAYLOAD; | |
| 1335 | 34461 | pes->data_index = 0; | |
| 1336 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
34461 | if (pes->stream_type == STREAM_TYPE_ISO_IEC_14496_PES && buf_size > 0) { |
| 1337 | ✗ | int sl_header_bytes = read_sl_header(pes, &pes->sl, p, | |
| 1338 | buf_size); | ||
| 1339 | ✗ | pes->pes_header_size += sl_header_bytes; | |
| 1340 | ✗ | p += sl_header_bytes; | |
| 1341 | ✗ | buf_size -= sl_header_bytes; | |
| 1342 | } | ||
| 1343 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 34455 times.
|
34461 | if (pes->stream_type == STREAM_TYPE_METADATA && |
| 1344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | pes->stream_id == STREAM_ID_METADATA_STREAM && |
| 1345 | ✗ | pes->st->codecpar->codec_id == AV_CODEC_ID_SMPTE_KLV && | |
| 1346 | buf_size >= 5) { | ||
| 1347 | /* skip metadata access unit header - see MISB ST 1402 */ | ||
| 1348 | ✗ | pes->pes_header_size += 5; | |
| 1349 | ✗ | p += 5; | |
| 1350 | ✗ | buf_size -= 5; | |
| 1351 | } | ||
| 1352 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | if ( pes->ts->fix_teletext_pts |
| 1353 |
1/2✓ Branch 0 taken 34461 times.
✗ Branch 1 not taken.
|
34461 | && ( pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT |
| 1354 |
2/2✓ Branch 0 taken 254 times.
✓ Branch 1 taken 34207 times.
|
34461 | || pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE) |
| 1355 | ) { | ||
| 1356 | 254 | AVProgram *p = NULL; | |
| 1357 | 254 | int pcr_found = 0; | |
| 1358 |
2/2✓ Branch 1 taken 254 times.
✓ Branch 2 taken 254 times.
|
508 | while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) { |
| 1359 |
2/4✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 254 times.
✗ Branch 3 not taken.
|
254 | if (p->pcr_pid != -1 && p->discard != AVDISCARD_ALL) { |
| 1360 | 254 | MpegTSFilter *f = pes->ts->pids[p->pcr_pid]; | |
| 1361 |
1/2✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
|
254 | if (f) { |
| 1362 | 254 | AVStream *st = NULL; | |
| 1363 |
1/2✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
|
254 | if (f->type == MPEGTS_PES) { |
| 1364 | 254 | PESContext *pcrpes = f->u.pes_filter.opaque; | |
| 1365 |
1/2✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
|
254 | if (pcrpes) |
| 1366 | 254 | st = pcrpes->st; | |
| 1367 | ✗ | } else if (f->type == MPEGTS_PCR) { | |
| 1368 | int i; | ||
| 1369 | ✗ | for (i = 0; i < p->nb_stream_indexes; i++) { | |
| 1370 | ✗ | AVStream *pst = pes->stream->streams[p->stream_index[i]]; | |
| 1371 | ✗ | if (pst->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) | |
| 1372 | ✗ | st = pst; | |
| 1373 | } | ||
| 1374 | } | ||
| 1375 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 254 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
254 | if (f->last_pcr != -1 && !f->discard) { |
| 1376 | // teletext packets do not always have correct timestamps, | ||
| 1377 | // the standard says they should be handled after 40.6 ms at most, | ||
| 1378 | // and the pcr error to this packet should be no more than 100 ms. | ||
| 1379 | // TODO: we should interpolate the PCR, not just use the last one | ||
| 1380 | ✗ | int64_t pcr = f->last_pcr / SYSTEM_CLOCK_FREQUENCY_DIVISOR; | |
| 1381 | ✗ | pcr_found = 1; | |
| 1382 | ✗ | if (st) { | |
| 1383 | ✗ | const FFStream *const sti = ffstream(st); | |
| 1384 | ✗ | FFStream *const pes_sti = ffstream(pes->st); | |
| 1385 | |||
| 1386 | ✗ | pes_sti->pts_wrap_reference = sti->pts_wrap_reference; | |
| 1387 | ✗ | pes_sti->pts_wrap_behavior = sti->pts_wrap_behavior; | |
| 1388 | } | ||
| 1389 | ✗ | if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) { | |
| 1390 | ✗ | pes->pts = pes->dts = pcr; | |
| 1391 | ✗ | } else if (pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT && | |
| 1392 | ✗ | pes->dts > pcr + 3654 + 9000) { | |
| 1393 | ✗ | pes->pts = pes->dts = pcr + 3654 + 9000; | |
| 1394 | ✗ | } else if (pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE && | |
| 1395 | ✗ | pes->dts > pcr + 10*90000) { //10sec | |
| 1396 | ✗ | pes->pts = pes->dts = pcr + 3654 + 9000; | |
| 1397 | } | ||
| 1398 | ✗ | break; | |
| 1399 | } | ||
| 1400 | } | ||
| 1401 | } | ||
| 1402 | } | ||
| 1403 | |||
| 1404 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 254 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
254 | if (pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT && |
| 1405 | !pcr_found) { | ||
| 1406 | ✗ | av_log(pes->stream, AV_LOG_VERBOSE, | |
| 1407 | "Forcing DTS/PTS to be unset for a " | ||
| 1408 | "non-trustworthy PES packet for PID %d as " | ||
| 1409 | "PCR hasn't been received yet.\n", | ||
| 1410 | pes->pid); | ||
| 1411 | ✗ | pes->dts = pes->pts = AV_NOPTS_VALUE; | |
| 1412 | } | ||
| 1413 | } | ||
| 1414 | } | ||
| 1415 | 34461 | break; | |
| 1416 | 410354 | case MPEGTS_PAYLOAD: | |
| 1417 | do { | ||
| 1418 | 410354 | int max_packet_size = ts->max_packet_size; | |
| 1419 |
3/4✓ Branch 0 taken 233124 times.
✓ Branch 1 taken 177230 times.
✓ Branch 2 taken 233124 times.
✗ Branch 3 not taken.
|
410354 | if (pes->PES_packet_length && pes->PES_packet_length + PES_START_SIZE > pes->pes_header_size) |
| 1420 | 233124 | max_packet_size = pes->PES_packet_length + PES_START_SIZE - pes->pes_header_size; | |
| 1421 | |||
| 1422 |
2/2✓ Branch 0 taken 375893 times.
✓ Branch 1 taken 34461 times.
|
410354 | if (pes->data_index > 0 && |
| 1423 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 375893 times.
|
375893 | pes->data_index + buf_size > max_packet_size) { |
| 1424 | ✗ | ret = new_pes_packet(pes, ts->pkt); | |
| 1425 | ✗ | if (ret < 0) | |
| 1426 | ✗ | return ret; | |
| 1427 | ✗ | pes->PES_packet_length = 0; | |
| 1428 | ✗ | max_packet_size = ts->max_packet_size; | |
| 1429 | ✗ | ts->stop_parse = 1; | |
| 1430 |
3/4✓ Branch 0 taken 34461 times.
✓ Branch 1 taken 375893 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34461 times.
|
410354 | } else if (pes->data_index == 0 && |
| 1431 | buf_size > max_packet_size) { | ||
| 1432 | // pes packet size is < ts size packet and pes data is padded with STUFFING_BYTE | ||
| 1433 | // not sure if this is legal in ts but see issue #2392 | ||
| 1434 | ✗ | buf_size = max_packet_size; | |
| 1435 | } | ||
| 1436 | |||
| 1437 |
2/2✓ Branch 0 taken 34461 times.
✓ Branch 1 taken 375893 times.
|
410354 | if (!pes->buffer) { |
| 1438 | 34461 | pes->buffer = buffer_pool_get(ts, max_packet_size); | |
| 1439 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34461 times.
|
34461 | if (!pes->buffer) |
| 1440 | ✗ | return AVERROR(ENOMEM); | |
| 1441 | } | ||
| 1442 | |||
| 1443 | 410354 | memcpy(pes->buffer->data + pes->data_index, p, buf_size); | |
| 1444 | 410354 | pes->data_index += buf_size; | |
| 1445 | /* emit complete packets with known packet size | ||
| 1446 | * decreases demuxer delay for infrequent packets like subtitles from | ||
| 1447 | * a couple of seconds to milliseconds for properly muxed files. */ | ||
| 1448 |
4/4✓ Branch 0 taken 405843 times.
✓ Branch 1 taken 4511 times.
✓ Branch 2 taken 233124 times.
✓ Branch 3 taken 172719 times.
|
410354 | if (!ts->stop_parse && pes->PES_packet_length && |
| 1449 |
2/2✓ Branch 0 taken 29633 times.
✓ Branch 1 taken 203491 times.
|
233124 | pes->pes_header_size + pes->data_index == pes->PES_packet_length + PES_START_SIZE) { |
| 1450 | 29633 | ts->stop_parse = 1; | |
| 1451 | 29633 | ret = new_pes_packet(pes, ts->pkt); | |
| 1452 | 29633 | pes->state = MPEGTS_SKIP; | |
| 1453 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29633 times.
|
29633 | if (ret < 0) |
| 1454 | ✗ | return ret; | |
| 1455 | } | ||
| 1456 | } while (0); | ||
| 1457 | 410354 | buf_size = 0; | |
| 1458 | 410354 | break; | |
| 1459 | 18633 | case MPEGTS_SKIP: | |
| 1460 | 18633 | buf_size = 0; | |
| 1461 | 18633 | break; | |
| 1462 | } | ||
| 1463 | } | ||
| 1464 | |||
| 1465 | 428989 | return 0; | |
| 1466 | } | ||
| 1467 | |||
| 1468 | 154 | static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid) | |
| 1469 | { | ||
| 1470 | MpegTSFilter *tss; | ||
| 1471 | PESContext *pes; | ||
| 1472 | |||
| 1473 | /* if no pid found, then add a pid context */ | ||
| 1474 | 154 | pes = av_mallocz(sizeof(PESContext)); | |
| 1475 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
|
154 | if (!pes) |
| 1476 | ✗ | return 0; | |
| 1477 | 154 | pes->ts = ts; | |
| 1478 | 154 | pes->stream = ts->stream; | |
| 1479 | 154 | pes->pid = pid; | |
| 1480 | 154 | pes->pcr_pid = pcr_pid; | |
| 1481 | 154 | pes->state = MPEGTS_SKIP; | |
| 1482 | 154 | pes->pts = AV_NOPTS_VALUE; | |
| 1483 | 154 | pes->dts = AV_NOPTS_VALUE; | |
| 1484 | 154 | tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); | |
| 1485 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
|
154 | if (!tss) { |
| 1486 | ✗ | av_free(pes); | |
| 1487 | ✗ | return 0; | |
| 1488 | } | ||
| 1489 | 154 | return pes; | |
| 1490 | } | ||
| 1491 | |||
| 1492 | #define MAX_LEVEL 4 | ||
| 1493 | typedef struct MP4DescrParseContext { | ||
| 1494 | AVFormatContext *s; | ||
| 1495 | FFIOContext pb; | ||
| 1496 | Mp4Descr *descr; | ||
| 1497 | Mp4Descr *active_descr; | ||
| 1498 | int descr_count; | ||
| 1499 | int max_descr_count; | ||
| 1500 | int level; | ||
| 1501 | int predefined_SLConfigDescriptor_seen; | ||
| 1502 | } MP4DescrParseContext; | ||
| 1503 | |||
| 1504 | ✗ | static int init_MP4DescrParseContext(MP4DescrParseContext *d, AVFormatContext *s, | |
| 1505 | const uint8_t *buf, unsigned size, | ||
| 1506 | Mp4Descr *descr, int max_descr_count) | ||
| 1507 | { | ||
| 1508 | ✗ | if (size > (1 << 30)) | |
| 1509 | ✗ | return AVERROR_INVALIDDATA; | |
| 1510 | |||
| 1511 | ✗ | ffio_init_read_context(&d->pb, buf, size); | |
| 1512 | |||
| 1513 | ✗ | d->s = s; | |
| 1514 | ✗ | d->level = 0; | |
| 1515 | ✗ | d->descr_count = 0; | |
| 1516 | ✗ | d->descr = descr; | |
| 1517 | ✗ | d->active_descr = NULL; | |
| 1518 | ✗ | d->max_descr_count = max_descr_count; | |
| 1519 | |||
| 1520 | ✗ | return 0; | |
| 1521 | } | ||
| 1522 | |||
| 1523 | ✗ | static void update_offsets(AVIOContext *pb, int64_t *off, int *len) | |
| 1524 | { | ||
| 1525 | ✗ | int64_t new_off = avio_tell(pb); | |
| 1526 | ✗ | (*len) -= new_off - *off; | |
| 1527 | ✗ | *off = new_off; | |
| 1528 | ✗ | } | |
| 1529 | |||
| 1530 | static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, | ||
| 1531 | int target_tag); | ||
| 1532 | |||
| 1533 | ✗ | static int parse_mp4_descr_arr(MP4DescrParseContext *d, int64_t off, int len) | |
| 1534 | { | ||
| 1535 | ✗ | while (len > 0) { | |
| 1536 | ✗ | int ret = parse_mp4_descr(d, off, len, 0); | |
| 1537 | ✗ | if (ret < 0) | |
| 1538 | ✗ | return ret; | |
| 1539 | ✗ | update_offsets(&d->pb.pub, &off, &len); | |
| 1540 | } | ||
| 1541 | ✗ | return 0; | |
| 1542 | } | ||
| 1543 | |||
| 1544 | ✗ | static int parse_MP4IODescrTag(MP4DescrParseContext *d, int64_t off, int len) | |
| 1545 | { | ||
| 1546 | ✗ | AVIOContext *const pb = &d->pb.pub; | |
| 1547 | ✗ | avio_rb16(pb); // ID | |
| 1548 | ✗ | avio_r8(pb); | |
| 1549 | ✗ | avio_r8(pb); | |
| 1550 | ✗ | avio_r8(pb); | |
| 1551 | ✗ | avio_r8(pb); | |
| 1552 | ✗ | avio_r8(pb); | |
| 1553 | ✗ | update_offsets(pb, &off, &len); | |
| 1554 | ✗ | return parse_mp4_descr_arr(d, off, len); | |
| 1555 | } | ||
| 1556 | |||
| 1557 | ✗ | static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len) | |
| 1558 | { | ||
| 1559 | int id_flags; | ||
| 1560 | ✗ | if (len < 2) | |
| 1561 | ✗ | return 0; | |
| 1562 | ✗ | id_flags = avio_rb16(&d->pb.pub); | |
| 1563 | ✗ | if (!(id_flags & 0x0020)) { // URL_Flag | |
| 1564 | ✗ | update_offsets(&d->pb.pub, &off, &len); | |
| 1565 | ✗ | return parse_mp4_descr_arr(d, off, len); // ES_Descriptor[] | |
| 1566 | } else { | ||
| 1567 | ✗ | return 0; | |
| 1568 | } | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | ✗ | static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len) | |
| 1572 | { | ||
| 1573 | ✗ | AVIOContext *const pb = &d->pb.pub; | |
| 1574 | ✗ | int es_id = 0; | |
| 1575 | ✗ | int ret = 0; | |
| 1576 | |||
| 1577 | ✗ | if (d->descr_count >= d->max_descr_count) | |
| 1578 | ✗ | return AVERROR_INVALIDDATA; | |
| 1579 | ✗ | ff_mp4_parse_es_descr(pb, &es_id); | |
| 1580 | ✗ | d->active_descr = d->descr + (d->descr_count++); | |
| 1581 | |||
| 1582 | ✗ | d->active_descr->es_id = es_id; | |
| 1583 | ✗ | update_offsets(pb, &off, &len); | |
| 1584 | ✗ | if ((ret = parse_mp4_descr(d, off, len, MP4DecConfigDescrTag)) < 0) | |
| 1585 | ✗ | return ret; | |
| 1586 | ✗ | update_offsets(pb, &off, &len); | |
| 1587 | ✗ | if (len > 0) | |
| 1588 | ✗ | ret = parse_mp4_descr(d, off, len, MP4SLDescrTag); | |
| 1589 | ✗ | d->active_descr = NULL; | |
| 1590 | ✗ | return ret; | |
| 1591 | } | ||
| 1592 | |||
| 1593 | ✗ | static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off, | |
| 1594 | int len) | ||
| 1595 | { | ||
| 1596 | ✗ | Mp4Descr *descr = d->active_descr; | |
| 1597 | ✗ | if (!descr) | |
| 1598 | ✗ | return AVERROR_INVALIDDATA; | |
| 1599 | ✗ | d->active_descr->dec_config_descr = av_malloc(len); | |
| 1600 | ✗ | if (!descr->dec_config_descr) | |
| 1601 | ✗ | return AVERROR(ENOMEM); | |
| 1602 | ✗ | descr->dec_config_descr_len = len; | |
| 1603 | ✗ | avio_read(&d->pb.pub, descr->dec_config_descr, len); | |
| 1604 | ✗ | return 0; | |
| 1605 | } | ||
| 1606 | |||
| 1607 | ✗ | static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len) | |
| 1608 | { | ||
| 1609 | ✗ | Mp4Descr *descr = d->active_descr; | |
| 1610 | ✗ | AVIOContext *const pb = &d->pb.pub; | |
| 1611 | int predefined; | ||
| 1612 | ✗ | if (!descr) | |
| 1613 | ✗ | return AVERROR_INVALIDDATA; | |
| 1614 | |||
| 1615 | #define R8_CHECK_CLIP_MAX(dst, maxv) do { \ | ||
| 1616 | descr->sl.dst = avio_r8(pb); \ | ||
| 1617 | if (descr->sl.dst > maxv) { \ | ||
| 1618 | descr->sl.dst = maxv; \ | ||
| 1619 | return AVERROR_INVALIDDATA; \ | ||
| 1620 | } \ | ||
| 1621 | } while (0) | ||
| 1622 | |||
| 1623 | ✗ | predefined = avio_r8(pb); | |
| 1624 | ✗ | if (!predefined) { | |
| 1625 | int lengths; | ||
| 1626 | ✗ | int flags = avio_r8(pb); | |
| 1627 | ✗ | descr->sl.use_au_start = !!(flags & 0x80); | |
| 1628 | ✗ | descr->sl.use_au_end = !!(flags & 0x40); | |
| 1629 | ✗ | descr->sl.use_rand_acc_pt = !!(flags & 0x20); | |
| 1630 | ✗ | descr->sl.use_padding = !!(flags & 0x08); | |
| 1631 | ✗ | descr->sl.use_timestamps = !!(flags & 0x04); | |
| 1632 | ✗ | descr->sl.use_idle = !!(flags & 0x02); | |
| 1633 | ✗ | descr->sl.timestamp_res = avio_rb32(pb); | |
| 1634 | ✗ | avio_rb32(pb); | |
| 1635 | ✗ | R8_CHECK_CLIP_MAX(timestamp_len, 63); | |
| 1636 | ✗ | R8_CHECK_CLIP_MAX(ocr_len, 63); | |
| 1637 | ✗ | R8_CHECK_CLIP_MAX(au_len, 31); | |
| 1638 | ✗ | descr->sl.inst_bitrate_len = avio_r8(pb); | |
| 1639 | ✗ | lengths = avio_rb16(pb); | |
| 1640 | ✗ | descr->sl.degr_prior_len = lengths >> 12; | |
| 1641 | ✗ | descr->sl.au_seq_num_len = (lengths >> 7) & 0x1f; | |
| 1642 | ✗ | descr->sl.packet_seq_num_len = (lengths >> 2) & 0x1f; | |
| 1643 | ✗ | } else if (!d->predefined_SLConfigDescriptor_seen){ | |
| 1644 | ✗ | avpriv_report_missing_feature(d->s, "Predefined SLConfigDescriptor"); | |
| 1645 | ✗ | d->predefined_SLConfigDescriptor_seen = 1; | |
| 1646 | } | ||
| 1647 | ✗ | return 0; | |
| 1648 | } | ||
| 1649 | |||
| 1650 | ✗ | static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, | |
| 1651 | int target_tag) | ||
| 1652 | { | ||
| 1653 | int tag; | ||
| 1654 | ✗ | AVIOContext *const pb = &d->pb.pub; | |
| 1655 | ✗ | int len1 = ff_mp4_read_descr(d->s, pb, &tag); | |
| 1656 | ✗ | int ret = 0; | |
| 1657 | |||
| 1658 | ✗ | update_offsets(pb, &off, &len); | |
| 1659 | ✗ | if (len < 0 || len1 > len || len1 <= 0) { | |
| 1660 | ✗ | av_log(d->s, AV_LOG_ERROR, | |
| 1661 | "Tag %x length violation new length %d bytes remaining %d\n", | ||
| 1662 | tag, len1, len); | ||
| 1663 | ✗ | return AVERROR_INVALIDDATA; | |
| 1664 | } | ||
| 1665 | |||
| 1666 | ✗ | if (d->level++ >= MAX_LEVEL) { | |
| 1667 | ✗ | av_log(d->s, AV_LOG_ERROR, "Maximum MP4 descriptor level exceeded\n"); | |
| 1668 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 1669 | ✗ | goto done; | |
| 1670 | } | ||
| 1671 | |||
| 1672 | ✗ | if (target_tag && tag != target_tag) { | |
| 1673 | ✗ | av_log(d->s, AV_LOG_ERROR, "Found tag %x expected %x\n", tag, | |
| 1674 | target_tag); | ||
| 1675 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 1676 | ✗ | goto done; | |
| 1677 | } | ||
| 1678 | |||
| 1679 | ✗ | switch (tag) { | |
| 1680 | ✗ | case MP4IODescrTag: | |
| 1681 | ✗ | ret = parse_MP4IODescrTag(d, off, len1); | |
| 1682 | ✗ | break; | |
| 1683 | ✗ | case MP4ODescrTag: | |
| 1684 | ✗ | ret = parse_MP4ODescrTag(d, off, len1); | |
| 1685 | ✗ | break; | |
| 1686 | ✗ | case MP4ESDescrTag: | |
| 1687 | ✗ | ret = parse_MP4ESDescrTag(d, off, len1); | |
| 1688 | ✗ | break; | |
| 1689 | ✗ | case MP4DecConfigDescrTag: | |
| 1690 | ✗ | ret = parse_MP4DecConfigDescrTag(d, off, len1); | |
| 1691 | ✗ | break; | |
| 1692 | ✗ | case MP4SLDescrTag: | |
| 1693 | ✗ | ret = parse_MP4SLDescrTag(d, off, len1); | |
| 1694 | ✗ | break; | |
| 1695 | } | ||
| 1696 | |||
| 1697 | |||
| 1698 | ✗ | done: | |
| 1699 | ✗ | d->level--; | |
| 1700 | ✗ | avio_seek(pb, off + len1, SEEK_SET); | |
| 1701 | ✗ | return ret; | |
| 1702 | } | ||
| 1703 | |||
| 1704 | ✗ | static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size, | |
| 1705 | Mp4Descr *descr, int *descr_count, int max_descr_count) | ||
| 1706 | { | ||
| 1707 | MP4DescrParseContext d; | ||
| 1708 | int ret; | ||
| 1709 | |||
| 1710 | ✗ | d.predefined_SLConfigDescriptor_seen = 0; | |
| 1711 | |||
| 1712 | ✗ | ret = init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count); | |
| 1713 | ✗ | if (ret < 0) | |
| 1714 | ✗ | return ret; | |
| 1715 | |||
| 1716 | ✗ | ret = parse_mp4_descr(&d, avio_tell(&d.pb.pub), size, MP4IODescrTag); | |
| 1717 | |||
| 1718 | ✗ | *descr_count += d.descr_count; | |
| 1719 | ✗ | return ret; | |
| 1720 | } | ||
| 1721 | |||
| 1722 | ✗ | static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size, | |
| 1723 | Mp4Descr *descr, int *descr_count, int max_descr_count) | ||
| 1724 | { | ||
| 1725 | MP4DescrParseContext d; | ||
| 1726 | int ret; | ||
| 1727 | |||
| 1728 | ✗ | ret = init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count); | |
| 1729 | ✗ | if (ret < 0) | |
| 1730 | ✗ | return ret; | |
| 1731 | |||
| 1732 | ✗ | ret = parse_mp4_descr_arr(&d, avio_tell(&d.pb.pub), size); | |
| 1733 | |||
| 1734 | ✗ | *descr_count = d.descr_count; | |
| 1735 | ✗ | return ret; | |
| 1736 | } | ||
| 1737 | |||
| 1738 | ✗ | static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, | |
| 1739 | int section_len) | ||
| 1740 | { | ||
| 1741 | ✗ | MpegTSContext *ts = filter->u.section_filter.opaque; | |
| 1742 | ✗ | MpegTSSectionFilter *tssf = &filter->u.section_filter; | |
| 1743 | SectionHeader h; | ||
| 1744 | const uint8_t *p, *p_end; | ||
| 1745 | ✗ | int mp4_descr_count = 0; | |
| 1746 | ✗ | Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } }; | |
| 1747 | int i, pid; | ||
| 1748 | ✗ | AVFormatContext *s = ts->stream; | |
| 1749 | |||
| 1750 | ✗ | p_end = section + section_len - 4; | |
| 1751 | ✗ | p = section; | |
| 1752 | ✗ | if (parse_section_header(&h, &p, p_end) < 0) | |
| 1753 | ✗ | return; | |
| 1754 | ✗ | if (h.tid != M4OD_TID) | |
| 1755 | ✗ | return; | |
| 1756 | ✗ | if (skip_identical(&h, tssf)) | |
| 1757 | ✗ | return; | |
| 1758 | |||
| 1759 | ✗ | mp4_read_od(s, p, (unsigned) (p_end - p), mp4_descr, &mp4_descr_count, | |
| 1760 | MAX_MP4_DESCR_COUNT); | ||
| 1761 | |||
| 1762 | ✗ | for (pid = 0; pid < NB_PID_MAX; pid++) { | |
| 1763 | ✗ | if (!ts->pids[pid]) | |
| 1764 | ✗ | continue; | |
| 1765 | ✗ | for (i = 0; i < mp4_descr_count; i++) { | |
| 1766 | PESContext *pes; | ||
| 1767 | AVStream *st; | ||
| 1768 | FFStream *sti; | ||
| 1769 | FFIOContext pb; | ||
| 1770 | ✗ | if (ts->pids[pid]->es_id != mp4_descr[i].es_id) | |
| 1771 | ✗ | continue; | |
| 1772 | ✗ | if (ts->pids[pid]->type != MPEGTS_PES) { | |
| 1773 | ✗ | av_log(s, AV_LOG_ERROR, "pid %x is not PES\n", pid); | |
| 1774 | ✗ | continue; | |
| 1775 | } | ||
| 1776 | ✗ | pes = ts->pids[pid]->u.pes_filter.opaque; | |
| 1777 | ✗ | st = pes->st; | |
| 1778 | ✗ | if (!st) | |
| 1779 | ✗ | continue; | |
| 1780 | ✗ | sti = ffstream(st); | |
| 1781 | |||
| 1782 | ✗ | pes->sl = mp4_descr[i].sl; | |
| 1783 | |||
| 1784 | ✗ | ffio_init_read_context(&pb, mp4_descr[i].dec_config_descr, | |
| 1785 | mp4_descr[i].dec_config_descr_len); | ||
| 1786 | ✗ | ff_mp4_read_dec_config_descr(s, st, &pb.pub); | |
| 1787 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_AAC && | |
| 1788 | ✗ | st->codecpar->extradata_size > 0) | |
| 1789 | ✗ | sti->need_parsing = 0; | |
| 1790 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_H264 && | |
| 1791 | ✗ | st->codecpar->extradata_size > 0) | |
| 1792 | ✗ | sti->need_parsing = 0; | |
| 1793 | |||
| 1794 | ✗ | st->codecpar->codec_type = avcodec_get_type(st->codecpar->codec_id); | |
| 1795 | ✗ | sti->need_context_update = 1; | |
| 1796 | } | ||
| 1797 | } | ||
| 1798 | ✗ | for (i = 0; i < mp4_descr_count; i++) | |
| 1799 | ✗ | av_free(mp4_descr[i].dec_config_descr); | |
| 1800 | } | ||
| 1801 | |||
| 1802 | ✗ | static void scte_data_cb(MpegTSFilter *filter, const uint8_t *section, | |
| 1803 | int section_len) | ||
| 1804 | { | ||
| 1805 | ✗ | AVProgram *prg = NULL; | |
| 1806 | ✗ | MpegTSContext *ts = filter->u.section_filter.opaque; | |
| 1807 | |||
| 1808 | ✗ | int idx = ff_find_stream_index(ts->stream, filter->pid); | |
| 1809 | ✗ | if (idx < 0) | |
| 1810 | ✗ | return; | |
| 1811 | |||
| 1812 | /** | ||
| 1813 | * In case we receive an SCTE-35 packet before mpegts context is fully | ||
| 1814 | * initialized. | ||
| 1815 | */ | ||
| 1816 | ✗ | if (!ts->pkt) | |
| 1817 | ✗ | return; | |
| 1818 | |||
| 1819 | ✗ | new_data_packet(section, section_len, ts->pkt); | |
| 1820 | ✗ | ts->pkt->stream_index = idx; | |
| 1821 | ✗ | prg = av_find_program_from_stream(ts->stream, NULL, idx); | |
| 1822 | ✗ | if (prg && prg->pcr_pid != -1 && prg->discard != AVDISCARD_ALL) { | |
| 1823 | ✗ | MpegTSFilter *f = ts->pids[prg->pcr_pid]; | |
| 1824 | ✗ | if (f && f->last_pcr != -1) | |
| 1825 | ✗ | ts->pkt->pts = ts->pkt->dts = f->last_pcr/SYSTEM_CLOCK_FREQUENCY_DIVISOR; | |
| 1826 | } | ||
| 1827 | ✗ | ts->stop_parse = 1; | |
| 1828 | |||
| 1829 | } | ||
| 1830 | |||
| 1831 | static const uint8_t opus_coupled_stream_cnt[9] = { | ||
| 1832 | 1, 0, 1, 1, 2, 2, 2, 3, 3 | ||
| 1833 | }; | ||
| 1834 | |||
| 1835 | static const uint8_t opus_stream_cnt[9] = { | ||
| 1836 | 1, 1, 1, 2, 2, 3, 4, 4, 5, | ||
| 1837 | }; | ||
| 1838 | |||
| 1839 | static const uint8_t opus_channel_map[8][8] = { | ||
| 1840 | { 0 }, | ||
| 1841 | { 0,1 }, | ||
| 1842 | { 0,2,1 }, | ||
| 1843 | { 0,1,2,3 }, | ||
| 1844 | { 0,4,1,2,3 }, | ||
| 1845 | { 0,4,1,2,3,5 }, | ||
| 1846 | { 0,4,1,2,3,5,6 }, | ||
| 1847 | { 0,6,1,2,3,4,5,7 }, | ||
| 1848 | }; | ||
| 1849 | |||
| 1850 | 90 | static int parse_mpeg2_extension_descriptor(AVFormatContext *fc, AVStream *st, int prg_id, | |
| 1851 | const uint8_t **pp, const uint8_t *desc_end) | ||
| 1852 | { | ||
| 1853 | 90 | MpegTSContext *ts = fc->priv_data; | |
| 1854 | 90 | int ext_tag = get8(pp, desc_end); | |
| 1855 | |||
| 1856 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
|
90 | switch (ext_tag) { |
| 1857 | ✗ | case JXS_VIDEO_DESCRIPTOR: /* JPEG-XS video descriptor*/ | |
| 1858 | { | ||
| 1859 | int horizontal_size, vertical_size, schar; | ||
| 1860 | int colour_primaries, transfer_characteristics, matrix_coefficients, video_full_range_flag; | ||
| 1861 | int descriptor_version, interlace_mode, n_fields; | ||
| 1862 | unsigned frat; | ||
| 1863 | |||
| 1864 | ✗ | if (desc_end - *pp < 29) | |
| 1865 | ✗ | return AVERROR_INVALIDDATA; | |
| 1866 | |||
| 1867 | ✗ | descriptor_version = get8(pp, desc_end); | |
| 1868 | ✗ | if (descriptor_version) { | |
| 1869 | ✗ | av_log(fc, AV_LOG_WARNING, "Unsupported JPEG-XS descriptor version (%d != 0)", descriptor_version); | |
| 1870 | ✗ | return AVERROR_INVALIDDATA; | |
| 1871 | } | ||
| 1872 | |||
| 1873 | ✗ | horizontal_size = get16(pp, desc_end); | |
| 1874 | ✗ | vertical_size = get16(pp, desc_end); | |
| 1875 | ✗ | *pp += 4; /* brat */ | |
| 1876 | ✗ | frat = bytestream_get_be32(pp); | |
| 1877 | ✗ | schar = get16(pp, desc_end); | |
| 1878 | ✗ | *pp += 2; /* Ppih */ | |
| 1879 | ✗ | *pp += 2; /* Plev */ | |
| 1880 | ✗ | *pp += 4; /* max_buffer_size */ | |
| 1881 | ✗ | *pp += 1; /* buffer_model_type */ | |
| 1882 | ✗ | colour_primaries = get8(pp, desc_end); | |
| 1883 | ✗ | transfer_characteristics = get8(pp, desc_end); | |
| 1884 | ✗ | matrix_coefficients = get8(pp, desc_end); | |
| 1885 | ✗ | video_full_range_flag = (get8(pp, desc_end) & 0x80) == 0x80 ? 1 : 0; | |
| 1886 | |||
| 1887 | ✗ | interlace_mode = (frat >> 30) & 0x3; | |
| 1888 | ✗ | if (interlace_mode == 3) { | |
| 1889 | ✗ | av_log(fc, AV_LOG_WARNING, "Unknown JPEG XS interlace mode 3"); | |
| 1890 | ✗ | return AVERROR_INVALIDDATA; | |
| 1891 | } | ||
| 1892 | |||
| 1893 | ✗ | st->codecpar->field_order = interlace_mode == 0 ? AV_FIELD_PROGRESSIVE | |
| 1894 | ✗ | : (interlace_mode == 1 ? AV_FIELD_TT : AV_FIELD_BB); | |
| 1895 | ✗ | n_fields = st->codecpar->field_order == AV_FIELD_PROGRESSIVE ? 1 : 2; | |
| 1896 | |||
| 1897 | ✗ | st->codecpar->width = horizontal_size; | |
| 1898 | ✗ | st->codecpar->height = vertical_size * n_fields; | |
| 1899 | |||
| 1900 | ✗ | if (frat != 0) { | |
| 1901 | ✗ | int framerate_num = (frat & 0x0000FFFFU); | |
| 1902 | ✗ | int framerate_den = ((frat >> 24) & 0x0000003FU); | |
| 1903 | |||
| 1904 | ✗ | if (framerate_den == 2) { | |
| 1905 | ✗ | framerate_num *= 1000; | |
| 1906 | ✗ | framerate_den = 1001; | |
| 1907 | ✗ | } else if (framerate_den != 1) { | |
| 1908 | ✗ | av_log(fc, AV_LOG_WARNING, "Unknown JPEG XS framerate denominator code %u", framerate_den); | |
| 1909 | ✗ | return AVERROR_INVALIDDATA; | |
| 1910 | } | ||
| 1911 | |||
| 1912 | ✗ | st->codecpar->framerate.num = framerate_num; | |
| 1913 | ✗ | st->codecpar->framerate.den = framerate_den; | |
| 1914 | } | ||
| 1915 | |||
| 1916 | ✗ | switch (schar & 0xf) { | |
| 1917 | ✗ | case 0: st->codecpar->format = AV_PIX_FMT_YUV422P10LE; break; | |
| 1918 | ✗ | case 1: st->codecpar->format = AV_PIX_FMT_YUV444P10LE; break; | |
| 1919 | ✗ | default: | |
| 1920 | ✗ | av_log(fc, AV_LOG_WARNING, "Unknown JPEG XS sampling format"); | |
| 1921 | ✗ | break; | |
| 1922 | } | ||
| 1923 | |||
| 1924 | ✗ | st->codecpar->color_range = video_full_range_flag ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; | |
| 1925 | ✗ | st->codecpar->color_primaries = colour_primaries; | |
| 1926 | ✗ | st->codecpar->color_trc = transfer_characteristics; | |
| 1927 | ✗ | st->codecpar->color_space = matrix_coefficients; | |
| 1928 | } | ||
| 1929 | ✗ | break; | |
| 1930 | 45 | case LCEVC_VIDEO_DESCRIPTOR: | |
| 1931 | { | ||
| 1932 | 45 | struct Program *p = get_program(ts, prg_id); | |
| 1933 | struct StreamGroup *stg; | ||
| 1934 | 45 | int lcevc_stream_tag = get8(pp, desc_end); | |
| 1935 | int i; | ||
| 1936 | |||
| 1937 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (!p) |
| 1938 | ✗ | return 0; | |
| 1939 | |||
| 1940 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 21 times.
|
45 | if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC) |
| 1941 | 24 | return AVERROR_INVALIDDATA; | |
| 1942 | |||
| 1943 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | for (i = 0; i < p->nb_stream_groups; i++) { |
| 1944 | 21 | stg = &p->stream_groups[i]; | |
| 1945 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC) |
| 1946 | ✗ | continue; | |
| 1947 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | if (stg->id == lcevc_stream_tag) |
| 1948 | 21 | break; | |
| 1949 | } | ||
| 1950 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | if (i == p->nb_stream_groups) { |
| 1951 | ✗ | if (p->nb_stream_groups == MAX_STREAMS_PER_PROGRAM) | |
| 1952 | ✗ | return AVERROR(EINVAL); | |
| 1953 | ✗ | p->nb_stream_groups++; | |
| 1954 | } | ||
| 1955 | |||
| 1956 | 21 | stg = &p->stream_groups[i]; | |
| 1957 | 21 | stg->id = lcevc_stream_tag; | |
| 1958 | 21 | stg->type = AV_STREAM_GROUP_PARAMS_LCEVC; | |
| 1959 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 21 times.
|
42 | for (i = 0; i < stg->nb_streams; i++) { |
| 1960 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | if (stg->streams[i]->codecpar->codec_id == AV_CODEC_ID_LCEVC) |
| 1961 | ✗ | break; | |
| 1962 | } | ||
| 1963 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | if (i == stg->nb_streams) { |
| 1964 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | if (stg->nb_streams == MAX_STREAMS_PER_PROGRAM) |
| 1965 | ✗ | return AVERROR(EINVAL); | |
| 1966 | 21 | stg->streams[stg->nb_streams++] = st; | |
| 1967 | } else | ||
| 1968 | ✗ | stg->streams[i] = st; | |
| 1969 | |||
| 1970 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | av_assert0(i < stg->nb_streams); |
| 1971 | } | ||
| 1972 | 21 | break; | |
| 1973 | 45 | case LCEVC_LINKAGE_DESCRIPTOR: | |
| 1974 | { | ||
| 1975 | 45 | struct Program *p = get_program(ts, prg_id); | |
| 1976 | 45 | int num_lcevc_stream_tags = get8(pp, desc_end); | |
| 1977 | |||
| 1978 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (!p) |
| 1979 | ✗ | return 0; | |
| 1980 | |||
| 1981 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (st->codecpar->codec_id == AV_CODEC_ID_LCEVC) |
| 1982 | ✗ | return AVERROR_INVALIDDATA; | |
| 1983 | |||
| 1984 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 45 times.
|
90 | for (int i = 0; i < num_lcevc_stream_tags; i++) { |
| 1985 | 45 | struct StreamGroup *stg = NULL; | |
| 1986 | 45 | int lcevc_stream_tag = get8(pp, desc_end);; | |
| 1987 | int j; | ||
| 1988 | |||
| 1989 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | for (j = 0; j < p->nb_stream_groups; j++) { |
| 1990 | ✗ | stg = &p->stream_groups[j]; | |
| 1991 | ✗ | if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC) | |
| 1992 | ✗ | continue; | |
| 1993 | ✗ | if (stg->id == lcevc_stream_tag) | |
| 1994 | ✗ | break; | |
| 1995 | } | ||
| 1996 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | if (j == p->nb_stream_groups) { |
| 1997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (p->nb_stream_groups == MAX_STREAMS_PER_PROGRAM) |
| 1998 | ✗ | return AVERROR(EINVAL); | |
| 1999 | 45 | p->nb_stream_groups++; | |
| 2000 | } | ||
| 2001 | |||
| 2002 | 45 | stg = &p->stream_groups[j]; | |
| 2003 | 45 | stg->id = lcevc_stream_tag; | |
| 2004 | 45 | stg->type = AV_STREAM_GROUP_PARAMS_LCEVC; | |
| 2005 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | for (j = 0; j < stg->nb_streams; j++) { |
| 2006 | ✗ | if (stg->streams[j]->index == st->index) | |
| 2007 | ✗ | break; | |
| 2008 | } | ||
| 2009 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | if (j == stg->nb_streams) { |
| 2010 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (stg->nb_streams == MAX_STREAMS_PER_PROGRAM) |
| 2011 | ✗ | return AVERROR(EINVAL); | |
| 2012 | 45 | stg->streams[stg->nb_streams++] = st; | |
| 2013 | } | ||
| 2014 | } | ||
| 2015 | } | ||
| 2016 | 45 | break; | |
| 2017 | ✗ | default: | |
| 2018 | ✗ | break; | |
| 2019 | } | ||
| 2020 | |||
| 2021 | 66 | return 0; | |
| 2022 | } | ||
| 2023 | |||
| 2024 | 1149 | int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, int prg_id, | |
| 2025 | const uint8_t **pp, const uint8_t *desc_list_end, | ||
| 2026 | Mp4Descr *mp4_descr, int mp4_descr_count, int pid, | ||
| 2027 | MpegTSContext *ts) | ||
| 2028 | { | ||
| 2029 | 1149 | FFStream *const sti = ffstream(st); | |
| 2030 | const uint8_t *desc_end; | ||
| 2031 | int desc_len, desc_tag, desc_es_id, ext_desc_tag, channels, channel_config_code; | ||
| 2032 | char language[252]; | ||
| 2033 | int i; | ||
| 2034 | |||
| 2035 | 1149 | desc_tag = get8(pp, desc_list_end); | |
| 2036 |
2/2✓ Branch 0 taken 636 times.
✓ Branch 1 taken 513 times.
|
1149 | if (desc_tag < 0) |
| 2037 | 636 | return AVERROR_INVALIDDATA; | |
| 2038 | 513 | desc_len = get8(pp, desc_list_end); | |
| 2039 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 513 times.
|
513 | if (desc_len < 0) |
| 2040 | ✗ | return AVERROR_INVALIDDATA; | |
| 2041 | 513 | desc_end = *pp + desc_len; | |
| 2042 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 513 times.
|
513 | if (desc_end > desc_list_end) |
| 2043 | ✗ | return AVERROR_INVALIDDATA; | |
| 2044 | |||
| 2045 | 513 | av_log(fc, AV_LOG_TRACE, "tag: 0x%02x len=%d\n", desc_tag, desc_len); | |
| 2046 | |||
| 2047 |
6/6✓ Branch 0 taken 508 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 475 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 22 times.
|
513 | if ((st->codecpar->codec_id == AV_CODEC_ID_NONE || sti->request_probe > 0) && |
| 2048 | stream_type == STREAM_TYPE_PRIVATE_DATA) | ||
| 2049 | 16 | mpegts_find_stream_type(st, desc_tag, DESC_types); | |
| 2050 | |||
| 2051 |
9/16✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 252 times.
✓ Branch 6 taken 53 times.
✓ Branch 7 taken 31 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 90 times.
✓ Branch 15 taken 64 times.
|
513 | switch (desc_tag) { |
| 2052 | ✗ | case VIDEO_STREAM_DESCRIPTOR: | |
| 2053 | ✗ | if (get8(pp, desc_end) & 0x1) { | |
| 2054 | ✗ | st->disposition |= AV_DISPOSITION_STILL_IMAGE; | |
| 2055 | } | ||
| 2056 | ✗ | break; | |
| 2057 | ✗ | case SL_DESCRIPTOR: | |
| 2058 | ✗ | desc_es_id = get16(pp, desc_end); | |
| 2059 | ✗ | if (desc_es_id < 0) | |
| 2060 | ✗ | break; | |
| 2061 | ✗ | if (ts && ts->pids[pid]) | |
| 2062 | ✗ | ts->pids[pid]->es_id = desc_es_id; | |
| 2063 | ✗ | for (i = 0; i < mp4_descr_count; i++) | |
| 2064 | ✗ | if (mp4_descr[i].dec_config_descr_len && | |
| 2065 | ✗ | mp4_descr[i].es_id == desc_es_id) { | |
| 2066 | FFIOContext pb; | ||
| 2067 | ✗ | ffio_init_read_context(&pb, mp4_descr[i].dec_config_descr, | |
| 2068 | ✗ | mp4_descr[i].dec_config_descr_len); | |
| 2069 | ✗ | ff_mp4_read_dec_config_descr(fc, st, &pb.pub); | |
| 2070 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_AAC && | |
| 2071 | ✗ | st->codecpar->extradata_size > 0) { | |
| 2072 | ✗ | sti->need_parsing = 0; | |
| 2073 | ✗ | sti->need_context_update = 1; | |
| 2074 | } | ||
| 2075 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4SYSTEMS) | |
| 2076 | ✗ | mpegts_open_section_filter(ts, pid, m4sl_cb, ts, 1); | |
| 2077 | } | ||
| 2078 | ✗ | break; | |
| 2079 | ✗ | case FMC_DESCRIPTOR: | |
| 2080 | ✗ | if (get16(pp, desc_end) < 0) | |
| 2081 | ✗ | break; | |
| 2082 | ✗ | if (mp4_descr_count > 0 && | |
| 2083 | ✗ | (st->codecpar->codec_id == AV_CODEC_ID_AAC_LATM || | |
| 2084 | ✗ | (sti->request_probe == 0 && st->codecpar->codec_id == AV_CODEC_ID_NONE) || | |
| 2085 | ✗ | sti->request_probe > 0) && | |
| 2086 | ✗ | mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) { | |
| 2087 | FFIOContext pb; | ||
| 2088 | ✗ | ffio_init_read_context(&pb, mp4_descr->dec_config_descr, | |
| 2089 | mp4_descr->dec_config_descr_len); | ||
| 2090 | ✗ | ff_mp4_read_dec_config_descr(fc, st, &pb.pub); | |
| 2091 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_AAC && | |
| 2092 | ✗ | st->codecpar->extradata_size > 0) { | |
| 2093 | ✗ | sti->request_probe = sti->need_parsing = 0; | |
| 2094 | ✗ | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; | |
| 2095 | ✗ | sti->need_context_update = 1; | |
| 2096 | } | ||
| 2097 | } | ||
| 2098 | ✗ | break; | |
| 2099 | ✗ | case TELETEXT_DESCRIPTOR: | |
| 2100 | { | ||
| 2101 | ✗ | uint8_t *extradata = NULL; | |
| 2102 | ✗ | int language_count = desc_len / 5, ret; | |
| 2103 | |||
| 2104 | ✗ | if (desc_len > 0 && desc_len % 5 != 0) | |
| 2105 | ✗ | return AVERROR_INVALIDDATA; | |
| 2106 | |||
| 2107 | ✗ | if (language_count > 0) { | |
| 2108 | /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */ | ||
| 2109 | ✗ | av_assert0(language_count <= sizeof(language) / 4); | |
| 2110 | |||
| 2111 | ✗ | if (st->codecpar->extradata == NULL) { | |
| 2112 | ✗ | ret = ff_alloc_extradata(st->codecpar, language_count * 2); | |
| 2113 | ✗ | if (ret < 0) | |
| 2114 | ✗ | return ret; | |
| 2115 | } | ||
| 2116 | |||
| 2117 | ✗ | if (st->codecpar->extradata_size < language_count * 2) | |
| 2118 | ✗ | return AVERROR_INVALIDDATA; | |
| 2119 | |||
| 2120 | ✗ | extradata = st->codecpar->extradata; | |
| 2121 | |||
| 2122 | ✗ | for (i = 0; i < language_count; i++) { | |
| 2123 | ✗ | language[i * 4 + 0] = get8(pp, desc_end); | |
| 2124 | ✗ | language[i * 4 + 1] = get8(pp, desc_end); | |
| 2125 | ✗ | language[i * 4 + 2] = get8(pp, desc_end); | |
| 2126 | ✗ | language[i * 4 + 3] = ','; | |
| 2127 | |||
| 2128 | ✗ | memcpy(extradata, *pp, 2); | |
| 2129 | ✗ | extradata += 2; | |
| 2130 | |||
| 2131 | ✗ | *pp += 2; | |
| 2132 | } | ||
| 2133 | |||
| 2134 | ✗ | language[i * 4 - 1] = 0; | |
| 2135 | ✗ | av_dict_set(&st->metadata, "language", language, 0); | |
| 2136 | ✗ | sti->need_context_update = 1; | |
| 2137 | } | ||
| 2138 | } | ||
| 2139 | ✗ | break; | |
| 2140 | 9 | case SUBTITLING_DESCRIPTOR: | |
| 2141 | { | ||
| 2142 | /* 8 bytes per DVB subtitle substream data: | ||
| 2143 | * ISO_639_language_code (3 bytes), | ||
| 2144 | * subtitling_type (1 byte), | ||
| 2145 | * composition_page_id (2 bytes), | ||
| 2146 | * ancillary_page_id (2 bytes) */ | ||
| 2147 | 9 | int language_count = desc_len / 8, ret; | |
| 2148 | |||
| 2149 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | if (desc_len > 0 && desc_len % 8 != 0) |
| 2150 | ✗ | return AVERROR_INVALIDDATA; | |
| 2151 | |||
| 2152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (language_count > 1) { |
| 2153 | ✗ | avpriv_request_sample(fc, "DVB subtitles with multiple languages"); | |
| 2154 | } | ||
| 2155 | |||
| 2156 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (language_count > 0) { |
| 2157 | uint8_t *extradata; | ||
| 2158 | |||
| 2159 | /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */ | ||
| 2160 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | av_assert0(language_count <= sizeof(language) / 4); |
| 2161 | |||
| 2162 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
|
9 | if (st->codecpar->extradata == NULL) { |
| 2163 | 3 | ret = ff_alloc_extradata(st->codecpar, language_count * 5); | |
| 2164 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
| 2165 | ✗ | return ret; | |
| 2166 | } | ||
| 2167 | |||
| 2168 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (st->codecpar->extradata_size < language_count * 5) |
| 2169 | ✗ | return AVERROR_INVALIDDATA; | |
| 2170 | |||
| 2171 | 9 | extradata = st->codecpar->extradata; | |
| 2172 | |||
| 2173 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
|
18 | for (i = 0; i < language_count; i++) { |
| 2174 | 9 | language[i * 4 + 0] = get8(pp, desc_end); | |
| 2175 | 9 | language[i * 4 + 1] = get8(pp, desc_end); | |
| 2176 | 9 | language[i * 4 + 2] = get8(pp, desc_end); | |
| 2177 | 9 | language[i * 4 + 3] = ','; | |
| 2178 | |||
| 2179 | /* hearing impaired subtitles detection using subtitling_type */ | ||
| 2180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | switch (*pp[0]) { |
| 2181 | ✗ | case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */ | |
| 2182 | case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */ | ||
| 2183 | case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */ | ||
| 2184 | case 0x23: /* DVB subtitles (for the hard of hearing) for display on 2.21:1 aspect ratio monitor */ | ||
| 2185 | case 0x24: /* DVB subtitles (for the hard of hearing) for display on a high definition monitor */ | ||
| 2186 | case 0x25: /* DVB subtitles (for the hard of hearing) with plano-stereoscopic disparity for display on a high definition monitor */ | ||
| 2187 | ✗ | st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; | |
| 2188 | ✗ | break; | |
| 2189 | } | ||
| 2190 | |||
| 2191 | 9 | extradata[4] = get8(pp, desc_end); /* subtitling_type */ | |
| 2192 | 9 | memcpy(extradata, *pp, 4); /* composition_page_id and ancillary_page_id */ | |
| 2193 | 9 | extradata += 5; | |
| 2194 | |||
| 2195 | 9 | *pp += 4; | |
| 2196 | } | ||
| 2197 | |||
| 2198 | 9 | language[i * 4 - 1] = 0; | |
| 2199 | 9 | av_dict_set(&st->metadata, "language", language, 0); | |
| 2200 | 9 | sti->need_context_update = 1; | |
| 2201 | } | ||
| 2202 | } | ||
| 2203 | 9 | break; | |
| 2204 | 252 | case ISO_639_LANGUAGE_DESCRIPTOR: | |
| 2205 |
2/2✓ Branch 0 taken 246 times.
✓ Branch 1 taken 252 times.
|
498 | for (i = 0; i + 4 <= desc_len; i += 4) { |
| 2206 | 246 | language[i + 0] = get8(pp, desc_end); | |
| 2207 | 246 | language[i + 1] = get8(pp, desc_end); | |
| 2208 | 246 | language[i + 2] = get8(pp, desc_end); | |
| 2209 | 246 | language[i + 3] = ','; | |
| 2210 |
2/4✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
✓ Branch 4 taken 186 times.
|
246 | switch (get8(pp, desc_end)) { |
| 2211 | ✗ | case 0x01: | |
| 2212 | ✗ | st->disposition |= AV_DISPOSITION_CLEAN_EFFECTS; | |
| 2213 | ✗ | break; | |
| 2214 | ✗ | case 0x02: | |
| 2215 | ✗ | st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; | |
| 2216 | ✗ | break; | |
| 2217 | 60 | case 0x03: | |
| 2218 | 60 | st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; | |
| 2219 | 60 | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
| 2220 | 60 | break; | |
| 2221 | } | ||
| 2222 | } | ||
| 2223 |
4/4✓ Branch 0 taken 246 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 242 times.
✓ Branch 3 taken 4 times.
|
252 | if (i && language[0]) { |
| 2224 | 242 | language[i - 1] = 0; | |
| 2225 | /* don't overwrite language, as it may already have been set by | ||
| 2226 | * another, more specific descriptor (e.g. supplementary audio) */ | ||
| 2227 | 242 | av_dict_set(&st->metadata, "language", language, AV_DICT_DONT_OVERWRITE); | |
| 2228 | } | ||
| 2229 | 252 | break; | |
| 2230 | 53 | case REGISTRATION_DESCRIPTOR: | |
| 2231 | 53 | st->codecpar->codec_tag = bytestream_get_le32(pp); | |
| 2232 | 53 | av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codecpar->codec_tag); | |
| 2233 |
3/4✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 50 times.
|
53 | if (st->codecpar->codec_id == AV_CODEC_ID_NONE || sti->request_probe > 0) { |
| 2234 | 3 | mpegts_find_stream_type(st, st->codecpar->codec_tag, REGD_types); | |
| 2235 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D')) |
| 2236 | 2 | sti->request_probe = 50; | |
| 2237 | } | ||
| 2238 | 53 | break; | |
| 2239 | 31 | case STREAM_IDENTIFIER_DESCRIPTOR: | |
| 2240 | 31 | sti->stream_identifier = 1 + get8(pp, desc_end); | |
| 2241 | 31 | break; | |
| 2242 | 4 | case METADATA_DESCRIPTOR: | |
| 2243 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (get16(pp, desc_end) == 0xFFFF) |
| 2244 | 4 | *pp += 4; | |
| 2245 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (get8(pp, desc_end) == 0xFF) { |
| 2246 | 4 | st->codecpar->codec_tag = bytestream_get_le32(pp); | |
| 2247 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (st->codecpar->codec_id == AV_CODEC_ID_NONE) |
| 2248 | 1 | mpegts_find_stream_type(st, st->codecpar->codec_tag, METADATA_types); | |
| 2249 | } | ||
| 2250 | 4 | break; | |
| 2251 | 4 | case DVB_EXTENSION_DESCRIPTOR: /* DVB extension descriptor */ | |
| 2252 | 4 | ext_desc_tag = get8(pp, desc_end); | |
| 2253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (ext_desc_tag < 0) |
| 2254 | ✗ | return AVERROR_INVALIDDATA; | |
| 2255 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
4 | if (st->codecpar->codec_id == AV_CODEC_ID_OPUS && |
| 2256 | ext_desc_tag == 0x80) { /* User defined (provisional Opus) */ | ||
| 2257 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (!st->codecpar->extradata) { |
| 2258 | 1 | st->codecpar->extradata = av_mallocz(sizeof(opus_default_extradata) + | |
| 2259 | AV_INPUT_BUFFER_PADDING_SIZE); | ||
| 2260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!st->codecpar->extradata) |
| 2261 | ✗ | return AVERROR(ENOMEM); | |
| 2262 | |||
| 2263 | 1 | st->codecpar->extradata_size = sizeof(opus_default_extradata); | |
| 2264 | 1 | memcpy(st->codecpar->extradata, opus_default_extradata, sizeof(opus_default_extradata)); | |
| 2265 | |||
| 2266 | 1 | channel_config_code = get8(pp, desc_end); | |
| 2267 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (channel_config_code < 0) |
| 2268 | ✗ | return AVERROR_INVALIDDATA; | |
| 2269 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (channel_config_code <= 0x8) { |
| 2270 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | st->codecpar->extradata[9] = channels = channel_config_code ? channel_config_code : 2; |
| 2271 | 1 | AV_WL32(&st->codecpar->extradata[12], 48000); | |
| 2272 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | st->codecpar->extradata[18] = channel_config_code ? (channels > 2) : /* Dual Mono */ 255; |
| 2273 | 1 | st->codecpar->extradata[19] = opus_stream_cnt[channel_config_code]; | |
| 2274 | 1 | st->codecpar->extradata[20] = opus_coupled_stream_cnt[channel_config_code]; | |
| 2275 | 1 | memcpy(&st->codecpar->extradata[21], opus_channel_map[channels - 1], channels); | |
| 2276 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | st->codecpar->extradata_size = st->codecpar->extradata[18] ? 21 + channels : 19; |
| 2277 | } else { | ||
| 2278 | ✗ | avpriv_request_sample(fc, "Opus in MPEG-TS - channel_config_code > 0x8"); | |
| 2279 | } | ||
| 2280 | 1 | sti->need_parsing = AVSTREAM_PARSE_FULL; | |
| 2281 | 1 | sti->need_context_update = 1; | |
| 2282 | } | ||
| 2283 | } | ||
| 2284 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (ext_desc_tag == SUPPLEMENTARY_AUDIO_DESCRIPTOR) { |
| 2285 | int flags; | ||
| 2286 | |||
| 2287 | ✗ | if (desc_len < 1) | |
| 2288 | ✗ | return AVERROR_INVALIDDATA; | |
| 2289 | ✗ | flags = get8(pp, desc_end); | |
| 2290 | |||
| 2291 | ✗ | if ((flags & 0x80) == 0) /* mix_type */ | |
| 2292 | ✗ | st->disposition |= AV_DISPOSITION_DEPENDENT; | |
| 2293 | |||
| 2294 | ✗ | switch ((flags >> 2) & 0x1F) { /* editorial_classification */ | |
| 2295 | ✗ | case 0x01: | |
| 2296 | ✗ | st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; | |
| 2297 | ✗ | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
| 2298 | ✗ | break; | |
| 2299 | ✗ | case 0x02: | |
| 2300 | ✗ | st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; | |
| 2301 | ✗ | break; | |
| 2302 | ✗ | case 0x03: | |
| 2303 | ✗ | st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; | |
| 2304 | ✗ | break; | |
| 2305 | } | ||
| 2306 | |||
| 2307 | ✗ | if (flags & 0x01) { /* language_code_present */ | |
| 2308 | ✗ | if (desc_len < 4) | |
| 2309 | ✗ | return AVERROR_INVALIDDATA; | |
| 2310 | ✗ | language[0] = get8(pp, desc_end); | |
| 2311 | ✗ | language[1] = get8(pp, desc_end); | |
| 2312 | ✗ | language[2] = get8(pp, desc_end); | |
| 2313 | ✗ | language[3] = 0; | |
| 2314 | |||
| 2315 | /* This language always has to override a possible | ||
| 2316 | * ISO 639 language descriptor language */ | ||
| 2317 | ✗ | if (language[0]) | |
| 2318 | ✗ | av_dict_set(&st->metadata, "language", language, 0); | |
| 2319 | } | ||
| 2320 | } | ||
| 2321 | 4 | break; | |
| 2322 | 6 | case AC3_DESCRIPTOR: | |
| 2323 | { | ||
| 2324 | 6 | int component_type_flag = get8(pp, desc_end) & (1 << 7); | |
| 2325 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (component_type_flag) { |
| 2326 | ✗ | int component_type = get8(pp, desc_end); | |
| 2327 | ✗ | int service_type_mask = 0x38; // 0b00111000 | |
| 2328 | ✗ | int service_type = ((component_type & service_type_mask) >> 3); | |
| 2329 | ✗ | if (service_type == 0x02 /* 0b010 */) { | |
| 2330 | ✗ | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
| 2331 | ✗ | av_log(ts ? ts->stream : fc, AV_LOG_DEBUG, "New track disposition for id %u: %u\n", st->id, st->disposition); | |
| 2332 | } | ||
| 2333 | } | ||
| 2334 | } | ||
| 2335 | 6 | break; | |
| 2336 | ✗ | case ENHANCED_AC3_DESCRIPTOR: | |
| 2337 | { | ||
| 2338 | ✗ | int component_type_flag = get8(pp, desc_end) & (1 << 7); | |
| 2339 | ✗ | if (component_type_flag) { | |
| 2340 | ✗ | int component_type = get8(pp, desc_end); | |
| 2341 | ✗ | int service_type_mask = 0x38; // 0b00111000 | |
| 2342 | ✗ | int service_type = ((component_type & service_type_mask) >> 3); | |
| 2343 | ✗ | if (service_type == 0x02 /* 0b010 */) { | |
| 2344 | ✗ | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
| 2345 | ✗ | av_log(ts ? ts->stream : fc, AV_LOG_DEBUG, "New track disposition for id %u: %u\n", st->id, st->disposition); | |
| 2346 | } | ||
| 2347 | } | ||
| 2348 | } | ||
| 2349 | ✗ | break; | |
| 2350 | ✗ | case DATA_COMPONENT_DESCRIPTOR: | |
| 2351 | // STD-B24, fascicle 3, chapter 4 defines private_stream_1 | ||
| 2352 | // for captions | ||
| 2353 | ✗ | if (stream_type == STREAM_TYPE_PRIVATE_DATA) { | |
| 2354 | // This structure is defined in STD-B10, part 1, listing 5.4 and | ||
| 2355 | // part 2, 6.2.20). | ||
| 2356 | // Listing of data_component_ids is in STD-B10, part 2, Annex J. | ||
| 2357 | // Component tag limits are documented in TR-B14, fascicle 2, | ||
| 2358 | // Vol. 3, Section 2, 4.2.8.1 | ||
| 2359 | ✗ | int actual_component_tag = sti->stream_identifier - 1; | |
| 2360 | ✗ | int picked_profile = AV_PROFILE_UNKNOWN; | |
| 2361 | ✗ | int data_component_id = get16(pp, desc_end); | |
| 2362 | ✗ | if (data_component_id < 0) | |
| 2363 | ✗ | return AVERROR_INVALIDDATA; | |
| 2364 | |||
| 2365 | ✗ | switch (data_component_id) { | |
| 2366 | ✗ | case 0x0008: | |
| 2367 | // [0x30..0x37] are component tags utilized for | ||
| 2368 | // non-mobile captioning service ("profile A"). | ||
| 2369 | ✗ | if (actual_component_tag >= 0x30 && | |
| 2370 | actual_component_tag <= 0x37) { | ||
| 2371 | ✗ | picked_profile = AV_PROFILE_ARIB_PROFILE_A; | |
| 2372 | } | ||
| 2373 | ✗ | break; | |
| 2374 | ✗ | case 0x0012: | |
| 2375 | // component tag 0x87 signifies a mobile/partial reception | ||
| 2376 | // (1seg) captioning service ("profile C"). | ||
| 2377 | ✗ | if (actual_component_tag == 0x87) { | |
| 2378 | ✗ | picked_profile = AV_PROFILE_ARIB_PROFILE_C; | |
| 2379 | } | ||
| 2380 | ✗ | break; | |
| 2381 | ✗ | default: | |
| 2382 | ✗ | break; | |
| 2383 | } | ||
| 2384 | |||
| 2385 | ✗ | if (picked_profile == AV_PROFILE_UNKNOWN) | |
| 2386 | ✗ | break; | |
| 2387 | |||
| 2388 | ✗ | st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; | |
| 2389 | ✗ | st->codecpar->codec_id = AV_CODEC_ID_ARIB_CAPTION; | |
| 2390 | ✗ | if (st->codecpar->profile != picked_profile) { | |
| 2391 | ✗ | st->codecpar->profile = picked_profile; | |
| 2392 | ✗ | sti->need_context_update = 1; | |
| 2393 | } | ||
| 2394 | ✗ | sti->request_probe = 0; | |
| 2395 | ✗ | sti->need_parsing = 0; | |
| 2396 | } | ||
| 2397 | ✗ | break; | |
| 2398 | ✗ | case DOVI_VIDEO_STREAM_DESCRIPTOR: | |
| 2399 | { | ||
| 2400 | uint32_t buf; | ||
| 2401 | AVDOVIDecoderConfigurationRecord *dovi; | ||
| 2402 | size_t dovi_size; | ||
| 2403 | ✗ | int dependency_pid = -1; // Unset | |
| 2404 | |||
| 2405 | ✗ | if (desc_end - *pp < 4) // (8 + 8 + 7 + 6 + 1 + 1 + 1) / 8 | |
| 2406 | ✗ | return AVERROR_INVALIDDATA; | |
| 2407 | |||
| 2408 | ✗ | dovi = av_dovi_alloc(&dovi_size); | |
| 2409 | ✗ | if (!dovi) | |
| 2410 | ✗ | return AVERROR(ENOMEM); | |
| 2411 | |||
| 2412 | ✗ | dovi->dv_version_major = get8(pp, desc_end); | |
| 2413 | ✗ | dovi->dv_version_minor = get8(pp, desc_end); | |
| 2414 | ✗ | buf = get16(pp, desc_end); | |
| 2415 | ✗ | dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits | |
| 2416 | ✗ | dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits | |
| 2417 | ✗ | dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit | |
| 2418 | ✗ | dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit | |
| 2419 | ✗ | dovi->bl_present_flag = buf & 0x01; // 1 bit | |
| 2420 | ✗ | if (!dovi->bl_present_flag && desc_end - *pp >= 2) { | |
| 2421 | ✗ | buf = get16(pp, desc_end); | |
| 2422 | ✗ | dependency_pid = buf >> 3; // 13 bits | |
| 2423 | } | ||
| 2424 | ✗ | if (desc_end - *pp >= 1) { // 8 bits | |
| 2425 | ✗ | buf = get8(pp, desc_end); | |
| 2426 | ✗ | dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits | |
| 2427 | ✗ | dovi->dv_md_compression = (buf >> 2) & 0x03; // 2 bits | |
| 2428 | } else { | ||
| 2429 | // 0 stands for None | ||
| 2430 | // Dolby Vision V1.2.93 profiles and levels | ||
| 2431 | ✗ | dovi->dv_bl_signal_compatibility_id = 0; | |
| 2432 | ✗ | dovi->dv_md_compression = AV_DOVI_COMPRESSION_NONE; | |
| 2433 | } | ||
| 2434 | |||
| 2435 | ✗ | if (!av_packet_side_data_add(&st->codecpar->coded_side_data, | |
| 2436 | ✗ | &st->codecpar->nb_coded_side_data, | |
| 2437 | AV_PKT_DATA_DOVI_CONF, | ||
| 2438 | (uint8_t *)dovi, dovi_size, 0)) { | ||
| 2439 | ✗ | av_free(dovi); | |
| 2440 | ✗ | return AVERROR(ENOMEM); | |
| 2441 | } | ||
| 2442 | |||
| 2443 | ✗ | av_log(fc, AV_LOG_TRACE, "DOVI, version: %d.%d, profile: %d, level: %d, " | |
| 2444 | "rpu flag: %d, el flag: %d, bl flag: %d, dependency_pid: %d, " | ||
| 2445 | "compatibility id: %d, compression: %d\n", | ||
| 2446 | ✗ | dovi->dv_version_major, dovi->dv_version_minor, | |
| 2447 | ✗ | dovi->dv_profile, dovi->dv_level, | |
| 2448 | ✗ | dovi->rpu_present_flag, | |
| 2449 | ✗ | dovi->el_present_flag, | |
| 2450 | ✗ | dovi->bl_present_flag, | |
| 2451 | dependency_pid, | ||
| 2452 | ✗ | dovi->dv_bl_signal_compatibility_id, | |
| 2453 | ✗ | dovi->dv_md_compression); | |
| 2454 | } | ||
| 2455 | ✗ | break; | |
| 2456 | 90 | case EXTENSION_DESCRIPTOR: /* descriptor extension */ | |
| 2457 | { | ||
| 2458 | 90 | int ret = parse_mpeg2_extension_descriptor(fc, st, prg_id, pp, desc_end); | |
| 2459 | |||
| 2460 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 66 times.
|
90 | if (ret < 0) |
| 2461 | 24 | return ret; | |
| 2462 | } | ||
| 2463 | 66 | break; | |
| 2464 | 64 | default: | |
| 2465 | 64 | break; | |
| 2466 | } | ||
| 2467 | 489 | *pp = desc_end; | |
| 2468 | 489 | return 0; | |
| 2469 | } | ||
| 2470 | |||
| 2471 | 12 | static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int programid, | |
| 2472 | int stream_identifier, int pmt_stream_idx, struct Program *p) | ||
| 2473 | { | ||
| 2474 | 12 | AVFormatContext *s = ts->stream; | |
| 2475 | 12 | AVStream *found = NULL; | |
| 2476 | |||
| 2477 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (stream_identifier) { /* match based on "stream identifier descriptor" if present */ |
| 2478 | ✗ | for (int i = 0; i < p->nb_streams; i++) { | |
| 2479 | ✗ | if (p->streams[i].stream_identifier == stream_identifier) | |
| 2480 | ✗ | if (!found || pmt_stream_idx == i) /* fallback to idx based guess if multiple streams have the same identifier */ | |
| 2481 | ✗ | found = s->streams[p->streams[i].idx]; | |
| 2482 | } | ||
| 2483 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
|
12 | } else if (pmt_stream_idx < p->nb_streams) { /* match based on position within the PMT */ |
| 2484 | 7 | found = s->streams[p->streams[pmt_stream_idx].idx]; | |
| 2485 | } | ||
| 2486 | |||
| 2487 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
|
12 | if (found) { |
| 2488 | 7 | av_log(ts->stream, AV_LOG_VERBOSE, | |
| 2489 | "reusing existing %s stream %d (pid=0x%x) for new pid=0x%x\n", | ||
| 2490 | 7 | av_get_media_type_string(found->codecpar->codec_type), | |
| 2491 | found->index, found->id, pid); | ||
| 2492 | } | ||
| 2493 | |||
| 2494 | 12 | return found; | |
| 2495 | } | ||
| 2496 | |||
| 2497 | 660 | static int parse_stream_identifier_desc(const uint8_t *p, const uint8_t *p_end) | |
| 2498 | { | ||
| 2499 | 660 | const uint8_t **pp = &p; | |
| 2500 | const uint8_t *desc_list_end; | ||
| 2501 | const uint8_t *desc_end; | ||
| 2502 | int desc_list_len; | ||
| 2503 | int desc_len, desc_tag; | ||
| 2504 | |||
| 2505 | 660 | desc_list_len = get16(pp, p_end); | |
| 2506 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
|
660 | if (desc_list_len < 0) |
| 2507 | ✗ | return -1; | |
| 2508 | 660 | desc_list_len &= 0xfff; | |
| 2509 | 660 | desc_list_end = p + desc_list_len; | |
| 2510 |
1/2✓ Branch 0 taken 660 times.
✗ Branch 1 not taken.
|
660 | if (desc_list_end > p_end) |
| 2511 | ✗ | return -1; | |
| 2512 | |||
| 2513 | while (1) { | ||
| 2514 | 1133 | desc_tag = get8(pp, desc_list_end); | |
| 2515 |
2/2✓ Branch 0 taken 632 times.
✓ Branch 1 taken 501 times.
|
1133 | if (desc_tag < 0) |
| 2516 | 632 | return -1; | |
| 2517 | 501 | desc_len = get8(pp, desc_list_end); | |
| 2518 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
|
501 | if (desc_len < 0) |
| 2519 | ✗ | return -1; | |
| 2520 | 501 | desc_end = *pp + desc_len; | |
| 2521 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 501 times.
|
501 | if (desc_end > desc_list_end) |
| 2522 | ✗ | return -1; | |
| 2523 | |||
| 2524 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 473 times.
|
501 | if (desc_tag == STREAM_IDENTIFIER_DESCRIPTOR) { |
| 2525 | 28 | return get8(pp, desc_end); | |
| 2526 | } | ||
| 2527 | 473 | *pp = desc_end; | |
| 2528 | } | ||
| 2529 | |||
| 2530 | return -1; | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | 166 | static int is_pes_stream(int stream_type, uint32_t prog_reg_desc) | |
| 2534 | { | ||
| 2535 |
2/3✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 136 times.
|
166 | switch (stream_type) { |
| 2536 | ✗ | case STREAM_TYPE_PRIVATE_SECTION: | |
| 2537 | case STREAM_TYPE_ISO_IEC_14496_SECTION: | ||
| 2538 | ✗ | return 0; | |
| 2539 | 30 | case STREAM_TYPE_SCTE_DATA_SCTE_35: | |
| 2540 | /* This User Private stream_type value is used by multiple organizations | ||
| 2541 | for different things. ANSI/SCTE 35 splice_info_section() is a | ||
| 2542 | private_section() not a PES_packet(). */ | ||
| 2543 | 30 | return !(prog_reg_desc == AV_RL32("CUEI")); | |
| 2544 | 136 | default: | |
| 2545 | 136 | return 1; | |
| 2546 | } | ||
| 2547 | } | ||
| 2548 | |||
| 2549 | 351 | static void create_stream_groups(MpegTSContext *ts, const struct Program *prg) | |
| 2550 | { | ||
| 2551 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 351 times.
|
396 | for (int i = 0; i < prg->nb_stream_groups; i++) { |
| 2552 | 45 | const struct StreamGroup *grp = &prg->stream_groups[i]; | |
| 2553 | AVStreamGroup *stg; | ||
| 2554 | int j; | ||
| 2555 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 21 times.
|
45 | if (grp->nb_streams < 2) |
| 2556 | 24 | continue; | |
| 2557 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 6 times.
|
21 | for (j = 0; j < ts->stream->nb_stream_groups; j++) { |
| 2558 | 15 | stg = ts->stream->stream_groups[j]; | |
| 2559 |
1/2✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
|
15 | if (stg->id == grp->id) |
| 2560 | 15 | break; | |
| 2561 | } | ||
| 2562 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 15 times.
|
21 | if (j == ts->stream->nb_stream_groups) |
| 2563 | 6 | stg = avformat_stream_group_create(ts->stream, grp->type, NULL); | |
| 2564 | else | ||
| 2565 | 15 | continue; | |
| 2566 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!stg) |
| 2567 | ✗ | continue; | |
| 2568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | av_assert0(grp->type == AV_STREAM_GROUP_PARAMS_LCEVC); |
| 2569 | 6 | stg->id = grp->id; | |
| 2570 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
|
18 | for (int j = 0; j < grp->nb_streams; j++) { |
| 2571 | 12 | int ret = avformat_stream_group_add_stream(stg, grp->streams[j]); | |
| 2572 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (ret < 0) { |
| 2573 | ✗ | ff_remove_stream_group(ts->stream, stg); | |
| 2574 | ✗ | continue; | |
| 2575 | } | ||
| 2576 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
|
12 | if (grp->streams[j]->codecpar->codec_id == AV_CODEC_ID_LCEVC) |
| 2577 | 6 | stg->params.lcevc->lcevc_index = stg->nb_streams - 1; | |
| 2578 | } | ||
| 2579 | } | ||
| 2580 | 351 | } | |
| 2581 | |||
| 2582 | 3660 | static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) | |
| 2583 | { | ||
| 2584 | 3660 | MpegTSContext *ts = filter->u.section_filter.opaque; | |
| 2585 | 3660 | MpegTSSectionFilter *tssf = &filter->u.section_filter; | |
| 2586 | struct Program old_program; | ||
| 2587 | 3660 | SectionHeader h1, *h = &h1; | |
| 2588 | PESContext *pes; | ||
| 2589 | AVStream *st; | ||
| 2590 | const uint8_t *p, *p_end, *desc_list_end; | ||
| 2591 | int program_info_length, pcr_pid, pid, stream_type; | ||
| 2592 | int desc_list_len; | ||
| 2593 | 3660 | uint32_t prog_reg_desc = 0; /* registration descriptor */ | |
| 2594 | 3660 | int stream_identifier = -1; | |
| 2595 | struct Program *prg; | ||
| 2596 | |||
| 2597 | 3660 | int mp4_descr_count = 0; | |
| 2598 | 3660 | Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = { { 0 } }; | |
| 2599 | int i; | ||
| 2600 | |||
| 2601 | 3660 | av_log(ts->stream, AV_LOG_TRACE, "PMT: len %i\n", section_len); | |
| 2602 | hex_dump_debug(ts->stream, section, section_len); | ||
| 2603 | |||
| 2604 | 3660 | p_end = section + section_len - 4; | |
| 2605 | 3660 | p = section; | |
| 2606 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3660 times.
|
3660 | if (parse_section_header(h, &p, p_end) < 0) |
| 2607 | 3309 | return; | |
| 2608 |
2/2✓ Branch 0 taken 75 times.
✓ Branch 1 taken 3585 times.
|
3660 | if (h->tid != PMT_TID) |
| 2609 | 75 | return; | |
| 2610 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3585 times.
|
3585 | if (!h->current_next) |
| 2611 | ✗ | return; | |
| 2612 |
2/2✓ Branch 1 taken 3234 times.
✓ Branch 2 taken 351 times.
|
3585 | if (skip_identical(h, tssf)) |
| 2613 | 3234 | return; | |
| 2614 | |||
| 2615 | 351 | av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d version=%d tid=%d\n", | |
| 2616 | 351 | h->id, h->sec_num, h->last_sec_num, h->version, h->tid); | |
| 2617 | |||
| 2618 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
351 | if (!ts->scan_all_pmts && ts->skip_changes) |
| 2619 | ✗ | return; | |
| 2620 | |||
| 2621 | 351 | prg = get_program(ts, h->id); | |
| 2622 |
1/2✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
|
351 | if (prg) |
| 2623 | 351 | old_program = *prg; | |
| 2624 | else | ||
| 2625 | ✗ | clear_program(&old_program); | |
| 2626 | |||
| 2627 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
351 | if (ts->skip_unknown_pmt && !prg) |
| 2628 | ✗ | return; | |
| 2629 |
3/6✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 351 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 351 times.
|
351 | if (prg && prg->nb_pids && prg->pids[0] != ts->current_pid) |
| 2630 | ✗ | return; | |
| 2631 |
2/2✓ Branch 0 taken 212 times.
✓ Branch 1 taken 139 times.
|
351 | if (!ts->skip_clear) |
| 2632 | 212 | clear_avprogram(ts, h->id); | |
| 2633 | 351 | clear_program(prg); | |
| 2634 | 351 | add_pid_to_program(prg, ts->current_pid); | |
| 2635 | |||
| 2636 | 351 | pcr_pid = get16(&p, p_end); | |
| 2637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
|
351 | if (pcr_pid < 0) |
| 2638 | ✗ | return; | |
| 2639 | 351 | pcr_pid &= 0x1fff; | |
| 2640 | 351 | add_pid_to_program(prg, pcr_pid); | |
| 2641 | 351 | update_av_program_info(ts->stream, h->id, pcr_pid, h->version); | |
| 2642 | |||
| 2643 | 351 | av_log(ts->stream, AV_LOG_TRACE, "pcr_pid=0x%x\n", pcr_pid); | |
| 2644 | |||
| 2645 | 351 | program_info_length = get16(&p, p_end); | |
| 2646 | |||
| 2647 |
2/4✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 351 times.
|
351 | if (program_info_length < 0 || (program_info_length & 0xFFF) > p_end - p) |
| 2648 | ✗ | return; | |
| 2649 | 351 | program_info_length &= 0xfff; | |
| 2650 |
2/2✓ Branch 0 taken 294 times.
✓ Branch 1 taken 351 times.
|
645 | while (program_info_length >= 2) { |
| 2651 | uint8_t tag, len; | ||
| 2652 | 294 | tag = get8(&p, p_end); | |
| 2653 | 294 | len = get8(&p, p_end); | |
| 2654 | |||
| 2655 | 294 | av_log(ts->stream, AV_LOG_TRACE, "program tag: 0x%02x len=%d\n", tag, len); | |
| 2656 | |||
| 2657 | 294 | program_info_length -= 2; | |
| 2658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 294 times.
|
294 | if (len > program_info_length) |
| 2659 | // something else is broken, exit the program_descriptors_loop | ||
| 2660 | ✗ | break; | |
| 2661 | 294 | program_info_length -= len; | |
| 2662 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 294 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
294 | if (tag == IOD_DESCRIPTOR && len >= 2) { |
| 2663 | ✗ | get8(&p, p_end); // scope | |
| 2664 | ✗ | get8(&p, p_end); // label | |
| 2665 | ✗ | len -= 2; | |
| 2666 | ✗ | mp4_read_iods(ts->stream, p, len, mp4_descr + mp4_descr_count, | |
| 2667 | &mp4_descr_count, MAX_MP4_DESCR_COUNT - mp4_descr_count); | ||
| 2668 |
3/4✓ Branch 0 taken 144 times.
✓ Branch 1 taken 150 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
|
294 | } else if (tag == REGISTRATION_DESCRIPTOR && len >= 4) { |
| 2669 | 144 | prog_reg_desc = bytestream_get_le32(&p); | |
| 2670 | 144 | len -= 4; | |
| 2671 | } | ||
| 2672 | 294 | p += len; | |
| 2673 | } | ||
| 2674 | 351 | p += program_info_length; | |
| 2675 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
|
351 | if (p >= p_end) |
| 2676 | ✗ | goto out; | |
| 2677 | |||
| 2678 | // stop parsing after pmt, we found header | ||
| 2679 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 275 times.
|
351 | if (!ts->pkt) |
| 2680 | 76 | ts->stop_parse = 2; | |
| 2681 | |||
| 2682 |
1/2✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
|
351 | if (prg) |
| 2683 | 351 | prg->pmt_found = 1; | |
| 2684 | |||
| 2685 |
1/2✓ Branch 0 taken 1011 times.
✗ Branch 1 not taken.
|
1011 | for (i = 0; i < MAX_STREAMS_PER_PROGRAM; i++) { |
| 2686 | 1011 | st = 0; | |
| 2687 | 1011 | pes = NULL; | |
| 2688 | 1011 | stream_type = get8(&p, p_end); | |
| 2689 |
2/2✓ Branch 0 taken 351 times.
✓ Branch 1 taken 660 times.
|
1011 | if (stream_type < 0) |
| 2690 | 351 | break; | |
| 2691 | 660 | pid = get16(&p, p_end); | |
| 2692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
|
660 | if (pid < 0) |
| 2693 | ✗ | goto out; | |
| 2694 | 660 | pid &= 0x1fff; | |
| 2695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
|
660 | if (pid == ts->current_pid) |
| 2696 | ✗ | goto out; | |
| 2697 | |||
| 2698 | 660 | stream_identifier = parse_stream_identifier_desc(p, p_end) + 1; | |
| 2699 | |||
| 2700 | /* now create stream */ | ||
| 2701 |
4/4✓ Branch 0 taken 514 times.
✓ Branch 1 taken 146 times.
✓ Branch 2 taken 494 times.
✓ Branch 3 taken 20 times.
|
660 | if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) { |
| 2702 | 494 | pes = ts->pids[pid]->u.pes_filter.opaque; | |
| 2703 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 478 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
|
494 | if (ts->merge_pmt_versions && !pes->st) { |
| 2704 | ✗ | st = find_matching_stream(ts, pid, h->id, stream_identifier, i, &old_program); | |
| 2705 | ✗ | if (st) { | |
| 2706 | ✗ | pes->st = st; | |
| 2707 | ✗ | pes->stream_type = stream_type; | |
| 2708 | ✗ | pes->merged_st = 1; | |
| 2709 | } | ||
| 2710 | } | ||
| 2711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
|
494 | if (!pes->st) { |
| 2712 | ✗ | pes->st = avformat_new_stream(pes->stream, NULL); | |
| 2713 | ✗ | if (!pes->st) | |
| 2714 | ✗ | goto out; | |
| 2715 | ✗ | pes->st->id = pes->pid; | |
| 2716 | } | ||
| 2717 | 494 | st = pes->st; | |
| 2718 |
2/2✓ Branch 1 taken 136 times.
✓ Branch 2 taken 30 times.
|
166 | } else if (is_pes_stream(stream_type, prog_reg_desc)) { |
| 2719 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
|
136 | if (ts->pids[pid]) |
| 2720 | ✗ | mpegts_close_filter(ts, ts->pids[pid]); // wrongly added sdt filter probably | |
| 2721 | 136 | pes = add_pes_stream(ts, pid, pcr_pid); | |
| 2722 |
4/6✓ Branch 0 taken 8 times.
✓ Branch 1 taken 128 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
136 | if (ts->merge_pmt_versions && pes && !pes->st) { |
| 2723 | 8 | st = find_matching_stream(ts, pid, h->id, stream_identifier, i, &old_program); | |
| 2724 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if (st) { |
| 2725 | 4 | pes->st = st; | |
| 2726 | 4 | pes->stream_type = stream_type; | |
| 2727 | 4 | pes->merged_st = 1; | |
| 2728 | } | ||
| 2729 | } | ||
| 2730 |
3/4✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 4 times.
|
136 | if (pes && !pes->st) { |
| 2731 | 132 | st = avformat_new_stream(pes->stream, NULL); | |
| 2732 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (!st) |
| 2733 | ✗ | goto out; | |
| 2734 | 132 | st->id = pes->pid; | |
| 2735 | } | ||
| 2736 | } else { | ||
| 2737 | 30 | int idx = ff_find_stream_index(ts->stream, pid); | |
| 2738 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
|
30 | if (idx >= 0) { |
| 2739 | 20 | st = ts->stream->streams[idx]; | |
| 2740 | } | ||
| 2741 |
4/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
|
30 | if (ts->merge_pmt_versions && !st) { |
| 2742 | 4 | st = find_matching_stream(ts, pid, h->id, stream_identifier, i, &old_program); | |
| 2743 | } | ||
| 2744 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
|
30 | if (!st) { |
| 2745 | 7 | st = avformat_new_stream(ts->stream, NULL); | |
| 2746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!st) |
| 2747 | ✗ | goto out; | |
| 2748 | 7 | st->id = pid; | |
| 2749 | 7 | st->codecpar->codec_type = AVMEDIA_TYPE_DATA; | |
| 2750 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | if (stream_type == STREAM_TYPE_SCTE_DATA_SCTE_35 && prog_reg_desc == AV_RL32("CUEI")) { |
| 2751 | 7 | mpegts_find_stream_type(st, stream_type, SCTE_types); | |
| 2752 | 7 | mpegts_open_section_filter(ts, pid, scte_data_cb, ts, 1); | |
| 2753 | } | ||
| 2754 | } | ||
| 2755 | } | ||
| 2756 | |||
| 2757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
|
660 | if (!st) |
| 2758 | ✗ | goto out; | |
| 2759 | |||
| 2760 |
4/4✓ Branch 0 taken 630 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 142 times.
✓ Branch 3 taken 488 times.
|
660 | if (pes && pes->stream_type != stream_type) |
| 2761 | 142 | mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc); | |
| 2762 | |||
| 2763 | 660 | add_pid_to_program(prg, pid); | |
| 2764 |
1/2✓ Branch 0 taken 660 times.
✗ Branch 1 not taken.
|
660 | if (prg) { |
| 2765 | 660 | prg->streams[i].idx = st->index; | |
| 2766 | 660 | prg->streams[i].stream_identifier = stream_identifier; | |
| 2767 | 660 | prg->nb_streams++; | |
| 2768 | } | ||
| 2769 | |||
| 2770 | 660 | av_program_add_stream_index(ts->stream, h->id, st->index); | |
| 2771 | |||
| 2772 | 660 | desc_list_len = get16(&p, p_end); | |
| 2773 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 660 times.
|
660 | if (desc_list_len < 0) |
| 2774 | ✗ | goto out; | |
| 2775 | 660 | desc_list_len &= 0xfff; | |
| 2776 | 660 | desc_list_end = p + desc_list_len; | |
| 2777 |
1/2✓ Branch 0 taken 660 times.
✗ Branch 1 not taken.
|
660 | if (desc_list_end > p_end) |
| 2778 | ✗ | goto out; | |
| 2779 | for (;;) { | ||
| 2780 |
2/2✓ Branch 1 taken 660 times.
✓ Branch 2 taken 485 times.
|
1145 | if (ff_parse_mpeg2_descriptor(ts->stream, st, stream_type, h->id, &p, |
| 2781 | desc_list_end, mp4_descr, | ||
| 2782 | mp4_descr_count, pid, ts) < 0) | ||
| 2783 | 660 | break; | |
| 2784 | |||
| 2785 |
2/6✓ Branch 0 taken 485 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 485 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
485 | if (pes && prog_reg_desc == AV_RL32("HDMV") && |
| 2786 | ✗ | stream_type == STREAM_TYPE_BLURAY_AUDIO_TRUEHD && pes->sub_st) { | |
| 2787 | ✗ | av_program_add_stream_index(ts->stream, h->id, | |
| 2788 | ✗ | pes->sub_st->index); | |
| 2789 | ✗ | pes->sub_st->codecpar->codec_tag = st->codecpar->codec_tag; | |
| 2790 | } | ||
| 2791 | } | ||
| 2792 | 660 | p = desc_list_end; | |
| 2793 | } | ||
| 2794 | |||
| 2795 |
1/2✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
|
351 | if (!ts->pids[pcr_pid]) |
| 2796 | ✗ | mpegts_open_pcr_filter(ts, pcr_pid); | |
| 2797 | |||
| 2798 | 351 | out: | |
| 2799 |
1/2✓ Branch 0 taken 351 times.
✗ Branch 1 not taken.
|
351 | if (prg) |
| 2800 | 351 | create_stream_groups(ts, prg); | |
| 2801 | |||
| 2802 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 351 times.
|
351 | for (i = 0; i < mp4_descr_count; i++) |
| 2803 | ✗ | av_free(mp4_descr[i].dec_config_descr); | |
| 2804 | } | ||
| 2805 | |||
| 2806 | 3687 | static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) | |
| 2807 | { | ||
| 2808 | 3687 | MpegTSContext *ts = filter->u.section_filter.opaque; | |
| 2809 | 3687 | MpegTSSectionFilter *tssf = &filter->u.section_filter; | |
| 2810 | 3687 | SectionHeader h1, *h = &h1; | |
| 2811 | const uint8_t *p, *p_end; | ||
| 2812 | int sid, pmt_pid; | ||
| 2813 | 3687 | int nb_prg = 0; | |
| 2814 | AVProgram *program; | ||
| 2815 | |||
| 2816 | 3687 | av_log(ts->stream, AV_LOG_TRACE, "PAT:\n"); | |
| 2817 | hex_dump_debug(ts->stream, section, section_len); | ||
| 2818 | |||
| 2819 | 3687 | p_end = section + section_len - 4; | |
| 2820 | 3687 | p = section; | |
| 2821 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3687 times.
|
3687 | if (parse_section_header(h, &p, p_end) < 0) |
| 2822 | 3414 | return; | |
| 2823 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3687 times.
|
3687 | if (h->tid != PAT_TID) |
| 2824 | ✗ | return; | |
| 2825 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3687 times.
|
3687 | if (!h->current_next) |
| 2826 | ✗ | return; | |
| 2827 |
2/2✓ Branch 0 taken 712 times.
✓ Branch 1 taken 2975 times.
|
3687 | if (ts->skip_changes) |
| 2828 | 712 | return; | |
| 2829 | |||
| 2830 |
2/2✓ Branch 1 taken 2702 times.
✓ Branch 2 taken 273 times.
|
2975 | if (skip_identical(h, tssf)) |
| 2831 | 2702 | return; | |
| 2832 | 273 | ts->id = h->id; | |
| 2833 | |||
| 2834 | for (;;) { | ||
| 2835 | 546 | sid = get16(&p, p_end); | |
| 2836 |
2/2✓ Branch 0 taken 273 times.
✓ Branch 1 taken 273 times.
|
546 | if (sid < 0) |
| 2837 | 273 | break; | |
| 2838 | 273 | pmt_pid = get16(&p, p_end); | |
| 2839 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
|
273 | if (pmt_pid < 0) |
| 2840 | ✗ | break; | |
| 2841 | 273 | pmt_pid &= 0x1fff; | |
| 2842 | |||
| 2843 |
2/4✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 273 times.
|
273 | if (pmt_pid <= 0x000F || pmt_pid == 0x1FFF) { |
| 2844 | ✗ | av_log(ts->stream, AV_LOG_WARNING, | |
| 2845 | "Ignoring invalid PAT entry: sid=0x%x pid=0x%x\n", sid, pmt_pid); | ||
| 2846 | ✗ | continue; | |
| 2847 | } | ||
| 2848 | |||
| 2849 | 273 | av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x pid=0x%x\n", sid, pmt_pid); | |
| 2850 | |||
| 2851 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | if (sid == 0x0000) { |
| 2852 | /* NIT info */ | ||
| 2853 | } else { | ||
| 2854 | 273 | MpegTSFilter *fil = ts->pids[pmt_pid]; | |
| 2855 | struct Program *prg; | ||
| 2856 | 273 | program = av_new_program(ts->stream, sid); | |
| 2857 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | if (program) { |
| 2858 | 273 | program->program_num = sid; | |
| 2859 | 273 | program->pmt_pid = pmt_pid; | |
| 2860 | } | ||
| 2861 |
2/2✓ Branch 0 taken 197 times.
✓ Branch 1 taken 76 times.
|
273 | if (fil) |
| 2862 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | if ( fil->type != MPEGTS_SECTION |
| 2863 |
1/2✓ Branch 0 taken 197 times.
✗ Branch 1 not taken.
|
197 | || fil->pid != pmt_pid |
| 2864 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
|
197 | || fil->u.section_filter.section_cb != pmt_cb) |
| 2865 | ✗ | mpegts_close_filter(ts, ts->pids[pmt_pid]); | |
| 2866 | |||
| 2867 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 197 times.
|
273 | if (!ts->pids[pmt_pid]) |
| 2868 | 76 | mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); | |
| 2869 | 273 | prg = add_program(ts, sid); | |
| 2870 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | if (prg) { |
| 2871 | 273 | unsigned prg_idx = prg - ts->prg; | |
| 2872 |
3/4✓ Branch 0 taken 197 times.
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 197 times.
|
273 | if (prg->nb_pids && prg->pids[0] != pmt_pid) |
| 2873 | ✗ | clear_program(prg); | |
| 2874 | 273 | add_pid_to_program(prg, pmt_pid); | |
| 2875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
|
273 | if (prg_idx > nb_prg) |
| 2876 | ✗ | FFSWAP(struct Program, ts->prg[nb_prg], ts->prg[prg_idx]); | |
| 2877 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | if (prg_idx >= nb_prg) |
| 2878 | 273 | nb_prg++; | |
| 2879 | } else | ||
| 2880 | ✗ | nb_prg = 0; | |
| 2881 | } | ||
| 2882 | } | ||
| 2883 | 273 | ts->nb_prg = nb_prg; | |
| 2884 | |||
| 2885 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | if (sid < 0) { |
| 2886 | int i,j; | ||
| 2887 |
2/2✓ Branch 0 taken 273 times.
✓ Branch 1 taken 273 times.
|
546 | for (j=0; j<ts->stream->nb_programs; j++) { |
| 2888 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | for (i = 0; i < ts->nb_prg; i++) |
| 2889 |
1/2✓ Branch 0 taken 273 times.
✗ Branch 1 not taken.
|
273 | if (ts->prg[i].id == ts->stream->programs[j]->id) |
| 2890 | 273 | break; | |
| 2891 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 273 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
273 | if (i==ts->nb_prg && !ts->skip_clear) |
| 2892 | ✗ | clear_avprogram(ts, ts->stream->programs[j]->id); | |
| 2893 | } | ||
| 2894 | } | ||
| 2895 | } | ||
| 2896 | |||
| 2897 | 14 | static void eit_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) | |
| 2898 | { | ||
| 2899 | 14 | MpegTSContext *ts = filter->u.section_filter.opaque; | |
| 2900 | const uint8_t *p, *p_end; | ||
| 2901 | 14 | SectionHeader h1, *h = &h1; | |
| 2902 | |||
| 2903 | /* | ||
| 2904 | * Sometimes we receive EPG packets but SDT table do not have | ||
| 2905 | * eit_pres_following or eit_sched turned on, so we open EPG | ||
| 2906 | * stream directly here. | ||
| 2907 | */ | ||
| 2908 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
|
14 | if (!ts->epg_stream) { |
| 2909 | 3 | ts->epg_stream = avformat_new_stream(ts->stream, NULL); | |
| 2910 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!ts->epg_stream) |
| 2911 | 2 | return; | |
| 2912 | 3 | ts->epg_stream->id = EIT_PID; | |
| 2913 | 3 | ts->epg_stream->codecpar->codec_type = AVMEDIA_TYPE_DATA; | |
| 2914 | 3 | ts->epg_stream->codecpar->codec_id = AV_CODEC_ID_EPG; | |
| 2915 | } | ||
| 2916 | |||
| 2917 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
|
14 | if (ts->epg_stream->discard == AVDISCARD_ALL) |
| 2918 | 2 | return; | |
| 2919 | |||
| 2920 | 12 | p_end = section + section_len - 4; | |
| 2921 | 12 | p = section; | |
| 2922 | |||
| 2923 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | if (parse_section_header(h, &p, p_end) < 0) |
| 2924 | ✗ | return; | |
| 2925 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
12 | if (h->tid < EIT_TID || h->tid > OEITS_END_TID) |
| 2926 | ✗ | return; | |
| 2927 | |||
| 2928 | 12 | av_log(ts->stream, AV_LOG_TRACE, "EIT: tid received = %.02x\n", h->tid); | |
| 2929 | |||
| 2930 | /** | ||
| 2931 | * Service_id 0xFFFF is reserved, it indicates that the current EIT table | ||
| 2932 | * is scrambled. | ||
| 2933 | */ | ||
| 2934 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (h->id == 0xFFFF) { |
| 2935 | ✗ | av_log(ts->stream, AV_LOG_TRACE, "Scrambled EIT table received.\n"); | |
| 2936 | ✗ | return; | |
| 2937 | } | ||
| 2938 | |||
| 2939 | /** | ||
| 2940 | * In case we receive an EPG packet before mpegts context is fully | ||
| 2941 | * initialized. | ||
| 2942 | */ | ||
| 2943 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!ts->pkt) |
| 2944 | ✗ | return; | |
| 2945 | |||
| 2946 | 12 | new_data_packet(section, section_len, ts->pkt); | |
| 2947 | 12 | ts->pkt->stream_index = ts->epg_stream->index; | |
| 2948 | 12 | ts->stop_parse = 1; | |
| 2949 | } | ||
| 2950 | |||
| 2951 | 589 | static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) | |
| 2952 | { | ||
| 2953 | 589 | MpegTSContext *ts = filter->u.section_filter.opaque; | |
| 2954 | 589 | MpegTSSectionFilter *tssf = &filter->u.section_filter; | |
| 2955 | 589 | SectionHeader h1, *h = &h1; | |
| 2956 | const uint8_t *p, *p_end, *desc_list_end, *desc_end; | ||
| 2957 | int onid, val, sid, desc_list_len, desc_tag, desc_len, service_type; | ||
| 2958 | char *name, *provider_name; | ||
| 2959 | |||
| 2960 | 589 | av_log(ts->stream, AV_LOG_TRACE, "SDT:\n"); | |
| 2961 | hex_dump_debug(ts->stream, section, section_len); | ||
| 2962 | |||
| 2963 | 589 | p_end = section + section_len - 4; | |
| 2964 | 589 | p = section; | |
| 2965 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 589 times.
|
589 | if (parse_section_header(h, &p, p_end) < 0) |
| 2966 | 432 | return; | |
| 2967 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 589 times.
|
589 | if (h->tid != SDT_TID) |
| 2968 | ✗ | return; | |
| 2969 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 589 times.
|
589 | if (!h->current_next) |
| 2970 | ✗ | return; | |
| 2971 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 501 times.
|
589 | if (ts->skip_changes) |
| 2972 | 88 | return; | |
| 2973 |
2/2✓ Branch 1 taken 344 times.
✓ Branch 2 taken 157 times.
|
501 | if (skip_identical(h, tssf)) |
| 2974 | 344 | return; | |
| 2975 | |||
| 2976 | 157 | onid = get16(&p, p_end); | |
| 2977 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
|
157 | if (onid < 0) |
| 2978 | ✗ | return; | |
| 2979 | 157 | val = get8(&p, p_end); | |
| 2980 |
1/2✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
|
157 | if (val < 0) |
| 2981 | ✗ | return; | |
| 2982 | for (;;) { | ||
| 2983 | 314 | sid = get16(&p, p_end); | |
| 2984 |
2/2✓ Branch 0 taken 157 times.
✓ Branch 1 taken 157 times.
|
314 | if (sid < 0) |
| 2985 | 157 | break; | |
| 2986 | 157 | val = get8(&p, p_end); | |
| 2987 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
|
157 | if (val < 0) |
| 2988 | ✗ | break; | |
| 2989 | 157 | desc_list_len = get16(&p, p_end); | |
| 2990 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
|
157 | if (desc_list_len < 0) |
| 2991 | ✗ | break; | |
| 2992 | 157 | desc_list_len &= 0xfff; | |
| 2993 | 157 | desc_list_end = p + desc_list_len; | |
| 2994 |
1/2✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
|
157 | if (desc_list_end > p_end) |
| 2995 | ✗ | break; | |
| 2996 | for (;;) { | ||
| 2997 | 314 | desc_tag = get8(&p, desc_list_end); | |
| 2998 |
2/2✓ Branch 0 taken 157 times.
✓ Branch 1 taken 157 times.
|
314 | if (desc_tag < 0) |
| 2999 | 157 | break; | |
| 3000 | 157 | desc_len = get8(&p, desc_list_end); | |
| 3001 | 157 | desc_end = p + desc_len; | |
| 3002 |
2/4✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
|
157 | if (desc_len < 0 || desc_end > desc_list_end) |
| 3003 | break; | ||
| 3004 | |||
| 3005 | 157 | av_log(ts->stream, AV_LOG_TRACE, "tag: 0x%02x len=%d\n", | |
| 3006 | desc_tag, desc_len); | ||
| 3007 | |||
| 3008 |
1/2✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
|
157 | switch (desc_tag) { |
| 3009 | 157 | case SERVICE_DESCRIPTOR: | |
| 3010 | 157 | service_type = get8(&p, desc_end); | |
| 3011 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
|
157 | if (service_type < 0) |
| 3012 | ✗ | break; | |
| 3013 | 157 | provider_name = getstr8(&p, desc_end); | |
| 3014 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
|
157 | if (!provider_name) |
| 3015 | ✗ | break; | |
| 3016 | 157 | name = getstr8(&p, desc_end); | |
| 3017 |
1/2✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
|
157 | if (name) { |
| 3018 | 157 | AVProgram *program = av_new_program(ts->stream, sid); | |
| 3019 |
1/2✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
|
157 | if (program) { |
| 3020 | 157 | av_dict_set(&program->metadata, "service_name", name, 0); | |
| 3021 | 157 | av_dict_set(&program->metadata, "service_provider", | |
| 3022 | provider_name, 0); | ||
| 3023 | } | ||
| 3024 | } | ||
| 3025 | 157 | av_free(name); | |
| 3026 | 157 | av_free(provider_name); | |
| 3027 | 157 | break; | |
| 3028 | ✗ | default: | |
| 3029 | ✗ | break; | |
| 3030 | } | ||
| 3031 | 157 | p = desc_end; | |
| 3032 | } | ||
| 3033 | 157 | p = desc_list_end; | |
| 3034 | } | ||
| 3035 | } | ||
| 3036 | |||
| 3037 | static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, | ||
| 3038 | const uint8_t *packet); | ||
| 3039 | |||
| 3040 | /* handle one TS packet */ | ||
| 3041 | 455748 | static int handle_packet(MpegTSContext *ts, const uint8_t *packet, int64_t pos) | |
| 3042 | { | ||
| 3043 | MpegTSFilter *tss; | ||
| 3044 | int len, pid, cc, expected_cc, cc_ok, afc, is_start, is_discontinuity, | ||
| 3045 | has_adaptation, has_payload; | ||
| 3046 | const uint8_t *p, *p_end; | ||
| 3047 | |||
| 3048 | 455748 | pid = AV_RB16(packet + 1) & 0x1fff; | |
| 3049 | 455748 | is_start = packet[1] & 0x40; | |
| 3050 | 455748 | tss = ts->pids[pid]; | |
| 3051 |
6/6✓ Branch 0 taken 447437 times.
✓ Branch 1 taken 8311 times.
✓ Branch 2 taken 7752 times.
✓ Branch 3 taken 439685 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 7734 times.
|
455748 | if (ts->auto_guess && !tss && is_start) { |
| 3052 | 18 | add_pes_stream(ts, pid, -1); | |
| 3053 | 18 | tss = ts->pids[pid]; | |
| 3054 | } | ||
| 3055 |
2/2✓ Branch 0 taken 15842 times.
✓ Branch 1 taken 439906 times.
|
455748 | if (!tss) |
| 3056 | 15842 | return 0; | |
| 3057 |
2/2✓ Branch 0 taken 43024 times.
✓ Branch 1 taken 396882 times.
|
439906 | if (is_start) |
| 3058 | 43024 | tss->discard = discard_pid(ts, pid); | |
| 3059 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 439906 times.
|
439906 | if (tss->discard) |
| 3060 | ✗ | return 0; | |
| 3061 | 439906 | ts->current_pid = pid; | |
| 3062 | |||
| 3063 | 439906 | afc = (packet[3] >> 4) & 3; | |
| 3064 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 439906 times.
|
439906 | if (afc == 0) /* reserved value */ |
| 3065 | ✗ | return 0; | |
| 3066 | 439906 | has_adaptation = afc & 2; | |
| 3067 | 439906 | has_payload = afc & 1; | |
| 3068 | 508821 | is_discontinuity = has_adaptation && | |
| 3069 |
4/4✓ Branch 0 taken 68915 times.
✓ Branch 1 taken 370991 times.
✓ Branch 2 taken 68873 times.
✓ Branch 3 taken 42 times.
|
508779 | packet[4] != 0 && /* with length > 0 */ |
| 3070 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 68873 times.
|
68873 | (packet[5] & 0x80); /* and discontinuity indicated */ |
| 3071 | |||
| 3072 | /* continuity check (currently not used) */ | ||
| 3073 | 439906 | cc = (packet[3] & 0xf); | |
| 3074 |
2/2✓ Branch 0 taken 436987 times.
✓ Branch 1 taken 2919 times.
|
439906 | expected_cc = has_payload ? (tss->last_cc + 1) & 0x0f : tss->last_cc; |
| 3075 |
1/2✓ Branch 0 taken 439906 times.
✗ Branch 1 not taken.
|
439906 | cc_ok = pid == NULL_PID || |
| 3076 | 439906 | is_discontinuity || | |
| 3077 |
5/6✓ Branch 0 taken 439906 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 438451 times.
✓ Branch 3 taken 1455 times.
✓ Branch 4 taken 437803 times.
✓ Branch 5 taken 648 times.
|
879812 | tss->last_cc < 0 || |
| 3078 | expected_cc == cc; | ||
| 3079 | |||
| 3080 | 439906 | tss->last_cc = cc; | |
| 3081 |
2/2✓ Branch 0 taken 648 times.
✓ Branch 1 taken 439258 times.
|
439906 | if (!cc_ok) { |
| 3082 | 648 | av_log(ts->stream, AV_LOG_DEBUG, | |
| 3083 | "Continuity check failed for pid %d expected %d got %d\n", | ||
| 3084 | pid, expected_cc, cc); | ||
| 3085 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 641 times.
|
648 | if (tss->type == MPEGTS_PES) { |
| 3086 | 7 | PESContext *pc = tss->u.pes_filter.opaque; | |
| 3087 | 7 | pc->flags |= AV_PKT_FLAG_CORRUPT; | |
| 3088 | } | ||
| 3089 | } | ||
| 3090 | |||
| 3091 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 439893 times.
|
439906 | if (packet[1] & 0x80) { |
| 3092 | 13 | av_log(ts->stream, AV_LOG_DEBUG, "Packet had TEI flag set; marking as corrupt\n"); | |
| 3093 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (tss->type == MPEGTS_PES) { |
| 3094 | 13 | PESContext *pc = tss->u.pes_filter.opaque; | |
| 3095 | 13 | pc->flags |= AV_PKT_FLAG_CORRUPT; | |
| 3096 | } | ||
| 3097 | } | ||
| 3098 | |||
| 3099 | 439906 | p = packet + 4; | |
| 3100 |
2/2✓ Branch 0 taken 68915 times.
✓ Branch 1 taken 370991 times.
|
439906 | if (has_adaptation) { |
| 3101 | int64_t pcr_h; | ||
| 3102 | int pcr_l; | ||
| 3103 |
2/2✓ Branch 1 taken 31712 times.
✓ Branch 2 taken 37203 times.
|
68915 | if (parse_pcr(&pcr_h, &pcr_l, packet) == 0) |
| 3104 | 31712 | tss->last_pcr = pcr_h * SYSTEM_CLOCK_FREQUENCY_DIVISOR + pcr_l; | |
| 3105 | /* skip adaptation field */ | ||
| 3106 | 68915 | p += p[0] + 1; | |
| 3107 | } | ||
| 3108 | /* if past the end of packet, ignore */ | ||
| 3109 | 439906 | p_end = packet + TS_PACKET_SIZE; | |
| 3110 |
3/4✓ Branch 0 taken 436974 times.
✓ Branch 1 taken 2932 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 436974 times.
|
439906 | if (p >= p_end || !has_payload) |
| 3111 | 2932 | return 0; | |
| 3112 | |||
| 3113 |
1/2✓ Branch 0 taken 436974 times.
✗ Branch 1 not taken.
|
436974 | if (pos >= 0) { |
| 3114 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 436974 times.
|
436974 | av_assert0(pos >= TS_PACKET_SIZE); |
| 3115 | 436974 | ts->pos47_full = pos - TS_PACKET_SIZE; | |
| 3116 | } | ||
| 3117 | |||
| 3118 |
2/2✓ Branch 0 taken 7985 times.
✓ Branch 1 taken 428989 times.
|
436974 | if (tss->type == MPEGTS_SECTION) { |
| 3119 |
2/2✓ Branch 0 taken 7950 times.
✓ Branch 1 taken 35 times.
|
7985 | if (is_start) { |
| 3120 | /* pointer field present */ | ||
| 3121 | 7950 | len = *p++; | |
| 3122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7950 times.
|
7950 | if (len > p_end - p) |
| 3123 | ✗ | return 0; | |
| 3124 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 7950 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
7950 | if (len && cc_ok) { |
| 3125 | /* write remaining section bytes */ | ||
| 3126 | ✗ | write_section_data(ts, tss, | |
| 3127 | p, len, 0); | ||
| 3128 | /* check whether filter has been closed */ | ||
| 3129 | ✗ | if (!ts->pids[pid]) | |
| 3130 | ✗ | return 0; | |
| 3131 | } | ||
| 3132 | 7950 | p += len; | |
| 3133 |
1/2✓ Branch 0 taken 7950 times.
✗ Branch 1 not taken.
|
7950 | if (p < p_end) { |
| 3134 | 7950 | write_section_data(ts, tss, | |
| 3135 | 7950 | p, p_end - p, 1); | |
| 3136 | } | ||
| 3137 | } else { | ||
| 3138 |
1/2✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
|
35 | if (cc_ok) { |
| 3139 | 35 | write_section_data(ts, tss, | |
| 3140 | 35 | p, p_end - p, 0); | |
| 3141 | } | ||
| 3142 | } | ||
| 3143 | |||
| 3144 | // stop find_stream_info from waiting for more streams | ||
| 3145 | // when all programs have received a PMT | ||
| 3146 |
4/4✓ Branch 0 taken 5411 times.
✓ Branch 1 taken 2574 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 5392 times.
|
7985 | if (ts->stream->ctx_flags & AVFMTCTX_NOHEADER && ts->scan_all_pmts <= 0) { |
| 3147 | int i; | ||
| 3148 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 19 times.
|
38 | for (i = 0; i < ts->nb_prg; i++) { |
| 3149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if (!ts->prg[i].pmt_found) |
| 3150 | ✗ | break; | |
| 3151 | } | ||
| 3152 |
2/4✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
19 | if (i == ts->nb_prg && ts->nb_prg > 0) { |
| 3153 | 19 | av_log(ts->stream, AV_LOG_DEBUG, "All programs have pmt, headers found\n"); | |
| 3154 | 19 | ts->stream->ctx_flags &= ~AVFMTCTX_NOHEADER; | |
| 3155 | } | ||
| 3156 | } | ||
| 3157 | |||
| 3158 | } else { | ||
| 3159 | int ret; | ||
| 3160 | // Note: The position here points actually behind the current packet. | ||
| 3161 |
1/2✓ Branch 0 taken 428989 times.
✗ Branch 1 not taken.
|
428989 | if (tss->type == MPEGTS_PES) { |
| 3162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 428989 times.
|
428989 | if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, |
| 3163 | 428989 | pos - ts->raw_packet_size)) < 0) | |
| 3164 | ✗ | return ret; | |
| 3165 | } | ||
| 3166 | } | ||
| 3167 | |||
| 3168 | 436974 | return 0; | |
| 3169 | } | ||
| 3170 | |||
| 3171 | 66 | static int mpegts_resync(AVFormatContext *s, int seekback, const uint8_t *current_packet) | |
| 3172 | { | ||
| 3173 | 66 | MpegTSContext *ts = s->priv_data; | |
| 3174 | 66 | AVIOContext *pb = s->pb; | |
| 3175 | int c, i; | ||
| 3176 | 66 | uint64_t pos = avio_tell(pb); | |
| 3177 | 66 | int64_t back = FFMIN(seekback, pos); | |
| 3178 | |||
| 3179 | //Special case for files like 01c56b0dc1.ts | ||
| 3180 |
3/6✓ Branch 0 taken 6 times.
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
66 | if (current_packet[0] == 0x80 && current_packet[12] == SYNC_BYTE && pos >= TS_PACKET_SIZE) { |
| 3181 | ✗ | avio_seek(pb, 12 - TS_PACKET_SIZE, SEEK_CUR); | |
| 3182 | ✗ | return 0; | |
| 3183 | } | ||
| 3184 | |||
| 3185 | 66 | avio_seek(pb, -back, SEEK_CUR); | |
| 3186 | |||
| 3187 |
1/2✓ Branch 0 taken 4580 times.
✗ Branch 1 not taken.
|
4580 | for (i = 0; i < ts->resync_size; i++) { |
| 3188 | 4580 | c = avio_r8(pb); | |
| 3189 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4580 times.
|
4580 | if (avio_feof(pb)) |
| 3190 | ✗ | return AVERROR_EOF; | |
| 3191 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 4514 times.
|
4580 | if (c == SYNC_BYTE) { |
| 3192 | int new_packet_size, ret; | ||
| 3193 | 66 | avio_seek(pb, -1, SEEK_CUR); | |
| 3194 | 66 | pos = avio_tell(pb); | |
| 3195 | 66 | ret = ffio_ensure_seekback(pb, PROBE_PACKET_MAX_BUF); | |
| 3196 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
|
66 | if (ret < 0) |
| 3197 | ✗ | return ret; | |
| 3198 | 66 | new_packet_size = get_packet_size(s); | |
| 3199 |
2/4✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
|
66 | if (new_packet_size > 0 && new_packet_size != ts->raw_packet_size) { |
| 3200 | ✗ | av_log(ts->stream, AV_LOG_WARNING, "changing packet size to %d\n", new_packet_size); | |
| 3201 | ✗ | ts->raw_packet_size = new_packet_size; | |
| 3202 | } | ||
| 3203 | 66 | avio_seek(pb, pos, SEEK_SET); | |
| 3204 | 66 | return 0; | |
| 3205 | } | ||
| 3206 | } | ||
| 3207 | ✗ | av_log(s, AV_LOG_ERROR, | |
| 3208 | "max resync size reached, could not find sync byte\n"); | ||
| 3209 | /* no sync found */ | ||
| 3210 | ✗ | return AVERROR_INVALIDDATA; | |
| 3211 | } | ||
| 3212 | |||
| 3213 | /* return AVERROR_something if error or EOF. Return 0 if OK. */ | ||
| 3214 | 456247 | static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size, | |
| 3215 | const uint8_t **data) | ||
| 3216 | { | ||
| 3217 | 456247 | AVIOContext *pb = s->pb; | |
| 3218 | int len; | ||
| 3219 | |||
| 3220 | // 192 bytes source packet that start with a 4 bytes TP_extra_header | ||
| 3221 | // followed by 188 bytes of TS packet. The sync byte is at offset 4, so skip | ||
| 3222 | // the first 4 bytes otherwise we'll end up syncing to the wrong packet. | ||
| 3223 |
2/2✓ Branch 0 taken 27772 times.
✓ Branch 1 taken 428475 times.
|
456247 | if (raw_packet_size == TS_DVHS_PACKET_SIZE) |
| 3224 | 27772 | avio_skip(pb, 4); | |
| 3225 | |||
| 3226 | for (;;) { | ||
| 3227 | 456313 | len = ffio_read_indirect(pb, buf, TS_PACKET_SIZE, data); | |
| 3228 |
2/2✓ Branch 0 taken 499 times.
✓ Branch 1 taken 455814 times.
|
456313 | if (len != TS_PACKET_SIZE) |
| 3229 |
2/2✓ Branch 0 taken 441 times.
✓ Branch 1 taken 58 times.
|
499 | return len < 0 ? len : AVERROR_EOF; |
| 3230 | /* check packet sync byte */ | ||
| 3231 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 455748 times.
|
455814 | if ((*data)[0] != SYNC_BYTE) { |
| 3232 | /* find a new packet start */ | ||
| 3233 | |||
| 3234 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
|
66 | if (mpegts_resync(s, raw_packet_size, *data) < 0) |
| 3235 | ✗ | return AVERROR(EAGAIN); | |
| 3236 | else | ||
| 3237 | 66 | continue; | |
| 3238 | } else { | ||
| 3239 | 455748 | break; | |
| 3240 | } | ||
| 3241 | } | ||
| 3242 | 455748 | return 0; | |
| 3243 | } | ||
| 3244 | |||
| 3245 | 455748 | static void finished_reading_packet(AVFormatContext *s, int raw_packet_size) | |
| 3246 | { | ||
| 3247 | 455748 | AVIOContext *pb = s->pb; | |
| 3248 | int skip; | ||
| 3249 |
2/2✓ Branch 0 taken 27754 times.
✓ Branch 1 taken 427994 times.
|
455748 | if (raw_packet_size == TS_DVHS_PACKET_SIZE) |
| 3250 | 27754 | skip = raw_packet_size - TS_DVHS_PACKET_SIZE; | |
| 3251 | else | ||
| 3252 | 427994 | skip = raw_packet_size - TS_PACKET_SIZE; | |
| 3253 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 455748 times.
|
455748 | if (skip > 0) |
| 3254 | ✗ | avio_skip(pb, skip); | |
| 3255 | 455748 | } | |
| 3256 | |||
| 3257 | 34731 | static int handle_packets(MpegTSContext *ts, int64_t nb_packets) | |
| 3258 | { | ||
| 3259 | 34731 | AVFormatContext *s = ts->stream; | |
| 3260 | uint8_t packet[TS_PACKET_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; | ||
| 3261 | const uint8_t *data; | ||
| 3262 | int64_t packet_num; | ||
| 3263 | 34731 | int ret = 0; | |
| 3264 | |||
| 3265 |
2/2✓ Branch 1 taken 319 times.
✓ Branch 2 taken 34412 times.
|
34731 | if (avio_tell(s->pb) != ts->last_pos) { |
| 3266 | int i; | ||
| 3267 | 319 | av_log(ts->stream, AV_LOG_TRACE, "Skipping after seek\n"); | |
| 3268 | /* seek detected, flush pes buffer */ | ||
| 3269 |
2/2✓ Branch 0 taken 2613248 times.
✓ Branch 1 taken 319 times.
|
2613567 | for (i = 0; i < NB_PID_MAX; i++) { |
| 3270 |
2/2✓ Branch 0 taken 1934 times.
✓ Branch 1 taken 2611314 times.
|
2613248 | if (ts->pids[i]) { |
| 3271 |
2/2✓ Branch 0 taken 634 times.
✓ Branch 1 taken 1300 times.
|
1934 | if (ts->pids[i]->type == MPEGTS_PES) { |
| 3272 | 634 | PESContext *pes = ts->pids[i]->u.pes_filter.opaque; | |
| 3273 | 634 | av_buffer_unref(&pes->buffer); | |
| 3274 | 634 | pes->data_index = 0; | |
| 3275 | 634 | pes->state = MPEGTS_SKIP; /* skip until pes header */ | |
| 3276 |
1/2✓ Branch 0 taken 1300 times.
✗ Branch 1 not taken.
|
1300 | } else if (ts->pids[i]->type == MPEGTS_SECTION) { |
| 3277 | 1300 | ts->pids[i]->u.section_filter.last_ver = -1; | |
| 3278 | } | ||
| 3279 | 1934 | ts->pids[i]->last_cc = -1; | |
| 3280 | 1934 | ts->pids[i]->last_pcr = -1; | |
| 3281 | } | ||
| 3282 | } | ||
| 3283 | } | ||
| 3284 | |||
| 3285 | 34731 | ts->stop_parse = 0; | |
| 3286 | 34731 | packet_num = 0; | |
| 3287 | 34731 | memset(packet + TS_PACKET_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
| 3288 | for (;;) { | ||
| 3289 | 490479 | packet_num++; | |
| 3290 |
3/4✓ Branch 0 taken 8387 times.
✓ Branch 1 taken 482092 times.
✓ Branch 2 taken 8387 times.
✗ Branch 3 not taken.
|
490479 | if (nb_packets != 0 && packet_num >= nb_packets || |
| 3291 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 490403 times.
|
490479 | ts->stop_parse > 1) { |
| 3292 | 76 | ret = AVERROR(EAGAIN); | |
| 3293 | 76 | break; | |
| 3294 | } | ||
| 3295 |
2/2✓ Branch 0 taken 34156 times.
✓ Branch 1 taken 456247 times.
|
490403 | if (ts->stop_parse > 0) |
| 3296 | 34156 | break; | |
| 3297 | |||
| 3298 | 456247 | ret = read_packet(s, packet, ts->raw_packet_size, &data); | |
| 3299 |
2/2✓ Branch 0 taken 499 times.
✓ Branch 1 taken 455748 times.
|
456247 | if (ret != 0) |
| 3300 | 499 | break; | |
| 3301 | 455748 | ret = handle_packet(ts, data, avio_tell(s->pb)); | |
| 3302 | 455748 | finished_reading_packet(s, ts->raw_packet_size); | |
| 3303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 455748 times.
|
455748 | if (ret != 0) |
| 3304 | ✗ | break; | |
| 3305 | } | ||
| 3306 | 34731 | ts->last_pos = avio_tell(s->pb); | |
| 3307 | 34731 | return ret; | |
| 3308 | } | ||
| 3309 | |||
| 3310 | 7480 | static int mpegts_probe(const AVProbeData *p) | |
| 3311 | { | ||
| 3312 | 7480 | const int size = p->buf_size; | |
| 3313 | 7480 | int maxscore = 0; | |
| 3314 | 7480 | int sumscore = 0; | |
| 3315 | int i; | ||
| 3316 | 7480 | int check_count = size / TS_FEC_PACKET_SIZE; | |
| 3317 | #define CHECK_COUNT 10 | ||
| 3318 | #define CHECK_BLOCK 100 | ||
| 3319 | |||
| 3320 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 7465 times.
|
7480 | if (!check_count) |
| 3321 | 15 | return 0; | |
| 3322 | |||
| 3323 |
2/2✓ Branch 0 taken 25745 times.
✓ Branch 1 taken 7465 times.
|
33210 | for (i = 0; i<check_count; i+=CHECK_BLOCK) { |
| 3324 | 25745 | int left = FFMIN(check_count - i, CHECK_BLOCK); | |
| 3325 | 25745 | int score = analyze(p->buf + TS_PACKET_SIZE *i, TS_PACKET_SIZE *left, TS_PACKET_SIZE , 1); | |
| 3326 | 25745 | int dvhs_score = analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, 1); | |
| 3327 | 25745 | int fec_score = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , 1); | |
| 3328 | 25745 | score = FFMAX3(score, dvhs_score, fec_score); | |
| 3329 | 25745 | sumscore += score; | |
| 3330 | 25745 | maxscore = FFMAX(maxscore, score); | |
| 3331 | } | ||
| 3332 | |||
| 3333 | 7465 | sumscore = sumscore * CHECK_COUNT / check_count; | |
| 3334 | 7465 | maxscore = maxscore * CHECK_COUNT / CHECK_BLOCK; | |
| 3335 | |||
| 3336 | ff_dlog(0, "TS score: %d %d\n", sumscore, maxscore); | ||
| 3337 | |||
| 3338 |
3/4✓ Branch 0 taken 3352 times.
✓ Branch 1 taken 4113 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3352 times.
|
7465 | if (check_count > CHECK_COUNT && sumscore > 6) { |
| 3339 | ✗ | return AVPROBE_SCORE_MAX + sumscore - CHECK_COUNT; | |
| 3340 |
4/4✓ Branch 0 taken 7105 times.
✓ Branch 1 taken 360 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 7043 times.
|
7465 | } else if (check_count >= CHECK_COUNT && sumscore > 6) { |
| 3341 | 62 | return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT; | |
| 3342 |
3/4✓ Branch 0 taken 7043 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7043 times.
|
7403 | } else if (check_count >= CHECK_COUNT && maxscore > 6) { |
| 3343 | ✗ | return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT; | |
| 3344 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7398 times.
|
7403 | } else if (sumscore > 6) { |
| 3345 | 5 | return 2; | |
| 3346 | } else { | ||
| 3347 | 7398 | return 0; | |
| 3348 | } | ||
| 3349 | } | ||
| 3350 | |||
| 3351 | /* return the 90kHz PCR and the extension for the 27MHz PCR. return | ||
| 3352 | * (-1) if not available */ | ||
| 3353 | 68915 | static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, const uint8_t *packet) | |
| 3354 | { | ||
| 3355 | int afc, len, flags; | ||
| 3356 | const uint8_t *p; | ||
| 3357 | unsigned int v; | ||
| 3358 | |||
| 3359 | 68915 | afc = (packet[3] >> 4) & 3; | |
| 3360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 68915 times.
|
68915 | if (afc <= 1) |
| 3361 | ✗ | return AVERROR_INVALIDDATA; | |
| 3362 | 68915 | p = packet + 4; | |
| 3363 | 68915 | len = p[0]; | |
| 3364 | 68915 | p++; | |
| 3365 |
2/2✓ Branch 0 taken 42 times.
✓ Branch 1 taken 68873 times.
|
68915 | if (len == 0) |
| 3366 | 42 | return AVERROR_INVALIDDATA; | |
| 3367 | 68873 | flags = *p++; | |
| 3368 | 68873 | len--; | |
| 3369 |
2/2✓ Branch 0 taken 37161 times.
✓ Branch 1 taken 31712 times.
|
68873 | if (!(flags & 0x10)) |
| 3370 | 37161 | return AVERROR_INVALIDDATA; | |
| 3371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31712 times.
|
31712 | if (len < 6) |
| 3372 | ✗ | return AVERROR_INVALIDDATA; | |
| 3373 | 31712 | v = AV_RB32(p); | |
| 3374 | 31712 | *ppcr_high = ((int64_t) v << 1) | (p[4] >> 7); | |
| 3375 | 31712 | *ppcr_low = ((p[4] & 1) << 8) | p[5]; | |
| 3376 | 31712 | return 0; | |
| 3377 | } | ||
| 3378 | |||
| 3379 | 152 | static void seek_back(AVFormatContext *s, AVIOContext *pb, int64_t pos) { | |
| 3380 | |||
| 3381 | /* NOTE: We attempt to seek on non-seekable files as well, as the | ||
| 3382 | * probe buffer usually is big enough. Only warn if the seek failed | ||
| 3383 | * on files where the seek should work. */ | ||
| 3384 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 152 times.
|
152 | if (avio_seek(pb, pos, SEEK_SET) < 0) |
| 3385 | ✗ | av_log(s, (pb->seekable & AVIO_SEEKABLE_NORMAL) ? AV_LOG_ERROR : AV_LOG_INFO, "Unable to seek back to the start\n"); | |
| 3386 | 152 | } | |
| 3387 | |||
| 3388 | 76 | static int mpegts_read_header(AVFormatContext *s) | |
| 3389 | { | ||
| 3390 | 76 | MpegTSContext *ts = s->priv_data; | |
| 3391 | 76 | AVIOContext *pb = s->pb; | |
| 3392 | 76 | int64_t pos, probesize = s->probesize; | |
| 3393 | 76 | int64_t seekback = FFMAX(s->probesize, (int64_t)ts->resync_size + PROBE_PACKET_MAX_BUF); | |
| 3394 | |||
| 3395 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
|
76 | if (ffio_ensure_seekback(pb, seekback) < 0) |
| 3396 | ✗ | av_log(s, AV_LOG_WARNING, "Failed to allocate buffers for seekback\n"); | |
| 3397 | |||
| 3398 | 76 | pos = avio_tell(pb); | |
| 3399 | 76 | ts->raw_packet_size = get_packet_size(s); | |
| 3400 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
|
76 | if (ts->raw_packet_size <= 0) { |
| 3401 | ✗ | av_log(s, AV_LOG_WARNING, "Could not detect TS packet size, defaulting to non-FEC/DVHS\n"); | |
| 3402 | ✗ | ts->raw_packet_size = TS_PACKET_SIZE; | |
| 3403 | } | ||
| 3404 | 76 | ts->stream = s; | |
| 3405 | 76 | ts->auto_guess = 0; | |
| 3406 | |||
| 3407 |
1/2✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
|
76 | if (s->iformat == &ff_mpegts_demuxer.p) { |
| 3408 | /* normal demux */ | ||
| 3409 | |||
| 3410 | /* first do a scan to get all the services */ | ||
| 3411 | 76 | seek_back(s, pb, pos); | |
| 3412 | |||
| 3413 | 76 | mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); | |
| 3414 | 76 | mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); | |
| 3415 | 76 | mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1); | |
| 3416 | |||
| 3417 | 76 | handle_packets(ts, probesize / ts->raw_packet_size); | |
| 3418 | /* if could not find service, enable auto_guess */ | ||
| 3419 | |||
| 3420 | 76 | ts->auto_guess = 1; | |
| 3421 | |||
| 3422 | 76 | av_log(ts->stream, AV_LOG_TRACE, "tuning done\n"); | |
| 3423 | |||
| 3424 | 76 | s->ctx_flags |= AVFMTCTX_NOHEADER; | |
| 3425 | } else { | ||
| 3426 | AVStream *st; | ||
| 3427 | int pcr_pid, pid, nb_packets, nb_pcrs, ret, pcr_l; | ||
| 3428 | int64_t pcrs[2], pcr_h; | ||
| 3429 | uint8_t packet[TS_PACKET_SIZE]; | ||
| 3430 | const uint8_t *data; | ||
| 3431 | |||
| 3432 | /* only read packets */ | ||
| 3433 | |||
| 3434 | ✗ | st = avformat_new_stream(s, NULL); | |
| 3435 | ✗ | if (!st) | |
| 3436 | ✗ | return AVERROR(ENOMEM); | |
| 3437 | ✗ | avpriv_set_pts_info(st, 60, 1, 27000000); | |
| 3438 | ✗ | st->codecpar->codec_type = AVMEDIA_TYPE_DATA; | |
| 3439 | ✗ | st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS; | |
| 3440 | |||
| 3441 | /* we iterate until we find two PCRs to estimate the bitrate */ | ||
| 3442 | ✗ | pcr_pid = -1; | |
| 3443 | ✗ | nb_pcrs = 0; | |
| 3444 | ✗ | nb_packets = 0; | |
| 3445 | for (;;) { | ||
| 3446 | ✗ | ret = read_packet(s, packet, ts->raw_packet_size, &data); | |
| 3447 | ✗ | if (ret < 0) | |
| 3448 | ✗ | return ret; | |
| 3449 | ✗ | pid = AV_RB16(data + 1) & 0x1fff; | |
| 3450 | ✗ | if ((pcr_pid == -1 || pcr_pid == pid) && | |
| 3451 | ✗ | parse_pcr(&pcr_h, &pcr_l, data) == 0) { | |
| 3452 | ✗ | finished_reading_packet(s, ts->raw_packet_size); | |
| 3453 | ✗ | pcr_pid = pid; | |
| 3454 | ✗ | pcrs[nb_pcrs] = pcr_h * SYSTEM_CLOCK_FREQUENCY_DIVISOR + pcr_l; | |
| 3455 | ✗ | nb_pcrs++; | |
| 3456 | ✗ | if (nb_pcrs >= 2) { | |
| 3457 | ✗ | if (pcrs[1] - pcrs[0] > 0) { | |
| 3458 | /* the difference needs to be positive to make sense for bitrate computation */ | ||
| 3459 | ✗ | break; | |
| 3460 | } else { | ||
| 3461 | ✗ | av_log(ts->stream, AV_LOG_WARNING, "invalid pcr pair %"PRId64" >= %"PRId64"\n", pcrs[0], pcrs[1]); | |
| 3462 | ✗ | pcrs[0] = pcrs[1]; | |
| 3463 | ✗ | nb_pcrs--; | |
| 3464 | } | ||
| 3465 | } | ||
| 3466 | } else { | ||
| 3467 | ✗ | finished_reading_packet(s, ts->raw_packet_size); | |
| 3468 | } | ||
| 3469 | ✗ | nb_packets++; | |
| 3470 | } | ||
| 3471 | |||
| 3472 | /* NOTE1: the bitrate is computed without the FEC */ | ||
| 3473 | /* NOTE2: it is only the bitrate of the start of the stream */ | ||
| 3474 | ✗ | ts->pcr_incr = pcrs[1] - pcrs[0]; | |
| 3475 | ✗ | ts->cur_pcr = pcrs[0] - ts->pcr_incr * (nb_packets - 1); | |
| 3476 | ✗ | s->bit_rate = TS_PACKET_SIZE * 8 * 27000000LL / ts->pcr_incr; | |
| 3477 | ✗ | st->codecpar->bit_rate = s->bit_rate; | |
| 3478 | ✗ | st->start_time = ts->cur_pcr; | |
| 3479 | ✗ | av_log(ts->stream, AV_LOG_TRACE, "start=%0.3f pcr=%0.3f incr=%"PRId64"\n", | |
| 3480 | ✗ | st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); | |
| 3481 | } | ||
| 3482 | |||
| 3483 | 76 | seek_back(s, pb, pos); | |
| 3484 | 76 | return 0; | |
| 3485 | } | ||
| 3486 | |||
| 3487 | #define MAX_PACKET_READAHEAD ((128 * 1024) / 188) | ||
| 3488 | |||
| 3489 | ✗ | static int mpegts_raw_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 3490 | { | ||
| 3491 | ✗ | MpegTSContext *ts = s->priv_data; | |
| 3492 | int ret, i; | ||
| 3493 | int64_t pcr_h, next_pcr_h, pos; | ||
| 3494 | int pcr_l, next_pcr_l; | ||
| 3495 | uint8_t pcr_buf[12]; | ||
| 3496 | const uint8_t *data; | ||
| 3497 | |||
| 3498 | ✗ | if ((ret = av_new_packet(pkt, TS_PACKET_SIZE)) < 0) | |
| 3499 | ✗ | return ret; | |
| 3500 | ✗ | ret = read_packet(s, pkt->data, ts->raw_packet_size, &data); | |
| 3501 | ✗ | pkt->pos = avio_tell(s->pb); | |
| 3502 | ✗ | if (ret < 0) { | |
| 3503 | ✗ | return ret; | |
| 3504 | } | ||
| 3505 | ✗ | if (data != pkt->data) | |
| 3506 | ✗ | memcpy(pkt->data, data, TS_PACKET_SIZE); | |
| 3507 | ✗ | finished_reading_packet(s, ts->raw_packet_size); | |
| 3508 | ✗ | if (ts->mpeg2ts_compute_pcr) { | |
| 3509 | /* compute exact PCR for each packet */ | ||
| 3510 | ✗ | if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) { | |
| 3511 | /* we read the next PCR (XXX: optimize it by using a bigger buffer */ | ||
| 3512 | ✗ | pos = avio_tell(s->pb); | |
| 3513 | ✗ | for (i = 0; i < MAX_PACKET_READAHEAD; i++) { | |
| 3514 | ✗ | avio_seek(s->pb, pos + i * ts->raw_packet_size, SEEK_SET); | |
| 3515 | ✗ | avio_read(s->pb, pcr_buf, 12); | |
| 3516 | ✗ | if (parse_pcr(&next_pcr_h, &next_pcr_l, pcr_buf) == 0) { | |
| 3517 | /* XXX: not precise enough */ | ||
| 3518 | ✗ | ts->pcr_incr = | |
| 3519 | ✗ | ((next_pcr_h - pcr_h) * SYSTEM_CLOCK_FREQUENCY_DIVISOR + (next_pcr_l - pcr_l)) / | |
| 3520 | ✗ | (i + 1); | |
| 3521 | ✗ | break; | |
| 3522 | } | ||
| 3523 | } | ||
| 3524 | ✗ | avio_seek(s->pb, pos, SEEK_SET); | |
| 3525 | /* no next PCR found: we use previous increment */ | ||
| 3526 | ✗ | ts->cur_pcr = pcr_h * SYSTEM_CLOCK_FREQUENCY_DIVISOR + pcr_l; | |
| 3527 | } | ||
| 3528 | ✗ | pkt->pts = ts->cur_pcr; | |
| 3529 | ✗ | pkt->duration = ts->pcr_incr; | |
| 3530 | ✗ | ts->cur_pcr += ts->pcr_incr; | |
| 3531 | } | ||
| 3532 | ✗ | pkt->stream_index = 0; | |
| 3533 | ✗ | return 0; | |
| 3534 | } | ||
| 3535 | |||
| 3536 | 34655 | static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 3537 | { | ||
| 3538 | 34655 | MpegTSContext *ts = s->priv_data; | |
| 3539 | int ret, i; | ||
| 3540 | |||
| 3541 | 34655 | pkt->size = -1; | |
| 3542 | 34655 | ts->pkt = pkt; | |
| 3543 | 34655 | ret = handle_packets(ts, 0); | |
| 3544 |
2/2✓ Branch 0 taken 499 times.
✓ Branch 1 taken 34156 times.
|
34655 | if (ret < 0) { |
| 3545 | 499 | av_packet_unref(ts->pkt); | |
| 3546 | /* flush pes data left */ | ||
| 3547 |
2/2✓ Branch 0 taken 2846022 times.
✓ Branch 1 taken 284 times.
|
2846306 | for (i = 0; i < NB_PID_MAX; i++) |
| 3548 |
4/4✓ Branch 0 taken 2967 times.
✓ Branch 1 taken 2843055 times.
✓ Branch 2 taken 1026 times.
✓ Branch 3 taken 1941 times.
|
2846022 | if (ts->pids[i] && ts->pids[i]->type == MPEGTS_PES) { |
| 3549 | 1026 | PESContext *pes = ts->pids[i]->u.pes_filter.opaque; | |
| 3550 |
3/4✓ Branch 0 taken 215 times.
✓ Branch 1 taken 811 times.
✓ Branch 2 taken 215 times.
✗ Branch 3 not taken.
|
1026 | if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { |
| 3551 | 215 | ret = new_pes_packet(pes, pkt); | |
| 3552 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 215 times.
|
215 | if (ret < 0) |
| 3553 | ✗ | return ret; | |
| 3554 | 215 | pes->state = MPEGTS_SKIP; | |
| 3555 | 215 | ret = 0; | |
| 3556 | 215 | break; | |
| 3557 | } | ||
| 3558 | } | ||
| 3559 | } | ||
| 3560 | |||
| 3561 |
3/4✓ Branch 0 taken 34371 times.
✓ Branch 1 taken 284 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34371 times.
|
34655 | if (!ret && pkt->size < 0) |
| 3562 | ✗ | ret = AVERROR_INVALIDDATA; | |
| 3563 | 34655 | return ret; | |
| 3564 | } | ||
| 3565 | |||
| 3566 | 76 | static void mpegts_free(MpegTSContext *ts) | |
| 3567 | { | ||
| 3568 | int i; | ||
| 3569 | |||
| 3570 | 76 | clear_programs(ts); | |
| 3571 | |||
| 3572 |
2/2✓ Branch 0 taken 2432 times.
✓ Branch 1 taken 76 times.
|
2508 | for (i = 0; i < FF_ARRAY_ELEMS(ts->pools); i++) |
| 3573 | 2432 | av_buffer_pool_uninit(&ts->pools[i]); | |
| 3574 | |||
| 3575 |
2/2✓ Branch 0 taken 622592 times.
✓ Branch 1 taken 76 times.
|
622668 | for (i = 0; i < NB_PID_MAX; i++) |
| 3576 |
2/2✓ Branch 0 taken 465 times.
✓ Branch 1 taken 622127 times.
|
622592 | if (ts->pids[i]) |
| 3577 | 465 | mpegts_close_filter(ts, ts->pids[i]); | |
| 3578 | 76 | } | |
| 3579 | |||
| 3580 | 76 | static int mpegts_read_close(AVFormatContext *s) | |
| 3581 | { | ||
| 3582 | 76 | MpegTSContext *ts = s->priv_data; | |
| 3583 | 76 | mpegts_free(ts); | |
| 3584 | 76 | return 0; | |
| 3585 | } | ||
| 3586 | |||
| 3587 | ✗ | av_unused static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index, | |
| 3588 | int64_t *ppos, int64_t pos_limit) | ||
| 3589 | { | ||
| 3590 | ✗ | MpegTSContext *ts = s->priv_data; | |
| 3591 | int64_t pos, timestamp; | ||
| 3592 | uint8_t buf[TS_PACKET_SIZE]; | ||
| 3593 | ✗ | int pcr_l, pcr_pid = | |
| 3594 | ✗ | ((PESContext *)s->streams[stream_index]->priv_data)->pcr_pid; | |
| 3595 | ✗ | int pos47 = ts->pos47_full % ts->raw_packet_size; | |
| 3596 | ✗ | pos = | |
| 3597 | ✗ | ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * | |
| 3598 | ✗ | ts->raw_packet_size + pos47; | |
| 3599 | ✗ | while(pos < pos_limit) { | |
| 3600 | ✗ | if (avio_seek(s->pb, pos, SEEK_SET) < 0) | |
| 3601 | ✗ | return AV_NOPTS_VALUE; | |
| 3602 | ✗ | if (avio_read(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE) | |
| 3603 | ✗ | return AV_NOPTS_VALUE; | |
| 3604 | ✗ | if (buf[0] != SYNC_BYTE) { | |
| 3605 | ✗ | if (mpegts_resync(s, TS_PACKET_SIZE, buf) < 0) | |
| 3606 | ✗ | return AV_NOPTS_VALUE; | |
| 3607 | ✗ | pos = avio_tell(s->pb); | |
| 3608 | ✗ | continue; | |
| 3609 | } | ||
| 3610 | ✗ | if ((pcr_pid < 0 || (AV_RB16(buf + 1) & 0x1fff) == pcr_pid) && | |
| 3611 | ✗ | parse_pcr(×tamp, &pcr_l, buf) == 0) { | |
| 3612 | ✗ | *ppos = pos; | |
| 3613 | ✗ | return timestamp; | |
| 3614 | } | ||
| 3615 | ✗ | pos += ts->raw_packet_size; | |
| 3616 | } | ||
| 3617 | |||
| 3618 | ✗ | return AV_NOPTS_VALUE; | |
| 3619 | } | ||
| 3620 | |||
| 3621 | 90 | static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index, | |
| 3622 | int64_t *ppos, int64_t pos_limit) | ||
| 3623 | { | ||
| 3624 | 90 | MpegTSContext *ts = s->priv_data; | |
| 3625 | AVPacket *pkt; | ||
| 3626 | int64_t pos; | ||
| 3627 | 90 | int pos47 = ts->pos47_full % ts->raw_packet_size; | |
| 3628 | 90 | pos = ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * ts->raw_packet_size + pos47; | |
| 3629 | 90 | ff_read_frame_flush(s); | |
| 3630 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
|
90 | if (avio_seek(s->pb, pos, SEEK_SET) < 0) |
| 3631 | ✗ | return AV_NOPTS_VALUE; | |
| 3632 | 90 | pkt = av_packet_alloc(); | |
| 3633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (!pkt) |
| 3634 | ✗ | return AV_NOPTS_VALUE; | |
| 3635 |
2/2✓ Branch 0 taken 484 times.
✓ Branch 1 taken 12 times.
|
496 | while(pos < pos_limit) { |
| 3636 | 484 | int ret = av_read_frame(s, pkt); | |
| 3637 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 466 times.
|
484 | if (ret < 0) { |
| 3638 | 18 | av_packet_free(&pkt); | |
| 3639 | 18 | return AV_NOPTS_VALUE; | |
| 3640 | } | ||
| 3641 |
3/4✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 163 times.
✓ Branch 3 taken 303 times.
|
466 | if (pkt->dts != AV_NOPTS_VALUE && pkt->pos >= 0) { |
| 3642 | 163 | ff_reduce_index(s, pkt->stream_index); | |
| 3643 | 163 | av_add_index_entry(s->streams[pkt->stream_index], pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */); | |
| 3644 |
3/4✓ Branch 0 taken 60 times.
✓ Branch 1 taken 103 times.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
|
163 | if (pkt->stream_index == stream_index && pkt->pos >= *ppos) { |
| 3645 | 60 | int64_t dts = pkt->dts; | |
| 3646 | 60 | *ppos = pkt->pos; | |
| 3647 | 60 | av_packet_free(&pkt); | |
| 3648 | 60 | return dts; | |
| 3649 | } | ||
| 3650 | } | ||
| 3651 | 406 | pos = pkt->pos; | |
| 3652 | 406 | av_packet_unref(pkt); | |
| 3653 | } | ||
| 3654 | |||
| 3655 | 12 | av_packet_free(&pkt); | |
| 3656 | 12 | return AV_NOPTS_VALUE; | |
| 3657 | } | ||
| 3658 | |||
| 3659 | /**************************************************************/ | ||
| 3660 | /* parsing functions - called from other demuxers such as RTP */ | ||
| 3661 | |||
| 3662 | ✗ | MpegTSContext *avpriv_mpegts_parse_open(AVFormatContext *s) | |
| 3663 | { | ||
| 3664 | MpegTSContext *ts; | ||
| 3665 | |||
| 3666 | ✗ | ts = av_mallocz(sizeof(MpegTSContext)); | |
| 3667 | ✗ | if (!ts) | |
| 3668 | ✗ | return NULL; | |
| 3669 | /* no stream case, currently used by RTP */ | ||
| 3670 | ✗ | ts->raw_packet_size = TS_PACKET_SIZE; | |
| 3671 | ✗ | ts->max_packet_size = 2048000; | |
| 3672 | ✗ | ts->stream = s; | |
| 3673 | ✗ | ts->auto_guess = 1; | |
| 3674 | |||
| 3675 | ✗ | mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); | |
| 3676 | ✗ | mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); | |
| 3677 | ✗ | mpegts_open_section_filter(ts, EIT_PID, eit_cb, ts, 1); | |
| 3678 | |||
| 3679 | ✗ | return ts; | |
| 3680 | } | ||
| 3681 | |||
| 3682 | /* return the consumed length if a packet was output, or -1 if no | ||
| 3683 | * packet is output */ | ||
| 3684 | ✗ | int avpriv_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt, | |
| 3685 | const uint8_t *buf, int len) | ||
| 3686 | { | ||
| 3687 | int len1; | ||
| 3688 | |||
| 3689 | ✗ | len1 = len; | |
| 3690 | ✗ | ts->pkt = pkt; | |
| 3691 | for (;;) { | ||
| 3692 | ✗ | ts->stop_parse = 0; | |
| 3693 | ✗ | if (len < TS_PACKET_SIZE) | |
| 3694 | ✗ | return AVERROR_INVALIDDATA; | |
| 3695 | ✗ | if (buf[0] != SYNC_BYTE) { | |
| 3696 | ✗ | buf++; | |
| 3697 | ✗ | len--; | |
| 3698 | } else { | ||
| 3699 | ✗ | handle_packet(ts, buf, len1 - len + TS_PACKET_SIZE); | |
| 3700 | ✗ | buf += TS_PACKET_SIZE; | |
| 3701 | ✗ | len -= TS_PACKET_SIZE; | |
| 3702 | ✗ | if (ts->stop_parse == 1) | |
| 3703 | ✗ | break; | |
| 3704 | } | ||
| 3705 | } | ||
| 3706 | ✗ | return len1 - len; | |
| 3707 | } | ||
| 3708 | |||
| 3709 | ✗ | void avpriv_mpegts_parse_close(MpegTSContext *ts) | |
| 3710 | { | ||
| 3711 | ✗ | mpegts_free(ts); | |
| 3712 | ✗ | av_free(ts); | |
| 3713 | ✗ | } | |
| 3714 | |||
| 3715 | const FFInputFormat ff_mpegts_demuxer = { | ||
| 3716 | .p.name = "mpegts", | ||
| 3717 | .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"), | ||
| 3718 | .p.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | ||
| 3719 | .p.priv_class = &mpegts_class, | ||
| 3720 | .priv_data_size = sizeof(MpegTSContext), | ||
| 3721 | .read_probe = mpegts_probe, | ||
| 3722 | .read_header = mpegts_read_header, | ||
| 3723 | .read_packet = mpegts_read_packet, | ||
| 3724 | .read_close = mpegts_read_close, | ||
| 3725 | .read_timestamp = mpegts_get_dts, | ||
| 3726 | .flags_internal = FF_INFMT_FLAG_PREFER_CODEC_FRAMERATE, | ||
| 3727 | }; | ||
| 3728 | |||
| 3729 | const FFInputFormat ff_mpegtsraw_demuxer = { | ||
| 3730 | .p.name = "mpegtsraw", | ||
| 3731 | .p.long_name = NULL_IF_CONFIG_SMALL("raw MPEG-TS (MPEG-2 Transport Stream)"), | ||
| 3732 | .p.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | ||
| 3733 | .p.priv_class = &mpegtsraw_class, | ||
| 3734 | .priv_data_size = sizeof(MpegTSContext), | ||
| 3735 | .read_header = mpegts_read_header, | ||
| 3736 | .read_packet = mpegts_raw_read_packet, | ||
| 3737 | .read_close = mpegts_read_close, | ||
| 3738 | .read_timestamp = mpegts_get_dts, | ||
| 3739 | .flags_internal = FF_INFMT_FLAG_PREFER_CODEC_FRAMERATE, | ||
| 3740 | }; | ||
| 3741 |