34#define SERIES1_PES_LENGTH 11
35#define SERIES2_PES_LENGTH 16
36#define AC3_PES_LENGTH 14
37#define VIDEO_PES_LENGTH 16
38#define DTIVO_PTS_OFFSET 6
39#define SA_PTS_OFFSET 9
40#define AC3_PTS_OFFSET 9
41#define VIDEO_PTS_OFFSET 9
42#define AC3_PKT_LENGTH 1536
48#define TIVO_PES_FILEID 0xf5467abd
49#define CHUNK_SIZE (128 * 1024)
50#define CHUNK_PEEK_COUNT 3
129 for (
i = 0;
i < num_recs;
i++) {
130 const uint8_t *record_header = buf + (
i * 16);
133 rec_hdr->
rec_type = record_header[3];
134 rec_hdr->subrec_type = record_header[2] & 0x0f;
135 if ((record_header[0] & 0x80) == 0x80) {
139 b1 = (((record_header[0] & 0x0f) << 4) |
140 ((record_header[1] & 0xf0) >> 4));
141 b2 = (((record_header[1] & 0x0f) << 4) |
142 ((record_header[2] & 0xf0) >> 4));
146 rec_hdr->rec_size = 0;
149 rec_hdr->rec_size = (record_header[0] << 8 |
150 record_header[1]) << 4 |
151 (record_header[2] >> 4);
152 rec_hdr->ty_pts =
AV_RB64(&record_header[8]);
159 const uint8_t *
buffer,
int search_len)
163 for (count = 0; count < search_len; count++) {
175 int num_6e0, num_be0, num_9c0, num_3c0;
190 ff_dlog(
s,
"probe: chunk has %d recs\n", num_recs);
202 num_6e0 = num_be0 = num_9c0 = num_3c0 = 0;
203 for (
i = 0;
i < num_recs;
i++) {
204 switch (hdrs[
i].subrec_type << 8 | hdrs[
i].rec_type) {
219 ff_dlog(
s,
"probe: chunk has %d 0x6e0 recs, %d 0xbe0 recs.\n",
224 ff_dlog(
s,
"detected Series 1 Tivo\n");
227 }
else if (num_be0 > 0) {
228 ff_dlog(
s,
"detected Series 2 Tivo\n");
233 ff_dlog(
s,
"detected AC-3 Audio (DTivo)\n");
238 }
else if (num_3c0 > 0) {
240 ff_dlog(
s,
"detected MPEG Audio\n");
246 uint32_t data_offset = 16 * num_recs;
248 for (
i = 0;
i < num_recs;
i++) {
252 if ((hdrs[
i].subrec_type << 8 | hdrs[
i].rec_type) == 0x3c0 && hdrs[
i].rec_size > 15) {
255 &chunk[data_offset], 5);
256 if (pes_offset >= 0) {
258 if ((chunk[data_offset + 6 + pes_offset] & 0x80) == 0x80) {
261 ff_dlog(
s,
"detected Stand-Alone Tivo\n");
266 ff_dlog(
s,
"detected DirecTV Tivo\n");
341 int read_size, num_recs;
364 if (ty->
chunk[3] & 0x80) {
374 ff_dlog(
s,
"chunk has %d records\n", num_recs);
398 if (subrec_type != 0x02 && subrec_type != 0x0c &&
399 subrec_type != 0x08 && rec_size > 7) {
405 if (es_offset1 != -1) {
411 if (subrec_type != 0x06) {
423 pkt->stream_index = 0;
426 ff_dlog(
s,
"video rec type 0x%02x has short PES"
427 " (%"PRId64
" bytes)\n", subrec_type, rec_size);
436 if (subrec_type == 0x06) {
447 pkt->stream_index = 0;
452 if (subrec_type != 0x02) {
453 if (subrec_type == 0x0c &&
pkt->size >= 6)
454 pkt->data[5] |= 0x08;
455 if (subrec_type == 0x07) {
487 ff_dlog(
s,
"PES header at %"PRId32
" not complete in record. storing.\n",
offset);
494 ff_dlog(
s,
"PES header not found in record of %"PRId32
" bytes!\n", rec_len);
525 if (subrec_type == 2) {
535 ff_dlog(
s,
"continuing PES header\n");
537 if (need >= rec_size) {
556 if (es_offset1 < 0) {
557 ff_dlog(
s,
"Can't find audio PES header in packet.\n");
570 pkt->stream_index = 1;
587 }
else if (subrec_type == 0x03) {
592 pkt->stream_index = 1;
599 if ((es_offset1 == 0) && (rec_size == 16)) {
616 }
else if (subrec_type == 0x04) {
623 pkt->stream_index = 1;
625 }
else if (subrec_type == 0x09) {
630 pkt->stream_index = 1;
724 .p.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 i(width, name, range_min, range_max)
static int read_probe(const AVProbeData *p)
static int read_header(FFV1Context *f, RangeCoder *c)
@ 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 struct 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.
#define AV_NOPTS_VALUE
Undefined timestamp value.
Macro definitions for various function/variable attributes.
#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)
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
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.
This structure contains the data a format has to probe a file.
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 TyRecHdr * parse_chunk_headers(const uint8_t *buf, int num_recs)
static int demux_audio(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt)
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 int find_es_header(const uint8_t *header, const uint8_t *buffer, int search_len)
static int ty_read_close(AVFormatContext *s)
static double b1(void *priv, double x, double y)
static double b2(void *priv, double x, double y)