31 #define SERIES1_PES_LENGTH 11
32 #define SERIES2_PES_LENGTH 16
33 #define AC3_PES_LENGTH 14
34 #define VIDEO_PES_LENGTH 16
35 #define DTIVO_PTS_OFFSET 6
36 #define SA_PTS_OFFSET 9
37 #define AC3_PTS_OFFSET 9
38 #define VIDEO_PTS_OFFSET 9
39 #define AC3_PKT_LENGTH 1536
45 #define TIVO_PES_FILEID 0xf5467abd
46 #define CHUNK_SIZE (128 * 1024)
47 #define CHUNK_PEEK_COUNT 3
126 for (
i = 0;
i < num_recs;
i++) {
127 const uint8_t *record_header = buf + (
i * 16);
130 rec_hdr->
rec_type = record_header[3];
131 rec_hdr->subrec_type = record_header[2] & 0x0f;
132 if ((record_header[0] & 0x80) == 0x80) {
136 b1 = (((record_header[0] & 0x0f) << 4) |
137 ((record_header[1] & 0xf0) >> 4));
138 b2 = (((record_header[1] & 0x0f) << 4) |
139 ((record_header[2] & 0xf0) >> 4));
143 rec_hdr->rec_size = 0;
146 rec_hdr->rec_size = (record_header[0] << 8 |
147 record_header[1]) << 4 |
148 (record_header[2] >> 4);
149 rec_hdr->ty_pts =
AV_RB64(&record_header[8]);
160 for (count = 0; count < search_len; count++) {
172 int num_6e0, num_be0, num_9c0, num_3c0;
187 ff_dlog(
s,
"probe: chunk has %d recs\n", num_recs);
199 num_6e0 = num_be0 = num_9c0 = num_3c0 = 0;
200 for (
i = 0;
i < num_recs;
i++) {
201 switch (hdrs[
i].subrec_type << 8 | hdrs[
i].rec_type) {
216 ff_dlog(
s,
"probe: chunk has %d 0x6e0 recs, %d 0xbe0 recs.\n",
221 ff_dlog(
s,
"detected Series 1 Tivo\n");
224 }
else if (num_be0 > 0) {
225 ff_dlog(
s,
"detected Series 2 Tivo\n");
230 ff_dlog(
s,
"detected AC-3 Audio (DTivo)\n");
235 }
else if (num_3c0 > 0) {
237 ff_dlog(
s,
"detected MPEG Audio\n");
243 uint32_t data_offset = 16 * num_recs;
245 for (
i = 0;
i < num_recs;
i++) {
249 if ((hdrs[
i].subrec_type << 8 | hdrs[
i].rec_type) == 0x3c0 && hdrs[
i].rec_size > 15) {
252 &chunk[data_offset], 5);
253 if (pes_offset >= 0) {
255 if ((chunk[data_offset + 6 + pes_offset] & 0x80) == 0x80) {
258 ff_dlog(
s,
"detected Stand-Alone Tivo\n");
263 ff_dlog(
s,
"detected DirecTV Tivo\n");
338 int read_size, num_recs;
361 if (ty->
chunk[3] & 0x80) {
371 ff_dlog(
s,
"chunk has %d records\n", num_recs);
395 if (subrec_type != 0x02 && subrec_type != 0x0c &&
396 subrec_type != 0x08 && rec_size > 4) {
401 if (es_offset1 != -1) {
404 if (subrec_type != 0x06) {
419 ff_dlog(
s,
"video rec type 0x%02x has short PES"
420 " (%"PRId64
" bytes)\n", subrec_type, rec_size);
429 if (subrec_type == 0x06) {
445 if (subrec_type != 0x02) {
446 if (subrec_type == 0x0c &&
pkt->
size >= 6)
448 if (subrec_type == 0x07) {
478 if (offset < 0 || offset + ty->pes_length > rec_len) {
480 ff_dlog(
s,
"PES header at %"PRId32
" not complete in record. storing.\n",
offset);
487 ff_dlog(
s,
"PES header not found in record of %"PRId32
" bytes!\n", rec_len);
518 if (subrec_type == 2) {
528 ff_dlog(
s,
"continuing PES header\n");
530 if (need >= rec_size) {
549 if (es_offset1 < 0) {
550 ff_dlog(
s,
"Can't find audio PES header in packet.\n");
580 }
else if (subrec_type == 0x03) {
592 if ((es_offset1 == 0) && (rec_size == 16)) {
609 }
else if (subrec_type == 0x04) {
618 }
else if (subrec_type == 0x09) {
721 .extensions =
"ty,ty+",
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
#define flags(name, subs,...)
static int read_header(FFV1Context *f)
@ AV_CODEC_ID_MPEG2VIDEO
preferred ID for MPEG-1/2 video decoding
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define AVERROR_EOF
End of file.
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
#define AV_NOPTS_VALUE
Undefined timestamp value.
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static av_cold int read_close(AVFormatContext *ctx)
static int64_t ff_parse_pes_pts(const uint8_t *buf)
Parse MPEG-PES five-byte timestamp.
static const uint8_t header[24]
enum AVMediaType codec_type
General type of the encoded data.
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
This structure contains the data a format has to probe a file.
int buf_size
Size of buf except extra allocated bytes.
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
AVCodecParameters * codecpar
Codec parameters associated with this stream.
enum AVStreamParseType need_parsing
uint8_t chunk[CHUNK_SIZE]
static int analyze_chunk(AVFormatContext *s, const uint8_t *chunk)
static int check_sync_pes(AVFormatContext *s, AVPacket *pkt, int32_t offset, int32_t rec_len)
static int ty_probe(const AVProbeData *p)
static const uint8_t ty_MPEGAudioPacket[]
static const uint8_t ty_AC3AudioPacket[]
static int ty_read_packet(AVFormatContext *s, AVPacket *pkt)
static int demux_audio(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt)
AVInputFormat ff_ty_demuxer
static int demux_video(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt)
#define SERIES1_PES_LENGTH
static int get_chunk(AVFormatContext *s)
static const uint8_t ty_VideoPacket[]
static int ty_read_header(AVFormatContext *s)
#define SERIES2_PES_LENGTH
static TyRecHdr * parse_chunk_headers(const uint8_t *buf, int num_recs)
static int find_es_header(const uint8_t *header, const uint8_t *buffer, int search_len)
static int ty_read_close(AVFormatContext *s)
static const uint8_t offset[127][2]
static double b1(void *priv, double x, double y)
static double b2(void *priv, double x, double y)