Libav 0.7.1
|
00001 /* 00002 * Windows Television (WTV) demuxer 00003 * Copyright (c) 2010-2011 Peter Ross <pross@xvid.org> 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00028 #include "libavutil/intreadwrite.h" 00029 #include "libavutil/intfloat_readwrite.h" 00030 #include "libavutil/dict.h" 00031 #include "avformat.h" 00032 #include "internal.h" 00033 #include "riff.h" 00034 #include "asf.h" 00035 #include "mpegts.h" 00036 #include <strings.h> 00037 00038 /* Macros for formating GUIDs */ 00039 #define PRI_GUID \ 00040 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" 00041 #define ARG_GUID(g) \ 00042 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] 00043 00044 #define PRI_PRETTY_GUID \ 00045 "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x" 00046 #define ARG_PRETTY_GUID(g) \ 00047 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] 00048 #define LEN_PRETTY_GUID 34 00049 00050 /* 00051 * 00052 * File system routines 00053 * 00054 */ 00055 00056 #define WTV_SECTOR_BITS 12 00057 #define WTV_SECTOR_SIZE (1 << WTV_SECTOR_BITS) 00058 #define WTV_BIGSECTOR_BITS 18 00059 00060 typedef struct { 00061 AVIOContext *pb_filesystem; 00063 int sector_bits; 00064 uint32_t *sectors; 00065 int nb_sectors; 00067 int error; 00068 int64_t position; 00069 int64_t length; 00070 } WtvFile; 00071 00075 static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size) 00076 { 00077 WtvFile *wf = opaque; 00078 AVIOContext *pb = wf->pb_filesystem; 00079 int nread = 0; 00080 00081 if (wf->error || pb->error) 00082 return -1; 00083 if (wf->position >= wf->length || pb->eof_reached) 00084 return 0; 00085 00086 buf_size = FFMIN(buf_size, wf->length - wf->position); 00087 while(nread < buf_size) { 00088 int n; 00089 int remaining_in_sector = (1 << wf->sector_bits) - (wf->position & ((1 << wf->sector_bits) - 1)); 00090 int read_request = FFMIN(buf_size - nread, remaining_in_sector); 00091 00092 n = avio_read(pb, buf, read_request); 00093 if (n <= 0) 00094 break; 00095 nread += n; 00096 buf += n; 00097 wf->position += n; 00098 if (n == remaining_in_sector) { 00099 int i = wf->position >> wf->sector_bits; 00100 if (i >= wf->nb_sectors || 00101 (wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) && 00102 avio_seek(pb, (int64_t)wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) { 00103 wf->error = 1; 00104 break; 00105 } 00106 } 00107 } 00108 return nread; 00109 } 00110 00114 static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence) 00115 { 00116 WtvFile *wf = opaque; 00117 AVIOContext *pb = wf->pb_filesystem; 00118 00119 if (whence == AVSEEK_SIZE) 00120 return wf->length; 00121 else if (whence == SEEK_CUR) 00122 offset = wf->position + offset; 00123 else if (whence == SEEK_END) 00124 offset = wf->length; 00125 00126 wf->error = offset < 0 || offset >= wf->length || 00127 avio_seek(pb, ((int64_t)wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS) 00128 + (offset & ((1 << wf->sector_bits) - 1)), SEEK_SET) < 0; 00129 wf->position = offset; 00130 return offset; 00131 } 00132 00140 static int read_ints(AVIOContext *pb, uint32_t *data, int count) 00141 { 00142 int i, total = 0; 00143 for (i = 0; i < count; i++) { 00144 if ((data[total] = avio_rl32(pb))) 00145 total++; 00146 } 00147 return total; 00148 } 00149 00157 static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int depth, AVFormatContext *s) 00158 { 00159 AVIOContext *pb; 00160 WtvFile *wf; 00161 uint8_t *buffer; 00162 00163 if (avio_seek(s->pb, first_sector << WTV_SECTOR_BITS, SEEK_SET) < 0) 00164 return NULL; 00165 00166 wf = av_mallocz(sizeof(WtvFile)); 00167 if (!wf) 00168 return NULL; 00169 00170 if (depth == 0) { 00171 wf->sectors = av_malloc(sizeof(uint32_t)); 00172 if (!wf->sectors) { 00173 av_free(wf); 00174 return NULL; 00175 } 00176 wf->sectors[0] = first_sector; 00177 wf->nb_sectors = 1; 00178 wf->sector_bits = WTV_SECTOR_BITS; 00179 } else if (depth == 1) { 00180 wf->sectors = av_malloc(WTV_SECTOR_SIZE); 00181 if (!wf->sectors) { 00182 av_free(wf); 00183 return NULL; 00184 } 00185 wf->nb_sectors = read_ints(s->pb, wf->sectors, WTV_SECTOR_SIZE / 4); 00186 wf->sector_bits = length & (1ULL<<63) ? WTV_SECTOR_BITS : WTV_BIGSECTOR_BITS; 00187 } else if (depth == 2) { 00188 uint32_t sectors1[WTV_SECTOR_SIZE / 4]; 00189 int nb_sectors1 = read_ints(s->pb, sectors1, WTV_SECTOR_SIZE / 4); 00190 int i; 00191 00192 wf->sectors = av_malloc(nb_sectors1 << WTV_SECTOR_BITS); 00193 if (!wf->sectors) { 00194 av_free(wf); 00195 return NULL; 00196 } 00197 wf->nb_sectors = 0; 00198 for (i = 0; i < nb_sectors1; i++) { 00199 if (avio_seek(s->pb, (int64_t)sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0) 00200 break; 00201 wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4); 00202 } 00203 wf->sector_bits = length & (1ULL<<63) ? WTV_SECTOR_BITS : WTV_BIGSECTOR_BITS; 00204 } else { 00205 av_log(s, AV_LOG_ERROR, "unsupported file allocation table depth (0x%x)\n", depth); 00206 av_free(wf); 00207 return NULL; 00208 } 00209 00210 if (!wf->nb_sectors) { 00211 av_free(wf->sectors); 00212 av_free(wf); 00213 return NULL; 00214 } 00215 00216 /* check length */ 00217 length &= 0xFFFFFFFFFFFF; 00218 if (length > ((int64_t)wf->nb_sectors << wf->sector_bits)) { 00219 av_log(s, AV_LOG_WARNING, "reported file length (0x%"PRIx64") exceeds number of available sectors (0x%"PRIx64")\n", length, (int64_t)wf->nb_sectors << wf->sector_bits); 00220 length = (int64_t)wf->nb_sectors << wf->sector_bits; 00221 } 00222 wf->length = length; 00223 00224 /* seek to intial sector */ 00225 wf->position = 0; 00226 if (avio_seek(s->pb, (int64_t)wf->sectors[0] << WTV_SECTOR_BITS, SEEK_SET) < 0) { 00227 av_free(wf->sectors); 00228 av_free(wf); 00229 return NULL; 00230 } 00231 00232 wf->pb_filesystem = s->pb; 00233 buffer = av_malloc(1 << wf->sector_bits); 00234 if (!buffer) { 00235 av_free(wf->sectors); 00236 av_free(wf); 00237 return NULL; 00238 } 00239 00240 pb = avio_alloc_context(buffer, 1 << wf->sector_bits, 0, wf, 00241 wtvfile_read_packet, NULL, wtvfile_seek); 00242 if (!pb) { 00243 av_free(buffer); 00244 av_free(wf->sectors); 00245 av_free(wf); 00246 } 00247 return pb; 00248 } 00249 00250 static const ff_asf_guid dir_entry_guid = 00251 {0x92,0xB7,0x74,0x91,0x59,0x70,0x70,0x44,0x88,0xDF,0x06,0x3B,0x82,0xCC,0x21,0x3D}; 00252 00261 static AVIOContext * wtvfile_open2(AVFormatContext *s, const uint8_t *buf, int buf_size, const uint8_t *filename, int filename_size) 00262 { 00263 const uint8_t *buf_end = buf + buf_size; 00264 00265 while(buf + 48 <= buf_end) { 00266 int dir_length, name_size, first_sector, depth; 00267 uint64_t file_length; 00268 const uint8_t *name; 00269 if (ff_guidcmp(buf, dir_entry_guid)) { 00270 av_log(s, AV_LOG_ERROR, "unknown guid "PRI_GUID", expected dir_entry_guid; " 00271 "remaining directory entries ignored\n", ARG_GUID(buf)); 00272 break; 00273 } 00274 dir_length = AV_RL16(buf + 16); 00275 file_length = AV_RL64(buf + 24); 00276 name_size = 2 * AV_RL32(buf + 32); 00277 if (buf + 48 + name_size > buf_end) { 00278 av_log(s, AV_LOG_ERROR, "filename exceeds buffer size; remaining directory entries ignored\n"); 00279 break; 00280 } 00281 first_sector = AV_RL32(buf + 40 + name_size); 00282 depth = AV_RL32(buf + 44 + name_size); 00283 00284 /* compare file name; test optional null terminator */ 00285 name = buf + 40; 00286 if (name_size >= filename_size && 00287 !memcmp(name, filename, filename_size) && 00288 (name_size < filename_size + 2 || !AV_RN16(name + filename_size))) 00289 return wtvfile_open_sector(first_sector, file_length, depth, s); 00290 00291 buf += dir_length; 00292 } 00293 return 0; 00294 } 00295 00296 #define wtvfile_open(s, buf, buf_size, filename) \ 00297 wtvfile_open2(s, buf, buf_size, filename, sizeof(filename)) 00298 00302 static void wtvfile_close(AVIOContext *pb) 00303 { 00304 WtvFile *wf = pb->opaque; 00305 av_free(wf->sectors); 00306 av_free(pb); 00307 } 00308 00309 /* 00310 * 00311 * Main demuxer 00312 * 00313 */ 00314 00315 typedef struct { 00316 int seen_data; 00317 } WtvStream; 00318 00319 typedef struct { 00320 AVIOContext *pb; 00321 int64_t epoch; 00322 int64_t pts; 00323 int64_t last_valid_pts; 00325 /* maintain private seek index, as the AVIndexEntry->pos is relative to the 00326 start of the 'timeline' file, not the file system (AVFormatContext->pb) */ 00327 AVIndexEntry *index_entries; 00328 int nb_index_entries; 00329 unsigned int index_entries_allocated_size; 00330 } WtvContext; 00331 00332 typedef struct { 00333 enum CodecID id; 00334 ff_asf_guid guid; 00335 } AVCodecGuid; 00336 00337 static enum CodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid) 00338 { 00339 int i; 00340 for (i = 0; guids[i].id != CODEC_ID_NONE; i++) { 00341 if (!ff_guidcmp(guids[i].guid, guid)) 00342 return guids[i].id; 00343 } 00344 return CODEC_ID_NONE; 00345 } 00346 00347 /* WTV GUIDs */ 00348 static const ff_asf_guid wtv_guid = 00349 {0xB7,0xD8,0x00,0x20,0x37,0x49,0xDA,0x11,0xA6,0x4E,0x00,0x07,0xE9,0x5E,0xAD,0x8D}; 00350 static const ff_asf_guid metadata_guid = 00351 {0x5A,0xFE,0xD7,0x6D,0xC8,0x1D,0x8F,0x4A,0x99,0x22,0xFA,0xB1,0x1C,0x38,0x14,0x53}; 00352 static const ff_asf_guid timestamp_guid = 00353 {0x5B,0x05,0xE6,0x1B,0x97,0xA9,0x49,0x43,0x88,0x17,0x1A,0x65,0x5A,0x29,0x8A,0x97}; 00354 static const ff_asf_guid data_guid = 00355 {0x95,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}; 00356 static const ff_asf_guid stream_guid = 00357 {0xED,0xA4,0x13,0x23,0x2D,0xBF,0x4F,0x45,0xAD,0x8A,0xD9,0x5B,0xA7,0xF9,0x1F,0xEE}; 00358 static const ff_asf_guid stream2_guid = 00359 {0xA2,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}; 00360 static const ff_asf_guid EVENTID_SubtitleSpanningEvent = 00361 {0x48,0xC0,0xCE,0x5D,0xB9,0xD0,0x63,0x41,0x87,0x2C,0x4F,0x32,0x22,0x3B,0xE8,0x8A}; 00362 static const ff_asf_guid EVENTID_LanguageSpanningEvent = 00363 {0x6D,0x66,0x92,0xE2,0x02,0x9C,0x8D,0x44,0xAA,0x8D,0x78,0x1A,0x93,0xFD,0xC3,0x95}; 00364 static const ff_asf_guid EVENTID_AudioDescriptorSpanningEvent = 00365 {0x1C,0xD4,0x7B,0x10,0xDA,0xA6,0x91,0x46,0x83,0x69,0x11,0xB2,0xCD,0xAA,0x28,0x8E}; 00366 static const ff_asf_guid EVENTID_CtxADescriptorSpanningEvent = 00367 {0xE6,0xA2,0xB4,0x3A,0x47,0x42,0x34,0x4B,0x89,0x6C,0x30,0xAF,0xA5,0xD2,0x1C,0x24}; 00368 static const ff_asf_guid EVENTID_CSDescriptorSpanningEvent = 00369 {0xD9,0x79,0xE7,0xEf,0xF0,0x97,0x86,0x47,0x80,0x0D,0x95,0xCF,0x50,0x5D,0xDC,0x66}; 00370 static const ff_asf_guid EVENTID_DVBScramblingControlSpanningEvent = 00371 {0xC4,0xE1,0xD4,0x4B,0xA1,0x90,0x09,0x41,0x82,0x36,0x27,0xF0,0x0E,0x7D,0xCC,0x5B}; 00372 static const ff_asf_guid EVENTID_StreamIDSpanningEvent = 00373 {0x68,0xAB,0xF1,0xCA,0x53,0xE1,0x41,0x4D,0xA6,0xB3,0xA7,0xC9,0x98,0xDB,0x75,0xEE}; 00374 static const ff_asf_guid EVENTID_TeletextSpanningEvent = 00375 {0x50,0xD9,0x99,0x95,0x33,0x5F,0x17,0x46,0xAF,0x7C,0x1E,0x54,0xB5,0x10,0xDA,0xA3}; 00376 static const ff_asf_guid EVENTID_AudioTypeSpanningEvent = 00377 {0xBE,0xBF,0x1C,0x50,0x49,0xB8,0xCE,0x42,0x9B,0xE9,0x3D,0xB8,0x69,0xFB,0x82,0xB3}; 00378 00379 /* Windows media GUIDs */ 00380 00381 #define MEDIASUBTYPE_BASE_GUID \ 00382 0x00,0x00,0x10,0x00,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71 00383 00384 /* Media types */ 00385 static const ff_asf_guid mediatype_audio = 00386 {'a','u','d','s',MEDIASUBTYPE_BASE_GUID}; 00387 static const ff_asf_guid mediatype_video = 00388 {'v','i','d','s',MEDIASUBTYPE_BASE_GUID}; 00389 static const ff_asf_guid mediasubtype_mpeg1payload = 00390 {0x81,0xEB,0x36,0xE4,0x4F,0x52,0xCE,0x11,0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}; 00391 static const ff_asf_guid mediatype_mpeg2_sections = 00392 {0x6C,0x17,0x5F,0x45,0x06,0x4B,0xCE,0x47,0x9A,0xEF,0x8C,0xAE,0xF7,0x3D,0xF7,0xB5}; 00393 static const ff_asf_guid mediatype_mpeg2_pes = 00394 {0x20,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}; 00395 static const ff_asf_guid mediatype_mstvcaption = 00396 {0x89,0x8A,0x8B,0xB8,0x49,0xB0,0x80,0x4C,0xAD,0xCF,0x58,0x98,0x98,0x5E,0x22,0xC1}; 00397 00398 /* Media subtypes */ 00399 static const ff_asf_guid mediasubtype_cpfilters_processed = 00400 {0x28,0xBD,0xAD,0x46,0xD0,0x6F,0x96,0x47,0x93,0xB2,0x15,0x5C,0x51,0xDC,0x04,0x8D}; 00401 static const ff_asf_guid mediasubtype_dvb_subtitle = 00402 {0xC3,0xCB,0xFF,0x34,0xB3,0xD5,0x71,0x41,0x90,0x02,0xD4,0xC6,0x03,0x01,0x69,0x7F}; 00403 static const ff_asf_guid mediasubtype_teletext = 00404 {0xE3,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA}; 00405 static const ff_asf_guid mediasubtype_dtvccdata = 00406 {0xAA,0xDD,0x2A,0xF5,0xF0,0x36,0xF5,0x43,0x95,0xEA,0x6D,0x86,0x64,0x84,0x26,0x2A}; 00407 static const ff_asf_guid mediasubtype_mpeg2_sections = 00408 {0x79,0x85,0x9F,0x4A,0xF8,0x6B,0x92,0x43,0x8A,0x6D,0xD2,0xDD,0x09,0xFA,0x78,0x61}; 00409 00410 /* Formats */ 00411 static const ff_asf_guid format_cpfilters_processed = 00412 {0x6F,0xB3,0x39,0x67,0x5F,0x1D,0xC2,0x4A,0x81,0x92,0x28,0xBB,0x0E,0x73,0xD1,0x6A}; 00413 static const ff_asf_guid format_waveformatex = 00414 {0x81,0x9F,0x58,0x05,0x56,0xC3,0xCE,0x11,0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}; 00415 static const ff_asf_guid format_videoinfo2 = 00416 {0xA0,0x76,0x2A,0xF7,0x0A,0xEB,0xD0,0x11,0xAC,0xE4,0x00,0x00,0xC0,0xCC,0x16,0xBA}; 00417 static const ff_asf_guid format_mpeg2_video = 00418 {0xE3,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}; 00419 static const ff_asf_guid format_none = 00420 {0xD6,0x17,0x64,0x0F,0x18,0xC3,0xD0,0x11,0xA4,0x3F,0x00,0xA0,0xC9,0x22,0x31,0x96}; 00421 00422 static const AVCodecGuid video_guids[] = { 00423 {CODEC_ID_MPEG2VIDEO, {0x26,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}}, 00424 {CODEC_ID_NONE} 00425 }; 00426 00427 static const AVCodecGuid audio_guids[] = { 00428 {CODEC_ID_AC3, {0x2C,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}}, 00429 {CODEC_ID_EAC3, {0xAF,0x87,0xFB,0xA7,0x02,0x2D,0xFB,0x42,0xA4,0xD4,0x05,0xCD,0x93,0x84,0x3B,0xDD}}, 00430 {CODEC_ID_MP2, {0x2B,0x80,0x6D,0xE0,0x46,0xDB,0xCF,0x11,0xB4,0xD1,0x00,0x80,0x5F,0x6C,0xBB,0xEA}}, 00431 {CODEC_ID_NONE} 00432 }; 00433 00434 static int read_probe(AVProbeData *p) 00435 { 00436 return ff_guidcmp(p->buf, wtv_guid) ? 0 : AVPROBE_SCORE_MAX; 00437 } 00438 00442 static void filetime_to_iso8601(char *buf, int buf_size, int64_t value) 00443 { 00444 time_t t = (value / 10000000LL) - 11644473600LL; 00445 strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t)); 00446 } 00447 00451 static void crazytime_to_iso8601(char *buf, int buf_size, int64_t value) 00452 { 00453 time_t t = (value / 10000000LL) - 719162LL*86400LL; 00454 strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t)); 00455 } 00456 00460 static void oledate_to_iso8601(char *buf, int buf_size, int64_t value) 00461 { 00462 time_t t = 631112400LL + 86400*av_int2dbl(value); 00463 strftime(buf, buf_size, "%Y-%m-%d %H:%M:%S", gmtime(&t)); 00464 } 00465 00466 static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length) 00467 { 00468 char mime[1024]; 00469 char description[1024]; 00470 unsigned int filesize; 00471 AVStream *st; 00472 int64_t pos = avio_tell(pb); 00473 00474 avio_get_str16le(pb, INT_MAX, mime, sizeof(mime)); 00475 if (strcmp(mime, "image/jpeg")) 00476 goto done; 00477 00478 avio_r8(pb); 00479 avio_get_str16le(pb, INT_MAX, description, sizeof(description)); 00480 filesize = avio_rl32(pb); 00481 if (!filesize) 00482 goto done; 00483 00484 st = av_new_stream(s, 0); 00485 if (!st) 00486 goto done; 00487 av_dict_set(&st->metadata, "title", description, 0); 00488 st->codec->codec_id = CODEC_ID_MJPEG; 00489 st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT; 00490 st->codec->extradata = av_mallocz(filesize); 00491 if (!st->codec->extradata) 00492 goto done; 00493 st->codec->extradata_size = filesize; 00494 avio_read(pb, st->codec->extradata, filesize); 00495 done: 00496 avio_seek(pb, pos + length, SEEK_SET); 00497 } 00498 00499 static void get_tag(AVFormatContext *s, AVIOContext *pb, const char *key, int type, int length) 00500 { 00501 int buf_size = FFMAX(2*length, LEN_PRETTY_GUID) + 1; 00502 char *buf = av_malloc(buf_size); 00503 if (!buf) 00504 return; 00505 00506 if (type == 0 && length == 4) { 00507 snprintf(buf, buf_size, "%"PRIi32, avio_rl32(pb)); 00508 } else if (type == 1) { 00509 avio_get_str16le(pb, length, buf, buf_size); 00510 if (!strlen(buf)) { 00511 av_free(buf); 00512 return; 00513 } 00514 } else if (type == 3 && length == 4) { 00515 strcpy(buf, avio_rl32(pb) ? "true" : "false"); 00516 } else if (type == 4 && length == 8) { 00517 int64_t num = avio_rl64(pb); 00518 if (!strcmp(key, "WM/EncodingTime") || 00519 !strcmp(key, "WM/MediaOriginalBroadcastDateTime")) 00520 filetime_to_iso8601(buf, buf_size, num); 00521 else if (!strcmp(key, "WM/WMRVEncodeTime") || 00522 !strcmp(key, "WM/WMRVEndTime")) 00523 crazytime_to_iso8601(buf, buf_size, num); 00524 else if (!strcmp(key, "WM/WMRVExpirationDate")) 00525 oledate_to_iso8601(buf, buf_size, num); 00526 else if (!strcmp(key, "WM/WMRVBitrate")) 00527 snprintf(buf, buf_size, "%f", av_int2dbl(num)); 00528 else 00529 snprintf(buf, buf_size, "%"PRIi64, num); 00530 } else if (type == 5 && length == 2) { 00531 snprintf(buf, buf_size, "%"PRIi16, avio_rl16(pb)); 00532 } else if (type == 6 && length == 16) { 00533 ff_asf_guid guid; 00534 avio_read(pb, guid, 16); 00535 snprintf(buf, buf_size, PRI_PRETTY_GUID, ARG_PRETTY_GUID(guid)); 00536 } else if (type == 2 && !strcmp(key, "WM/Picture")) { 00537 get_attachment(s, pb, length); 00538 av_freep(&buf); 00539 return; 00540 } else { 00541 av_freep(&buf); 00542 av_log(s, AV_LOG_WARNING, "unsupported metadata entry; key:%s, type:%d, length:0x%x\n", key, type, length); 00543 avio_skip(pb, length); 00544 return; 00545 } 00546 00547 av_dict_set(&s->metadata, key, buf, 0); 00548 av_freep(&buf); 00549 } 00550 00554 static void parse_legacy_attrib(AVFormatContext *s, AVIOContext *pb) 00555 { 00556 ff_asf_guid guid; 00557 int length, type; 00558 while(!pb->eof_reached) { 00559 char key[1024]; 00560 ff_get_guid(pb, &guid); 00561 type = avio_rl32(pb); 00562 length = avio_rl32(pb); 00563 if (!length) 00564 break; 00565 if (ff_guidcmp(&guid, metadata_guid)) { 00566 av_log(s, AV_LOG_WARNING, "unknown guid "PRI_GUID", expected metadata_guid; " 00567 "remaining metadata entries ignored\n", ARG_GUID(guid)); 00568 break; 00569 } 00570 avio_get_str16le(pb, INT_MAX, key, sizeof(key)); 00571 get_tag(s, pb, key, type, length); 00572 } 00573 00574 ff_metadata_conv(&s->metadata, NULL, ff_asf_metadata_conv); 00575 } 00576 00581 static int parse_videoinfoheader2(AVFormatContext *s, AVStream *st) 00582 { 00583 WtvContext *wtv = s->priv_data; 00584 AVIOContext *pb = wtv->pb; 00585 00586 avio_skip(pb, 72); // picture aspect ratio is unreliable 00587 ff_get_bmp_header(pb, st); 00588 00589 return 72 + 40; 00590 } 00591 00595 static void parse_mpeg1waveformatex(AVStream *st) 00596 { 00597 /* fwHeadLayer */ 00598 switch (AV_RL16(st->codec->extradata)) { 00599 case 0x0001 : st->codec->codec_id = CODEC_ID_MP1; break; 00600 case 0x0002 : st->codec->codec_id = CODEC_ID_MP2; break; 00601 case 0x0004 : st->codec->codec_id = CODEC_ID_MP3; break; 00602 } 00603 00604 st->codec->bit_rate = AV_RL32(st->codec->extradata + 2); /* dwHeadBitrate */ 00605 00606 /* dwHeadMode */ 00607 switch (AV_RL16(st->codec->extradata + 6)) { 00608 case 1 : case 2 : case 4 : st->codec->channels = 2; break; 00609 case 8 : st->codec->channels = 1; break; 00610 } 00611 } 00612 00618 static AVStream * new_stream(AVFormatContext *s, AVStream *st, int sid, int codec_type) 00619 { 00620 if (st) { 00621 if (st->codec->extradata) { 00622 av_freep(&st->codec->extradata); 00623 st->codec->extradata_size = 0; 00624 } 00625 } else { 00626 WtvStream *wst = av_mallocz(sizeof(WtvStream)); 00627 if (!wst) 00628 return NULL; 00629 st = av_new_stream(s, sid); 00630 if (!st) 00631 return NULL; 00632 st->priv_data = wst; 00633 } 00634 st->codec->codec_type = codec_type; 00635 st->need_parsing = AVSTREAM_PARSE_FULL; 00636 av_set_pts_info(st, 64, 1, 10000000); 00637 return st; 00638 } 00639 00649 static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, 00650 ff_asf_guid mediatype, ff_asf_guid subtype, 00651 ff_asf_guid formattype, int size) 00652 { 00653 WtvContext *wtv = s->priv_data; 00654 AVIOContext *pb = wtv->pb; 00655 if (!ff_guidcmp(subtype, mediasubtype_cpfilters_processed) && 00656 !ff_guidcmp(formattype, format_cpfilters_processed)) { 00657 ff_asf_guid actual_subtype; 00658 ff_asf_guid actual_formattype; 00659 00660 if (size < 32) { 00661 av_log(s, AV_LOG_WARNING, "format buffer size underflow\n"); 00662 avio_skip(pb, size); 00663 return NULL; 00664 } 00665 00666 avio_skip(pb, size - 32); 00667 ff_get_guid(pb, &actual_subtype); 00668 ff_get_guid(pb, &actual_formattype); 00669 avio_seek(pb, -size, SEEK_CUR); 00670 00671 st = parse_media_type(s, st, sid, mediatype, actual_subtype, actual_formattype, size - 32); 00672 avio_skip(pb, 32); 00673 return st; 00674 } else if (!ff_guidcmp(mediatype, mediatype_audio)) { 00675 st = new_stream(s, st, sid, AVMEDIA_TYPE_AUDIO); 00676 if (!st) 00677 return NULL; 00678 if (!ff_guidcmp(formattype, format_waveformatex)) { 00679 int ret = ff_get_wav_header(pb, st->codec, size); 00680 if (ret < 0) 00681 return NULL; 00682 } else { 00683 if (ff_guidcmp(formattype, format_none)) 00684 av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); 00685 avio_skip(pb, size); 00686 } 00687 00688 if (!memcmp(subtype + 4, (const uint8_t[]){MEDIASUBTYPE_BASE_GUID}, 12)) { 00689 st->codec->codec_id = ff_wav_codec_get_id(AV_RL32(subtype), st->codec->bits_per_coded_sample); 00690 } else if (!ff_guidcmp(subtype, mediasubtype_mpeg1payload)) { 00691 if (st->codec->extradata && st->codec->extradata_size >= 22) 00692 parse_mpeg1waveformatex(st); 00693 else 00694 av_log(s, AV_LOG_WARNING, "MPEG1WAVEFORMATEX underflow\n"); 00695 } else { 00696 st->codec->codec_id = ff_codec_guid_get_id(audio_guids, subtype); 00697 if (st->codec->codec_id == CODEC_ID_NONE) 00698 av_log(s, AV_LOG_WARNING, "unknown subtype:"PRI_GUID"\n", ARG_GUID(subtype)); 00699 } 00700 return st; 00701 } else if (!ff_guidcmp(mediatype, mediatype_video)) { 00702 st = new_stream(s, st, sid, AVMEDIA_TYPE_VIDEO); 00703 if (!st) 00704 return NULL; 00705 if (!ff_guidcmp(formattype, format_videoinfo2)) { 00706 int consumed = parse_videoinfoheader2(s, st); 00707 avio_skip(pb, FFMAX(size - consumed, 0)); 00708 } else if (!ff_guidcmp(formattype, format_mpeg2_video)) { 00709 int consumed = parse_videoinfoheader2(s, st); 00710 avio_skip(pb, FFMAX(size - consumed, 0)); 00711 } else { 00712 if (ff_guidcmp(formattype, format_none)) 00713 av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); 00714 avio_skip(pb, size); 00715 } 00716 00717 if (!memcmp(subtype + 4, (const uint8_t[]){MEDIASUBTYPE_BASE_GUID}, 12)) { 00718 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype)); 00719 } else { 00720 st->codec->codec_id = ff_codec_guid_get_id(video_guids, subtype); 00721 } 00722 if (st->codec->codec_id == CODEC_ID_NONE) 00723 av_log(s, AV_LOG_WARNING, "unknown subtype:"PRI_GUID"\n", ARG_GUID(subtype)); 00724 return st; 00725 } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_pes) && 00726 !ff_guidcmp(subtype, mediasubtype_dvb_subtitle)) { 00727 st = new_stream(s, st, sid, AVMEDIA_TYPE_SUBTITLE); 00728 if (!st) 00729 return NULL; 00730 if (ff_guidcmp(formattype, format_none)) 00731 av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); 00732 avio_skip(pb, size); 00733 st->codec->codec_id = CODEC_ID_DVB_SUBTITLE; 00734 return st; 00735 } else if (!ff_guidcmp(mediatype, mediatype_mstvcaption) && 00736 (!ff_guidcmp(subtype, mediasubtype_teletext) || !ff_guidcmp(subtype, mediasubtype_dtvccdata))) { 00737 st = new_stream(s, st, sid, AVMEDIA_TYPE_SUBTITLE); 00738 if (!st) 00739 return NULL; 00740 if (ff_guidcmp(formattype, format_none)) 00741 av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); 00742 avio_skip(pb, size); 00743 st->codec->codec_id = CODEC_ID_DVB_TELETEXT; 00744 return st; 00745 } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_sections) && 00746 !ff_guidcmp(subtype, mediasubtype_mpeg2_sections)) { 00747 if (ff_guidcmp(formattype, format_none)) 00748 av_log(s, AV_LOG_WARNING, "unknown formattype:"PRI_GUID"\n", ARG_GUID(formattype)); 00749 avio_skip(pb, size); 00750 return NULL; 00751 } 00752 00753 av_log(s, AV_LOG_WARNING, "unknown media type, mediatype:"PRI_GUID 00754 ", subtype:"PRI_GUID", formattype:"PRI_GUID"\n", 00755 ARG_GUID(mediatype), ARG_GUID(subtype), ARG_GUID(formattype)); 00756 avio_skip(pb, size); 00757 return NULL; 00758 } 00759 00760 enum { 00761 SEEK_TO_DATA = 0, 00762 SEEK_TO_PTS, 00763 }; 00764 00772 static int parse_chunks(AVFormatContext *s, int mode, int64_t seekts, int *len_ptr) 00773 { 00774 WtvContext *wtv = s->priv_data; 00775 AVIOContext *pb = wtv->pb; 00776 while (!pb->eof_reached) { 00777 ff_asf_guid g; 00778 int len, sid, consumed; 00779 00780 ff_get_guid(pb, &g); 00781 len = avio_rl32(pb); 00782 if (len < 32) 00783 break; 00784 sid = avio_rl32(pb) & 0x7FFF; 00785 avio_skip(pb, 8); 00786 consumed = 32; 00787 00788 if (!ff_guidcmp(g, stream_guid)) { 00789 if (ff_find_stream_index(s, sid) < 0) { 00790 ff_asf_guid mediatype, subtype, formattype; 00791 int size; 00792 avio_skip(pb, 28); 00793 ff_get_guid(pb, &mediatype); 00794 ff_get_guid(pb, &subtype); 00795 avio_skip(pb, 12); 00796 ff_get_guid(pb, &formattype); 00797 size = avio_rl32(pb); 00798 parse_media_type(s, 0, sid, mediatype, subtype, formattype, size); 00799 consumed += 92 + size; 00800 } 00801 } else if (!ff_guidcmp(g, stream2_guid)) { 00802 int stream_index = ff_find_stream_index(s, sid); 00803 if (stream_index >= 0 && !((WtvStream*)s->streams[stream_index]->priv_data)->seen_data) { 00804 ff_asf_guid mediatype, subtype, formattype; 00805 int size; 00806 avio_skip(pb, 12); 00807 ff_get_guid(pb, &mediatype); 00808 ff_get_guid(pb, &subtype); 00809 avio_skip(pb, 12); 00810 ff_get_guid(pb, &formattype); 00811 size = avio_rl32(pb); 00812 parse_media_type(s, s->streams[stream_index], sid, mediatype, subtype, formattype, size); 00813 consumed += 76 + size; 00814 } 00815 } else if (!ff_guidcmp(g, EVENTID_AudioDescriptorSpanningEvent) || 00816 !ff_guidcmp(g, EVENTID_CtxADescriptorSpanningEvent) || 00817 !ff_guidcmp(g, EVENTID_CSDescriptorSpanningEvent) || 00818 !ff_guidcmp(g, EVENTID_StreamIDSpanningEvent) || 00819 !ff_guidcmp(g, EVENTID_SubtitleSpanningEvent) || 00820 !ff_guidcmp(g, EVENTID_TeletextSpanningEvent)) { 00821 int stream_index = ff_find_stream_index(s, sid); 00822 if (stream_index >= 0) { 00823 AVStream *st = s->streams[stream_index]; 00824 uint8_t buf[258]; 00825 const uint8_t *pbuf = buf; 00826 int buf_size; 00827 00828 avio_skip(pb, 8); 00829 consumed += 8; 00830 if (!ff_guidcmp(g, EVENTID_CtxADescriptorSpanningEvent) || 00831 !ff_guidcmp(g, EVENTID_CSDescriptorSpanningEvent)) { 00832 avio_skip(pb, 6); 00833 consumed += 6; 00834 } 00835 00836 buf_size = FFMIN(len - consumed, sizeof(buf)); 00837 avio_read(pb, buf, buf_size); 00838 consumed += buf_size; 00839 ff_parse_mpeg2_descriptor(s, st, 0, &pbuf, buf + buf_size, 0, 0, 0, 0); 00840 } 00841 } else if (!ff_guidcmp(g, EVENTID_AudioTypeSpanningEvent)) { 00842 int stream_index = ff_find_stream_index(s, sid); 00843 if (stream_index >= 0) { 00844 AVStream *st = s->streams[stream_index]; 00845 int audio_type; 00846 avio_skip(pb, 8); 00847 audio_type = avio_r8(pb); 00848 if (audio_type == 2) 00849 st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; 00850 else if (audio_type == 3) 00851 st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; 00852 consumed += 9; 00853 } 00854 } else if (!ff_guidcmp(g, EVENTID_DVBScramblingControlSpanningEvent)) { 00855 int stream_index = ff_find_stream_index(s, sid); 00856 if (stream_index >= 0) { 00857 avio_skip(pb, 12); 00858 if (avio_rl32(pb)) 00859 av_log(s, AV_LOG_WARNING, "DVB scrambled stream detected (st:%d), decoding will likely fail\n", stream_index); 00860 consumed += 16; 00861 } 00862 } else if (!ff_guidcmp(g, EVENTID_LanguageSpanningEvent)) { 00863 int stream_index = ff_find_stream_index(s, sid); 00864 if (stream_index >= 0) { 00865 AVStream *st = s->streams[stream_index]; 00866 uint8_t language[4]; 00867 avio_skip(pb, 12); 00868 avio_read(pb, language, 3); 00869 if (language[0]) { 00870 language[3] = 0; 00871 av_dict_set(&st->metadata, "language", language, 0); 00872 if (!strcmp(language, "nar") || !strcmp(language, "NAR")) 00873 st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; 00874 } 00875 consumed += 15; 00876 } 00877 } else if (!ff_guidcmp(g, timestamp_guid)) { 00878 int stream_index = ff_find_stream_index(s, sid); 00879 if (stream_index >= 0) { 00880 avio_skip(pb, 8); 00881 wtv->pts = avio_rl64(pb); 00882 consumed += 16; 00883 if (wtv->pts == -1) 00884 wtv->pts = AV_NOPTS_VALUE; 00885 else { 00886 wtv->last_valid_pts = wtv->pts; 00887 if (wtv->epoch == AV_NOPTS_VALUE || wtv->pts < wtv->epoch) 00888 wtv->epoch = wtv->pts; 00889 if (mode == SEEK_TO_PTS && wtv->pts >= seekts) { 00890 #define WTV_PAD8(x) (((x) + 7) & ~7) 00891 avio_skip(pb, WTV_PAD8(len) - consumed); 00892 return 0; 00893 } 00894 } 00895 } 00896 } else if (!ff_guidcmp(g, data_guid)) { 00897 int stream_index = ff_find_stream_index(s, sid); 00898 if (mode == SEEK_TO_DATA && stream_index >= 0 && len > 32) { 00899 WtvStream *wst = s->streams[stream_index]->priv_data; 00900 wst->seen_data = 1; 00901 if (len_ptr) { 00902 *len_ptr = len; 00903 } 00904 return stream_index; 00905 } 00906 } else if ( 00907 !ff_guidcmp(g, /* DSATTRIB_CAPTURE_STREAMTIME */ (const ff_asf_guid){0x14,0x56,0x1A,0x0C,0xCD,0x30,0x40,0x4F,0xBC,0xBF,0xD0,0x3E,0x52,0x30,0x62,0x07}) || 00908 !ff_guidcmp(g, /* DSATTRIB_PicSampleSeq */ (const ff_asf_guid){0x02,0xAE,0x5B,0x2F,0x8F,0x7B,0x60,0x4F,0x82,0xD6,0xE4,0xEA,0x2F,0x1F,0x4C,0x99}) || 00909 !ff_guidcmp(g, /* DSATTRIB_TRANSPORT_PROPERTIES */ (const ff_asf_guid){0x12,0xF6,0x22,0xB6,0xAD,0x47,0x71,0x46,0xAD,0x6C,0x05,0xA9,0x8E,0x65,0xDE,0x3A}) || 00910 !ff_guidcmp(g, /* dvr_ms_vid_frame_rep_data */ (const ff_asf_guid){0xCC,0x32,0x64,0xDD,0x29,0xE2,0xDB,0x40,0x80,0xF6,0xD2,0x63,0x28,0xD2,0x76,0x1F}) || 00911 !ff_guidcmp(g, /* EVENTID_ChannelChangeSpanningEvent */ (const ff_asf_guid){0xE5,0xC5,0x67,0x90,0x5C,0x4C,0x05,0x42,0x86,0xC8,0x7A,0xFE,0x20,0xFE,0x1E,0xFA}) || 00912 !ff_guidcmp(g, /* EVENTID_ChannelInfoSpanningEvent */ (const ff_asf_guid){0x80,0x6D,0xF3,0x41,0x32,0x41,0xC2,0x4C,0xB1,0x21,0x01,0xA4,0x32,0x19,0xD8,0x1B}) || 00913 !ff_guidcmp(g, /* EVENTID_ChannelTypeSpanningEvent */ (const ff_asf_guid){0x51,0x1D,0xAB,0x72,0xD2,0x87,0x9B,0x48,0xBA,0x11,0x0E,0x08,0xDC,0x21,0x02,0x43}) || 00914 !ff_guidcmp(g, /* EVENTID_PIDListSpanningEvent */ (const ff_asf_guid){0x65,0x8F,0xFC,0x47,0xBB,0xE2,0x34,0x46,0x9C,0xEF,0xFD,0xBF,0xE6,0x26,0x1D,0x5C}) || 00915 !ff_guidcmp(g, /* EVENTID_SignalAndServiceStatusSpanningEvent */ (const ff_asf_guid){0xCB,0xC5,0x68,0x80,0x04,0x3C,0x2B,0x49,0xB4,0x7D,0x03,0x08,0x82,0x0D,0xCE,0x51}) || 00916 !ff_guidcmp(g, /* EVENTID_StreamTypeSpanningEvent */ (const ff_asf_guid){0xBC,0x2E,0xAF,0x82,0xA6,0x30,0x64,0x42,0xA8,0x0B,0xAD,0x2E,0x13,0x72,0xAC,0x60}) || 00917 !ff_guidcmp(g, (const ff_asf_guid){0x1E,0xBE,0xC3,0xC5,0x43,0x92,0xDC,0x11,0x85,0xE5,0x00,0x12,0x3F,0x6F,0x73,0xB9}) || 00918 !ff_guidcmp(g, (const ff_asf_guid){0x3B,0x86,0xA2,0xB1,0xEB,0x1E,0xC3,0x44,0x8C,0x88,0x1C,0xA3,0xFF,0xE3,0xE7,0x6A}) || 00919 !ff_guidcmp(g, (const ff_asf_guid){0x4E,0x7F,0x4C,0x5B,0xC4,0xD0,0x38,0x4B,0xA8,0x3E,0x21,0x7F,0x7B,0xBF,0x52,0xE7}) || 00920 !ff_guidcmp(g, (const ff_asf_guid){0x63,0x36,0xEB,0xFE,0xA1,0x7E,0xD9,0x11,0x83,0x08,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) || 00921 !ff_guidcmp(g, (const ff_asf_guid){0x70,0xE9,0xF1,0xF8,0x89,0xA4,0x4C,0x4D,0x83,0x73,0xB8,0x12,0xE0,0xD5,0xF8,0x1E}) || 00922 !ff_guidcmp(g, (const ff_asf_guid){0x96,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) || 00923 !ff_guidcmp(g, (const ff_asf_guid){0x97,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D}) || 00924 !ff_guidcmp(g, (const ff_asf_guid){0xA1,0xC3,0xD2,0xC2,0x7E,0x9A,0xDA,0x11,0x8B,0xF7,0x00,0x07,0xE9,0x5E,0xAD,0x8D})) { 00925 //ignore known guids 00926 } else 00927 av_log(s, AV_LOG_WARNING, "unsupported chunk:"PRI_GUID"\n", ARG_GUID(g)); 00928 00929 avio_skip(pb, WTV_PAD8(len) - consumed); 00930 } 00931 return AVERROR_EOF; 00932 } 00933 00934 /* declare utf16le strings */ 00935 #define _ , 0, 00936 static const uint8_t timeline_le16[] = 00937 {'t'_'i'_'m'_'e'_'l'_'i'_'n'_'e', 0}; 00938 static const uint8_t table_0_entries_legacy_attrib_le16[] = 00939 {'t'_'a'_'b'_'l'_'e'_'.'_'0'_'.'_'e'_'n'_'t'_'r'_'i'_'e'_'s'_'.'_'l'_'e'_'g'_'a'_'c'_'y'_'_'_'a'_'t'_'t'_'r'_'i'_'b', 0}; 00940 static const uint8_t table_0_entries_time_le16[] = 00941 {'t'_'a'_'b'_'l'_'e'_'.'_'0'_'.'_'e'_'n'_'t'_'r'_'i'_'e'_'s'_'.'_'t'_'i'_'m'_'e', 0}; 00942 static const uint8_t timeline_table_0_entries_Events_le16[] = 00943 {'t'_'i'_'m'_'e'_'l'_'i'_'n'_'e'_'.'_'t'_'a'_'b'_'l'_'e'_'.'_'0'_'.'_'e'_'n'_'t'_'r'_'i'_'e'_'s'_'.'_'E'_'v'_'e'_'n'_'t'_'s', 0}; 00944 #undef _ 00945 00946 static int read_header(AVFormatContext *s, AVFormatParameters *ap) 00947 { 00948 WtvContext *wtv = s->priv_data; 00949 int root_sector, root_size; 00950 uint8_t root[WTV_SECTOR_SIZE]; 00951 AVIOContext *pb; 00952 int64_t timeline_pos; 00953 int ret; 00954 00955 wtv->epoch = 00956 wtv->pts = 00957 wtv->last_valid_pts = AV_NOPTS_VALUE; 00958 00959 /* read root directory sector */ 00960 avio_skip(s->pb, 0x30); 00961 root_size = avio_rl32(s->pb); 00962 if (root_size > sizeof(root)) { 00963 av_log(s, AV_LOG_ERROR, "root directory size exceeds sector size\n"); 00964 return AVERROR_INVALIDDATA; 00965 } 00966 avio_skip(s->pb, 4); 00967 root_sector = avio_rl32(s->pb); 00968 00969 avio_seek(s->pb, root_sector << WTV_SECTOR_BITS, SEEK_SET); 00970 root_size = avio_read(s->pb, root, root_size); 00971 if (root_size < 0) 00972 return AVERROR_INVALIDDATA; 00973 00974 /* parse chunks up until first data chunk */ 00975 wtv->pb = wtvfile_open(s, root, root_size, timeline_le16); 00976 if (!wtv->pb) { 00977 av_log(s, AV_LOG_ERROR, "timeline data missing\n"); 00978 return AVERROR_INVALIDDATA; 00979 } 00980 00981 ret = parse_chunks(s, SEEK_TO_DATA, 0, 0); 00982 if (ret < 0) 00983 return ret; 00984 avio_seek(wtv->pb, -32, SEEK_CUR); 00985 00986 timeline_pos = avio_tell(s->pb); // save before opening another file 00987 00988 /* read metadata */ 00989 pb = wtvfile_open(s, root, root_size, table_0_entries_legacy_attrib_le16); 00990 if (pb) { 00991 parse_legacy_attrib(s, pb); 00992 wtvfile_close(pb); 00993 } 00994 00995 /* read seek index */ 00996 if (s->nb_streams) { 00997 AVStream *st = s->streams[0]; 00998 pb = wtvfile_open(s, root, root_size, table_0_entries_time_le16); 00999 if (pb) { 01000 while(1) { 01001 uint64_t timestamp = avio_rl64(pb); 01002 uint64_t frame_nb = avio_rl64(pb); 01003 if (pb->eof_reached) 01004 break; 01005 ff_add_index_entry(&wtv->index_entries, &wtv->nb_index_entries, &wtv->index_entries_allocated_size, 01006 0, timestamp, frame_nb, 0, AVINDEX_KEYFRAME); 01007 } 01008 wtvfile_close(pb); 01009 01010 if (wtv->nb_index_entries) { 01011 pb = wtvfile_open(s, root, root_size, timeline_table_0_entries_Events_le16); 01012 if (pb) { 01013 int i; 01014 while (1) { 01015 uint64_t frame_nb = avio_rl64(pb); 01016 uint64_t position = avio_rl64(pb); 01017 if (pb->eof_reached) 01018 break; 01019 for (i = wtv->nb_index_entries - 1; i >= 0; i--) { 01020 AVIndexEntry *e = wtv->index_entries + i; 01021 if (frame_nb > e->size) 01022 break; 01023 if (position > e->pos) 01024 e->pos = position; 01025 } 01026 } 01027 wtvfile_close(pb); 01028 st->duration = wtv->index_entries[wtv->nb_index_entries - 1].timestamp; 01029 } 01030 } 01031 } 01032 } 01033 01034 avio_seek(s->pb, timeline_pos, SEEK_SET); 01035 return 0; 01036 } 01037 01038 static int read_packet(AVFormatContext *s, AVPacket *pkt) 01039 { 01040 WtvContext *wtv = s->priv_data; 01041 AVIOContext *pb = wtv->pb; 01042 int stream_index, len, ret; 01043 01044 stream_index = parse_chunks(s, SEEK_TO_DATA, 0, &len); 01045 if (stream_index < 0) 01046 return stream_index; 01047 01048 ret = av_get_packet(pb, pkt, len - 32); 01049 if (ret < 0) 01050 return ret; 01051 pkt->stream_index = stream_index; 01052 pkt->pts = wtv->pts; 01053 avio_skip(pb, WTV_PAD8(len) - len); 01054 return 0; 01055 } 01056 01057 static int read_seek(AVFormatContext *s, int stream_index, 01058 int64_t ts, int flags) 01059 { 01060 WtvContext *wtv = s->priv_data; 01061 AVIOContext *pb = wtv->pb; 01062 AVStream *st = s->streams[0]; 01063 int64_t ts_relative; 01064 int i; 01065 01066 if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE)) 01067 return AVERROR(ENOSYS); 01068 01069 /* timestamp adjustment is required because wtv->pts values are absolute, 01070 * whereas AVIndexEntry->timestamp values are relative to epoch. */ 01071 ts_relative = ts; 01072 if (wtv->epoch != AV_NOPTS_VALUE) 01073 ts_relative -= wtv->epoch; 01074 01075 i = ff_index_search_timestamp(wtv->index_entries, wtv->nb_index_entries, ts_relative, flags); 01076 if (i < 0) { 01077 if (wtv->last_valid_pts == AV_NOPTS_VALUE || ts < wtv->last_valid_pts) 01078 avio_seek(pb, 0, SEEK_SET); 01079 else if (st->duration != AV_NOPTS_VALUE && ts_relative > st->duration && wtv->nb_index_entries) 01080 avio_seek(pb, wtv->index_entries[wtv->nb_index_entries - 1].pos, SEEK_SET); 01081 if (parse_chunks(s, SEEK_TO_PTS, ts, 0) < 0) 01082 return AVERROR(ERANGE); 01083 return 0; 01084 } 01085 wtv->pts = wtv->index_entries[i].timestamp; 01086 if (wtv->epoch != AV_NOPTS_VALUE) 01087 wtv->pts += wtv->epoch; 01088 wtv->last_valid_pts = wtv->pts; 01089 avio_seek(pb, wtv->index_entries[i].pos, SEEK_SET); 01090 return 0; 01091 } 01092 01093 static int read_close(AVFormatContext *s) 01094 { 01095 WtvContext *wtv = s->priv_data; 01096 wtvfile_close(wtv->pb); 01097 return 0; 01098 } 01099 01100 AVInputFormat ff_wtv_demuxer = { 01101 .name = "wtv", 01102 .long_name = NULL_IF_CONFIG_SMALL("Windows Television (WTV)"), 01103 .priv_data_size = sizeof(WtvContext), 01104 .read_probe = read_probe, 01105 .read_header = read_header, 01106 .read_packet = read_packet, 01107 .read_seek = read_seek, 01108 .read_close = read_close, 01109 .flags = AVFMT_SHOW_IDS, 01110 };