Mercurial > libavformat.hg
annotate pva.c @ 5200:cd884511ec8b libavformat
Make packet interleaving in the muxer not scan through the whole
buffer when simply appending at the end works.
Much faster if one stream ends prematurely.
Fixes issue1379.
author | michael |
---|---|
date | Wed, 16 Sep 2009 00:59:15 +0000 |
parents | 72b7219c6337 |
children | 536e5527c1e0 |
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; |
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 }; |