X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fnutdec.c;h=56d208fcc8b353415331efbbb6792453f13aeb02;hb=7207dd8f829baee58b4df6c97c19ffde77039e8d;hp=00c9ae36b7bba15cacf353cc0deab64a1a47bd87;hpb=46c1917350f58dfab84e41919e6c02d43950db8c;p=ffmpeg diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c index 00c9ae36b7b..56d208fcc8b 100644 --- a/libavformat/nutdec.c +++ b/libavformat/nutdec.c @@ -183,7 +183,7 @@ static int nut_probe(AVProbeData *p) tmp = ffio_read_varlen(bc); \ if (!(check)) { \ av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp); \ - return -1; \ + return AVERROR_INVALIDDATA; \ } \ dst = tmp; \ } while (0) @@ -193,7 +193,7 @@ static int skip_reserved(AVIOContext *bc, int64_t pos) pos -= avio_tell(bc); if (pos < 0) { avio_seek(bc, pos, SEEK_CUR); - return -1; + return AVERROR_INVALIDDATA; } else { while (pos--) avio_r8(bc); @@ -213,7 +213,14 @@ static int decode_main_header(NUTContext *nut) end = get_packetheader(nut, bc, 1, MAIN_STARTCODE); end += avio_tell(bc); - GET_V(tmp, tmp >= 2 && tmp <= NUT_VERSION); + nut->version = ffio_read_varlen(bc); + if (nut->version < NUT_MIN_VERSION && + nut->version > NUT_MAX_VERSION) { + av_log(s, AV_LOG_ERROR, "Version %d not supported.\n", + nut->version); + return AVERROR(ENOSYS); + } + GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS); nut->max_distance = ffio_read_varlen(bc); @@ -314,6 +321,11 @@ static int decode_main_header(NUTContext *nut) assert(nut->header_len[0] == 0); } + // flags had been effectively introduced in version 4 + if (nut->version > NUT_STABLE_VERSION) { + nut->flags = ffio_read_varlen(bc); + } + if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n"); return AVERROR_INVALIDDATA; @@ -376,7 +388,7 @@ static int decode_stream_header(NUTContext *nut) break; default: av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class); - return -1; + return AVERROR(ENOSYS); } if (class < 3 && st->codec->codec_id == AV_CODEC_ID_NONE) av_log(s, AV_LOG_ERROR, @@ -405,7 +417,7 @@ static int decode_stream_header(NUTContext *nut) if ((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)) { av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); - return -1; + return AVERROR_INVALIDDATA; } ffio_read_varlen(bc); /* csp type */ } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -416,7 +428,7 @@ static int decode_stream_header(NUTContext *nut) if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id); - return -1; + return AVERROR_INVALIDDATA; } stc->time_base = &nut->time_base[stc->time_base_id]; avpriv_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, @@ -449,9 +461,11 @@ static int decode_info_header(NUTContext *nut) int64_t value, end; char name[256], str_value[1024], type_str[256]; const char *type; + int *event_flags = NULL; AVChapter *chapter = NULL; AVStream *st = NULL; AVDictionary **metadata = NULL; + int metadata_flag = 0; end = get_packetheader(nut, bc, 1, INFO_STARTCODE); end += avio_tell(bc); @@ -472,8 +486,13 @@ static int decode_info_header(NUTContext *nut) } else if (stream_id_plus1) { st = s->streams[stream_id_plus1 - 1]; metadata = &st->metadata; - } else + event_flags = &st->event_flags; + metadata_flag = AVSTREAM_EVENT_FLAG_METADATA_UPDATED; + } else { metadata = &s->metadata; + event_flags = &s->event_flags; + metadata_flag = AVFMT_EVENT_FLAG_METADATA_UPDATED; + } for (i = 0; i < count; i++) { get_str(bc, name, sizeof(name)); @@ -509,14 +528,17 @@ static int decode_info_header(NUTContext *nut) continue; } if (metadata && av_strcasecmp(name, "Uses") && - av_strcasecmp(name, "Depends") && av_strcasecmp(name, "Replaces")) + av_strcasecmp(name, "Depends") && av_strcasecmp(name, "Replaces")) { + if (event_flags) + *event_flags |= metadata_flag; av_dict_set(metadata, name, str_value, 0); + } } } if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n"); - return -1; + return AVERROR_INVALIDDATA; } return 0; } @@ -526,6 +548,7 @@ static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr) AVFormatContext *s = nut->avf; AVIOContext *bc = s->pb; int64_t end, tmp; + int ret; nut->last_syncpoint_pos = avio_tell(bc) - 8; @@ -540,14 +563,24 @@ static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr) ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count], tmp / nut->time_base_count); + if (nut->flags & NUT_BROADCAST) { + tmp = ffio_read_varlen(bc); + av_log(s, AV_LOG_VERBOSE, "Syncpoint wallclock %"PRId64"\n", + av_rescale_q(tmp / nut->time_base_count, + nut->time_base[tmp % nut->time_base_count], + AV_TIME_BASE_Q)); + } + if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n"); - return -1; + return AVERROR_INVALIDDATA; } *ts = tmp / s->nb_streams * av_q2d(nut->time_base[tmp % s->nb_streams]) * AV_TIME_BASE; - ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts); + + if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, *back_ptr, *ts)) < 0) + return ret; return 0; } @@ -561,13 +594,13 @@ static int find_and_decode_index(NUTContext *nut) int64_t filesize = avio_size(bc); int64_t *syncpoints; int8_t *has_keyframe; - int ret = -1; + int ret = AVERROR_INVALIDDATA; avio_seek(bc, filesize - 12, SEEK_SET); avio_seek(bc, filesize - avio_rb64(bc), SEEK_SET); if (avio_rb64(bc) != INDEX_STARTCODE) { av_log(s, AV_LOG_ERROR, "no index at the end\n"); - return -1; + return ret; } end = get_packetheader(nut, bc, 1, INDEX_STARTCODE); @@ -719,7 +752,8 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, int size, flags, size_mul, pts_delta, i, reserved_count; uint64_t tmp; - if (avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) { + if (!(nut->flags & NUT_PIPE) && + avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) { av_log(s, AV_LOG_ERROR, "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n", avio_tell(bc), nut->last_syncpoint_pos, nut->max_distance); @@ -772,8 +806,9 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, if (flags & FLAG_CHECKSUM) { avio_rb32(bc); // FIXME check this - } else if (size > 2 * nut->max_distance || FFABS(stc->last_pts - *pts) > - stc->max_pts_distance) { + } else if (!(nut->flags & NUT_PIPE) && + size > 2 * nut->max_distance || + FFABS(stc->last_pts - *pts) > stc->max_pts_distance) { av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n"); return AVERROR_INVALIDDATA; } @@ -843,7 +878,7 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt) } else { frame_code = avio_r8(bc); if (bc->eof_reached) - return -1; + return AVERROR_EOF; if (frame_code == 'N') { tmp = frame_code; for (i = 1; i < 8; i++) @@ -924,6 +959,10 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t pos, pos2, ts; int i; + if (nut->flags & NUT_PIPE) { + return AVERROR(ENOSYS); + } + if (st->index_entries) { int index = av_index_search_timestamp(st, pts, flags); if (index < 0)