X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fwtv.c;h=c85f374499d8eb855545c0935d34b5df347412cb;hb=55ddd700c67529ff2c6c4e976673f1341bba7a82;hp=2e5d39cff2e4865d858fe4f7f7ca1de3a7790600;hpb=511cf612ac979f536fd65e14603a87ca5ad435f3;p=ffmpeg diff --git a/libavformat/wtv.c b/libavformat/wtv.c index 2e5d39cff2e..c85f374499d 100644 --- a/libavformat/wtv.c +++ b/libavformat/wtv.c @@ -25,6 +25,8 @@ * @author Peter Ross */ +#include + #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" @@ -36,13 +38,8 @@ #include "mpegts.h" /* Macros for formating GUIDs */ -#define PRI_GUID \ - "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" -#define ARG_GUID(g) \ - g[0],g[1],g[2],g[3],g[4],g[5],g[6],g[7],g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15] - #define PRI_PRETTY_GUID \ - "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x" + "%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%02x%02x%02x%02x%02x%02x%02x%02x" #define ARG_PRETTY_GUID(g) \ AV_RL32(g),AV_RL16(g+4),AV_RL16(g+6),g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15] #define LEN_PRETTY_GUID 34 @@ -57,6 +54,8 @@ #define WTV_SECTOR_SIZE (1 << WTV_SECTOR_BITS) #define WTV_BIGSECTOR_BITS 18 +#define SHIFT_SECTOR_BITS(a) ((int64_t)(a) << WTV_SECTOR_BITS) + typedef struct { AVIOContext *pb_filesystem; /** file system (AVFormatContext->pb) */ @@ -69,6 +68,11 @@ typedef struct { int64_t length; } WtvFile; +static int64_t seek_by_sector(AVIOContext *pb, int64_t sector, int64_t offset) +{ + return avio_seek(pb, SHIFT_SECTOR_BITS(sector) + offset, SEEK_SET); +} + /** * @return bytes read, 0 on end of file, or <0 on error */ @@ -99,7 +103,7 @@ static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size) int i = wf->position >> wf->sector_bits; if (i >= wf->nb_sectors || (wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) && - avio_seek(pb, (int64_t)wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) { + seek_by_sector(pb, wf->sectors[i], 0) < 0)) { wf->error = 1; break; } @@ -124,8 +128,8 @@ static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence) offset = wf->length; wf->error = offset < 0 || offset >= wf->length || - avio_seek(pb, ((int64_t)wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS) - + (offset & ((1 << wf->sector_bits) - 1)), SEEK_SET) < 0; + seek_by_sector(pb, wf->sectors[offset >> wf->sector_bits], + offset & ((1 << wf->sector_bits) - 1)) < 0; wf->position = offset; return offset; } @@ -160,7 +164,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int WtvFile *wf; uint8_t *buffer; - if (avio_seek(s->pb, first_sector << WTV_SECTOR_BITS, SEEK_SET) < 0) + if (seek_by_sector(s->pb, first_sector, 0) < 0) return NULL; wf = av_mallocz(sizeof(WtvFile)); @@ -189,14 +193,14 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4); int i; - wf->sectors = av_malloc(nb_sectors1 << WTV_SECTOR_BITS); + wf->sectors = av_malloc(SHIFT_SECTOR_BITS(nb_sectors1)); if (!wf->sectors) { av_free(wf); return NULL; } wf->nb_sectors = 0; for (i = 0; i < nb_sectors1; i++) { - if (avio_seek(s->pb, (int64_t)sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0) + if (seek_by_sector(s->pb, sectors1[i], 0) < 0) break; wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4); } @@ -223,7 +227,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int /* seek to initial sector */ wf->position = 0; - if (avio_seek(s->pb, (int64_t)wf->sectors[0] << WTV_SECTOR_BITS, SEEK_SET) < 0) { + if (seek_by_sector(s->pb, wf->sectors[0], 0) < 0) { av_free(wf->sectors); av_free(wf); return NULL; @@ -267,14 +271,19 @@ static AVIOContext * wtvfile_open2(AVFormatContext *s, const uint8_t *buf, int b uint64_t file_length; const uint8_t *name; if (ff_guidcmp(buf, dir_entry_guid)) { - av_log(s, AV_LOG_ERROR, "unknown guid "PRI_GUID", expected dir_entry_guid; " - "remaining directory entries ignored\n", ARG_GUID(buf)); + av_log(s, AV_LOG_ERROR, "unknown guid "FF_PRI_GUID", expected dir_entry_guid; " + "remaining directory entries ignored\n", FF_ARG_GUID(buf)); break; } dir_length = AV_RL16(buf + 16); file_length = AV_RL64(buf + 24); name_size = 2 * AV_RL32(buf + 32); - if (buf + 48 + name_size > buf_end) { + if (name_size < 0) { + av_log(s, AV_LOG_ERROR, + "bad filename length, remaining directory entries ignored\n"); + break; + } + if (48 + name_size > buf_end - buf) { av_log(s, AV_LOG_ERROR, "filename exceeds buffer size; remaining directory entries ignored\n"); break; } @@ -331,21 +340,6 @@ typedef struct { unsigned int index_entries_allocated_size; } WtvContext; -typedef struct { - enum AVCodecID id; - ff_asf_guid guid; -} AVCodecGuid; - -static enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid) -{ - int i; - for (i = 0; guids[i].id != AV_CODEC_ID_NONE; i++) { - if (!ff_guidcmp(guids[i].guid, guid)) - return guids[i].id; - } - return AV_CODEC_ID_NONE; -} - /* WTV GUIDs */ static const ff_asf_guid wtv_guid = {0xB7,0xD8,0x00,0x20,0x37,0x49,0xDA,0x11,0xA6,0x4E,0x00,0x07,0xE9,0x5E,0xAD,0x8D}; @@ -380,14 +374,11 @@ static const ff_asf_guid EVENTID_AudioTypeSpanningEvent = /* Windows media GUIDs */ -#define MEDIASUBTYPE_BASE_GUID \ - 0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 - /* Media types */ static const ff_asf_guid mediatype_audio = - {'a','u','d','s',MEDIASUBTYPE_BASE_GUID}; + {'a','u','d','s',FF_MEDIASUBTYPE_BASE_GUID}; static const ff_asf_guid mediatype_video = - {'v','i','d','s',MEDIASUBTYPE_BASE_GUID}; + {'v','i','d','s',FF_MEDIASUBTYPE_BASE_GUID}; static const ff_asf_guid mediasubtype_mpeg1payload = {0x81,0xEB,0x36,0xE4,0x4F,0x52,0xCE,0x11,0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}; static const ff_asf_guid mediatype_mpeg2_sections = @@ -426,13 +417,6 @@ static const AVCodecGuid video_guids[] = { {AV_CODEC_ID_NONE} }; -static const AVCodecGuid audio_guids[] = { - {AV_CODEC_ID_AC3, {0x2C,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}}, - {AV_CODEC_ID_EAC3, {0xAF,0x87,0xFB,0xA7,0x02,0x2D,0xFB,0x42,0xA4,0xD4,0x05,0xCD,0x93,0x84,0x3B,0xDD}}, - {AV_CODEC_ID_MP2, {0x2B,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}}, - {AV_CODEC_ID_NONE} -}; - static int read_probe(AVProbeData *p) { return ff_guidcmp(p->buf, wtv_guid) ? 0 : AVPROBE_SCORE_MAX; @@ -502,6 +486,7 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length) st->codec->codec_id = AV_CODEC_ID_MJPEG; st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; st->codec->extradata = av_mallocz(filesize); + st->id = -1; if (!st->codec->extradata) goto done; st->codec->extradata_size = filesize; @@ -518,7 +503,7 @@ static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int ty return; if (type == 0 && length == 4) { - snprintf(buf, buf_size, "%"PRIi32, avio_rl32(pb)); + snprintf(buf, buf_size, "%u", avio_rl32(pb)); } else if (type == 1) { avio_get_str16le(pb, length, buf, buf_size); if (!strlen(buf)) { @@ -542,7 +527,7 @@ static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int ty else snprintf(buf, buf_size, "%"PRIi64, num); } else if (type == 5 && length == 2) { - snprintf(buf, buf_size, "%"PRIi16, avio_rl16(pb)); + snprintf(buf, buf_size, "%u", avio_rl16(pb)); } else if (type == 6 && length == 16) { ff_asf_guid guid; avio_read(pb, guid, 16); @@ -577,8 +562,8 @@ static void parse_legacy_attrib(AVFormatContext *s, AVIOContext *pb) if (!length) break; if (ff_guidcmp(&guid, metadata_guid)) { - av_log(s, AV_LOG_WARNING, "unknown guid "PRI_GUID", expected metadata_guid; " - "remaining metadata entries ignored\n", ARG_GUID(guid)); + av_log(s, AV_LOG_WARNING, "unknown guid "FF_PRI_GUID", expected metadata_guid; " + "remaining metadata entries ignored\n", FF_ARG_GUID(guid)); break; } avio_get_str16le(pb, INT_MAX, key, sizeof(key)); @@ -702,11 +687,11 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, return NULL; } else { if (ff_guidcmp(formattype, format_none)) - av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); + av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); avio_skip(pb, size); } - if (!memcmp(subtype + 4, (const uint8_t[]){MEDIASUBTYPE_BASE_GUID}, 12)) { + if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) { st->codec->codec_id = ff_wav_codec_get_id(AV_RL32(subtype), st->codec->bits_per_coded_sample); } else if (!ff_guidcmp(subtype, mediasubtype_mpeg1payload)) { if (st->codec->extradata && st->codec->extradata_size >= 22) @@ -714,9 +699,9 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, else av_log(s, AV_LOG_WARNING, "MPEG1WAVEFORMATEX underflow\n"); } else { - st->codec->codec_id = ff_codec_guid_get_id(audio_guids, subtype); + st->codec->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subtype); if (st->codec->codec_id == AV_CODEC_ID_NONE) - av_log(s, AV_LOG_WARNING, "unknown subtype:"PRI_GUID"\n", ARG_GUID(subtype)); + av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype)); } return st; } else if (!ff_guidcmp(mediatype, mediatype_video)) { @@ -731,17 +716,17 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, avio_skip(pb, FFMAX(size - consumed, 0)); } else { if (ff_guidcmp(formattype, format_none)) - av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); + av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); avio_skip(pb, size); } - if (!memcmp(subtype + 4, (const uint8_t[]){MEDIASUBTYPE_BASE_GUID}, 12)) { + if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) { st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype)); } else { st->codec->codec_id = ff_codec_guid_get_id(video_guids, subtype); } if (st->codec->codec_id == AV_CODEC_ID_NONE) - av_log(s, AV_LOG_WARNING, "unknown subtype:"PRI_GUID"\n", ARG_GUID(subtype)); + av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype)); return st; } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_pes) && !ff_guidcmp(subtype, mediasubtype_dvb_subtitle)) { @@ -749,7 +734,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, if (!st) return NULL; if (ff_guidcmp(formattype, format_none)) - av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); + av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); avio_skip(pb, size); st->codec->codec_id = AV_CODEC_ID_DVB_SUBTITLE; return st; @@ -759,21 +744,21 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, if (!st) return NULL; if (ff_guidcmp(formattype, format_none)) - av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); + av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); avio_skip(pb, size); st->codec->codec_id = AV_CODEC_ID_DVB_TELETEXT; return st; } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_sections) && !ff_guidcmp(subtype, mediasubtype_mpeg2_sections)) { if (ff_guidcmp(formattype, format_none)) - av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); + av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype)); avio_skip(pb, size); return NULL; } - av_log(s, AV_LOG_WARNING, "unknown media type, mediatype:"PRI_GUID - ", subtype:"PRI_GUID", formattype:"PRI_GUID"\n", - ARG_GUID(mediatype), ARG_GUID(subtype), ARG_GUID(formattype)); + av_log(s, AV_LOG_WARNING, "unknown media type, mediatype:"FF_PRI_GUID + ", subtype:"FF_PRI_GUID", formattype:"FF_PRI_GUID"\n", + FF_ARG_GUID(mediatype), FF_ARG_GUID(subtype), FF_ARG_GUID(formattype)); avio_skip(pb, size); return NULL; } @@ -945,7 +930,7 @@ static int parse_chunks(AVFormatContext *s, int mode, int64_t seekts, int *len_p !ff_guidcmp(g, (const ff_asf_guid){0xA1,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D})) { //ignore known guids } else - av_log(s, AV_LOG_WARNING, "unsupported chunk:"PRI_GUID"\n", ARG_GUID(g)); + av_log(s, AV_LOG_WARNING, "unsupported chunk:"FF_PRI_GUID"\n", FF_ARG_GUID(g)); avio_skip(pb, WTV_PAD8(len) - consumed); } @@ -987,7 +972,7 @@ static int read_header(AVFormatContext *s) avio_skip(s->pb, 4); root_sector = avio_rl32(s->pb); - avio_seek(s->pb, root_sector << WTV_SECTOR_BITS, SEEK_SET); + seek_by_sector(s->pb, root_sector, 0); root_size = avio_read(s->pb, root, root_size); if (root_size < 0) return AVERROR_INVALIDDATA;