Mercurial > libavformat.hg
annotate pva.c @ 4002:65cb6eca2944 libavformat
matroskaenc: require global header
fixes issue696
author | aurel |
---|---|
date | Wed, 22 Oct 2008 21:14:42 +0000 |
parents | 7a0230981402 |
children | 0b5471a1f061 |
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); | |
48 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
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); | |
56 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
2896 | 57 st->codec->codec_id = CODEC_ID_MP2; |
2880 | 58 st->need_parsing = AVSTREAM_PARSE_HEADERS; |
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; |
dfb3aa1324c7
Implement read_timestamp and enable seeking in PVA files.
ivo
parents:
2909
diff
changeset
|
179 int64_t res; |
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 }; |