Mercurial > libavformat.hg
annotate pva.c @ 6491:b7f807b4cd88 libavformat tip
In mov demuxer, check that nb_streams is valid before using it in read_dac3
| author | bcoudurier |
|---|---|
| date | Tue, 28 Sep 2010 00:33:21 +0000 |
| parents | 536e5527c1e0 |
| children |
| rev | line source |
|---|---|
| 2880 | 1 /* |
| 2 * TechnoTrend PVA (.pva) demuxer | |
| 3 * Copyright (c) 2007, 2008 Ivo van Poorten | |
| 4 * | |
| 5 * This file is part of FFmpeg. | |
| 6 * | |
| 7 * FFmpeg is free software; you can redistribute it and/or | |
| 8 * modify it under the terms of the GNU Lesser General Public | |
| 9 * License as published by the Free Software Foundation; either | |
| 10 * version 2.1 of the License, or (at your option) any later version. | |
| 11 * | |
| 12 * FFmpeg is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 * Lesser General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU Lesser General Public | |
| 18 * License along with FFmpeg; if not, write to the Free Software | |
| 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 */ | |
| 21 | |
| 22 #include "avformat.h" | |
|
2907
b548dfced05b
use ff_parse_pes_pts for parsing an MPEG-PES timestamp
ivo
parents:
2900
diff
changeset
|
23 #include "mpeg.h" |
| 2880 | 24 |
| 25 #define PVA_MAX_PAYLOAD_LENGTH 0x17f8 | |
| 26 #define PVA_VIDEO_PAYLOAD 0x01 | |
| 27 #define PVA_AUDIO_PAYLOAD 0x02 | |
| 28 #define PVA_MAGIC (('A' << 8) + 'V') | |
| 29 | |
| 30 typedef struct { | |
| 31 int continue_pes; | |
| 32 } PVAContext; | |
| 33 | |
| 34 static int pva_probe(AVProbeData * pd) { | |
| 35 unsigned char *buf = pd->buf; | |
| 36 | |
| 37 if (AV_RB16(buf) == PVA_MAGIC && buf[2] && buf[2] < 3 && buf[4] == 0x55) | |
| 38 return AVPROBE_SCORE_MAX / 2; | |
| 39 | |
| 40 return 0; | |
| 41 } | |
| 42 | |
| 43 static int pva_read_header(AVFormatContext *s, AVFormatParameters *ap) { | |
| 44 AVStream *st; | |
| 45 | |
| 46 if (!(st = av_new_stream(s, 0))) | |
| 47 return AVERROR(ENOMEM); | |
|
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4968
diff
changeset
|
48 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
| 2880 | 49 st->codec->codec_id = CODEC_ID_MPEG2VIDEO; |
| 50 st->need_parsing = AVSTREAM_PARSE_FULL; | |
| 51 av_set_pts_info(st, 32, 1, 90000); | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
52 av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME); |
| 2880 | 53 |
| 54 if (!(st = av_new_stream(s, 1))) | |
| 55 return AVERROR(ENOMEM); | |
|
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4968
diff
changeset
|
56 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
| 2896 | 57 st->codec->codec_id = CODEC_ID_MP2; |
|
4968
72b7219c6337
technically mp2 in pva needs AVSTREAM_PARSE_FULL
bcoudurier
parents:
4903
diff
changeset
|
58 st->need_parsing = AVSTREAM_PARSE_FULL; |
| 2880 | 59 av_set_pts_info(st, 33, 1, 90000); |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
60 av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME); |
| 2880 | 61 |
| 62 /* the parameters will be extracted from the compressed bitstream */ | |
| 63 return 0; | |
| 64 } | |
| 65 | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
66 #define pva_log if (read_packet) av_log |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
67 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
68 static int read_part_of_packet(AVFormatContext *s, int64_t *pts, |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
69 int *len, int *strid, int read_packet) { |
| 2880 | 70 ByteIOContext *pb = s->pb; |
| 71 PVAContext *pvactx = s->priv_data; | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
72 int syncword, streamid, reserved, flags, length, pts_flag; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
73 int64_t pva_pts = AV_NOPTS_VALUE, startpos; |
| 2880 | 74 |
|
2898
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
75 recover: |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
76 startpos = url_ftell(pb); |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
77 |
| 2880 | 78 syncword = get_be16(pb); |
| 79 streamid = get_byte(pb); | |
| 80 get_byte(pb); /* counter not used */ | |
| 81 reserved = get_byte(pb); | |
| 82 flags = get_byte(pb); | |
| 83 length = get_be16(pb); | |
| 84 | |
| 2900 | 85 pts_flag = flags & 0x10; |
| 2880 | 86 |
| 87 if (syncword != PVA_MAGIC) { | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
88 pva_log(s, AV_LOG_ERROR, "invalid syncword\n"); |
| 2880 | 89 return AVERROR(EIO); |
| 90 } | |
| 2897 | 91 if (streamid != PVA_VIDEO_PAYLOAD && streamid != PVA_AUDIO_PAYLOAD) { |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
92 pva_log(s, AV_LOG_ERROR, "invalid streamid\n"); |
| 2897 | 93 return AVERROR(EIO); |
| 94 } | |
| 2880 | 95 if (reserved != 0x55) { |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
96 pva_log(s, AV_LOG_WARNING, "expected reserved byte to be 0x55\n"); |
| 2880 | 97 } |
| 98 if (length > PVA_MAX_PAYLOAD_LENGTH) { | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
99 pva_log(s, AV_LOG_ERROR, "invalid payload length %u\n", length); |
| 2880 | 100 return AVERROR(EIO); |
| 101 } | |
| 102 | |
| 103 if (streamid == PVA_VIDEO_PAYLOAD && pts_flag) { | |
| 104 pva_pts = get_be32(pb); | |
| 105 length -= 4; | |
| 106 } else if (streamid == PVA_AUDIO_PAYLOAD) { | |
| 107 /* PVA Audio Packets either start with a signaled PES packet or | |
| 108 * are a continuation of the previous PES packet. New PES packets | |
| 109 * always start at the beginning of a PVA Packet, never somewhere in | |
| 110 * the middle. */ | |
| 111 if (!pvactx->continue_pes) { | |
| 112 int pes_signal, pes_header_data_length, pes_packet_length, | |
| 113 pes_flags; | |
| 114 unsigned char pes_header_data[256]; | |
| 115 | |
| 116 pes_signal = get_be24(pb); | |
| 117 get_byte(pb); | |
| 118 pes_packet_length = get_be16(pb); | |
| 119 pes_flags = get_be16(pb); | |
| 120 pes_header_data_length = get_byte(pb); | |
| 121 | |
| 122 if (pes_signal != 1) { | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
123 pva_log(s, AV_LOG_WARNING, "expected signaled PES packet, " |
|
2898
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
124 "trying to recover\n"); |
|
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
125 url_fskip(pb, length - 9); |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
126 if (!read_packet) |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
127 return AVERROR(EIO); |
|
2898
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
128 goto recover; |
| 2880 | 129 } |
| 130 | |
| 131 get_buffer(pb, pes_header_data, pes_header_data_length); | |
| 132 length -= 9 + pes_header_data_length; | |
| 133 | |
| 134 pes_packet_length -= 3 + pes_header_data_length; | |
| 135 | |
| 136 pvactx->continue_pes = pes_packet_length; | |
| 137 | |
|
2907
b548dfced05b
use ff_parse_pes_pts for parsing an MPEG-PES timestamp
ivo
parents:
2900
diff
changeset
|
138 if (pes_flags & 0x80 && (pes_header_data[0] & 0xf0) == 0x20) |
|
b548dfced05b
use ff_parse_pes_pts for parsing an MPEG-PES timestamp
ivo
parents:
2900
diff
changeset
|
139 pva_pts = ff_parse_pes_pts(pes_header_data); |
| 2880 | 140 } |
| 141 | |
| 142 pvactx->continue_pes -= length; | |
| 143 | |
| 144 if (pvactx->continue_pes < 0) { | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
145 pva_log(s, AV_LOG_WARNING, "audio data corruption\n"); |
| 2880 | 146 pvactx->continue_pes = 0; |
| 147 } | |
| 148 } | |
| 149 | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
150 if (pva_pts != AV_NOPTS_VALUE) |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
151 av_add_index_entry(s->streams[streamid-1], startpos, pva_pts, 0, 0, AVINDEX_KEYFRAME); |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
152 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
153 *pts = pva_pts; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
154 *len = length; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
155 *strid = streamid; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
156 return 0; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
157 } |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
158 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
159 static int pva_read_packet(AVFormatContext *s, AVPacket *pkt) { |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
160 ByteIOContext *pb = s->pb; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
161 int64_t pva_pts; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
162 int ret, length, streamid; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
163 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
164 if (read_part_of_packet(s, &pva_pts, &length, &streamid, 1) < 0 || |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
165 (ret = av_get_packet(pb, pkt, length)) <= 0) |
| 2880 | 166 return AVERROR(EIO); |
| 167 | |
| 168 pkt->stream_index = streamid - 1; | |
| 2909 | 169 pkt->pts = pva_pts; |
| 2880 | 170 |
| 171 return ret; | |
| 172 } | |
| 173 | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
174 static int64_t pva_read_timestamp(struct AVFormatContext *s, int stream_index, |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
175 int64_t *pos, int64_t pos_limit) { |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
176 ByteIOContext *pb = s->pb; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
177 PVAContext *pvactx = s->priv_data; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
178 int length, streamid; |
| 4903 | 179 int64_t res = AV_NOPTS_VALUE; |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
180 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
181 pos_limit = FFMIN(*pos+PVA_MAX_PAYLOAD_LENGTH*8, (uint64_t)*pos+pos_limit); |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
182 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
183 while (*pos < pos_limit) { |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
184 res = AV_NOPTS_VALUE; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
185 url_fseek(pb, *pos, SEEK_SET); |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
186 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
187 pvactx->continue_pes = 0; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
188 if (read_part_of_packet(s, &res, &length, &streamid, 0)) { |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
189 (*pos)++; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
190 continue; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
191 } |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
192 if (streamid - 1 != stream_index || res == AV_NOPTS_VALUE) { |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
193 *pos = url_ftell(pb) + length; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
194 continue; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
195 } |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
196 break; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
197 } |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
198 |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
199 pvactx->continue_pes = 0; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
200 return res; |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
201 } |
|
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
202 |
| 2880 | 203 AVInputFormat pva_demuxer = { |
| 204 "pva", | |
|
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
2910
diff
changeset
|
205 NULL_IF_CONFIG_SMALL("TechnoTrend PVA file and stream format"), |
| 2880 | 206 sizeof(PVAContext), |
| 207 pva_probe, | |
| 208 pva_read_header, | |
| 209 pva_read_packet, | |
|
2910
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
210 .read_timestamp = pva_read_timestamp |
| 2880 | 211 }; |
