Mercurial > libavformat.hg
annotate pva.c @ 2904:72e3c40f0fb2 libavformat
cosmetics: Add another pair of parentheses to aid readability.
author | diego |
---|---|
date | Sun, 06 Jan 2008 22:50:09 +0000 |
parents | a28c002dd2b4 |
children | b548dfced05b |
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" | |
23 | |
24 #define PVA_MAX_PAYLOAD_LENGTH 0x17f8 | |
25 #define PVA_VIDEO_PAYLOAD 0x01 | |
26 #define PVA_AUDIO_PAYLOAD 0x02 | |
27 #define PVA_MAGIC (('A' << 8) + 'V') | |
28 | |
29 typedef struct { | |
30 int continue_pes; | |
31 } PVAContext; | |
32 | |
33 static int pva_probe(AVProbeData * pd) { | |
34 unsigned char *buf = pd->buf; | |
35 | |
36 if (AV_RB16(buf) == PVA_MAGIC && buf[2] && buf[2] < 3 && buf[4] == 0x55) | |
37 return AVPROBE_SCORE_MAX / 2; | |
38 | |
39 return 0; | |
40 } | |
41 | |
42 static int pva_read_header(AVFormatContext *s, AVFormatParameters *ap) { | |
43 AVStream *st; | |
44 | |
45 if (!(st = av_new_stream(s, 0))) | |
46 return AVERROR(ENOMEM); | |
47 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
48 st->codec->codec_id = CODEC_ID_MPEG2VIDEO; | |
49 st->need_parsing = AVSTREAM_PARSE_FULL; | |
50 av_set_pts_info(st, 32, 1, 90000); | |
51 | |
52 if (!(st = av_new_stream(s, 1))) | |
53 return AVERROR(ENOMEM); | |
54 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
2896 | 55 st->codec->codec_id = CODEC_ID_MP2; |
2880 | 56 st->need_parsing = AVSTREAM_PARSE_HEADERS; |
57 av_set_pts_info(st, 33, 1, 90000); | |
58 | |
59 /* the parameters will be extracted from the compressed bitstream */ | |
60 return 0; | |
61 } | |
62 | |
63 static int pva_read_packet(AVFormatContext *s, AVPacket *pkt) { | |
64 ByteIOContext *pb = s->pb; | |
65 PVAContext *pvactx = s->priv_data; | |
66 int ret, syncword, streamid, reserved, flags, length, pts_flag; | |
2895 | 67 int64_t pva_pts = AV_NOPTS_VALUE; |
2880 | 68 |
2898
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
69 recover: |
2880 | 70 syncword = get_be16(pb); |
71 streamid = get_byte(pb); | |
72 get_byte(pb); /* counter not used */ | |
73 reserved = get_byte(pb); | |
74 flags = get_byte(pb); | |
75 length = get_be16(pb); | |
76 | |
2900 | 77 pts_flag = flags & 0x10; |
2880 | 78 |
79 if (syncword != PVA_MAGIC) { | |
80 av_log(s, AV_LOG_ERROR, "invalid syncword\n"); | |
81 return AVERROR(EIO); | |
82 } | |
2897 | 83 if (streamid != PVA_VIDEO_PAYLOAD && streamid != PVA_AUDIO_PAYLOAD) { |
84 av_log(s, AV_LOG_ERROR, "invalid streamid\n"); | |
85 return AVERROR(EIO); | |
86 } | |
2880 | 87 if (reserved != 0x55) { |
88 av_log(s, AV_LOG_WARNING, "expected reserved byte to be 0x55\n"); | |
89 } | |
90 if (length > PVA_MAX_PAYLOAD_LENGTH) { | |
91 av_log(s, AV_LOG_ERROR, "invalid payload length %u\n", length); | |
92 return AVERROR(EIO); | |
93 } | |
94 | |
95 if (streamid == PVA_VIDEO_PAYLOAD && pts_flag) { | |
96 pva_pts = get_be32(pb); | |
97 length -= 4; | |
98 } else if (streamid == PVA_AUDIO_PAYLOAD) { | |
99 /* PVA Audio Packets either start with a signaled PES packet or | |
100 * are a continuation of the previous PES packet. New PES packets | |
101 * always start at the beginning of a PVA Packet, never somewhere in | |
102 * the middle. */ | |
103 if (!pvactx->continue_pes) { | |
104 int pes_signal, pes_header_data_length, pes_packet_length, | |
105 pes_flags; | |
106 unsigned char pes_header_data[256]; | |
107 | |
108 pes_signal = get_be24(pb); | |
109 get_byte(pb); | |
110 pes_packet_length = get_be16(pb); | |
111 pes_flags = get_be16(pb); | |
112 pes_header_data_length = get_byte(pb); | |
113 | |
114 if (pes_signal != 1) { | |
2898
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
115 av_log(s, AV_LOG_WARNING, "expected signaled PES packet, " |
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
116 "trying to recover\n"); |
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
117 url_fskip(pb, length - 9); |
32895d361262
do not return an error, but warn and recover when encountering an audio packet
ivo
parents:
2897
diff
changeset
|
118 goto recover; |
2880 | 119 } |
120 | |
121 get_buffer(pb, pes_header_data, pes_header_data_length); | |
122 length -= 9 + pes_header_data_length; | |
123 | |
124 pes_packet_length -= 3 + pes_header_data_length; | |
125 | |
126 pvactx->continue_pes = pes_packet_length; | |
127 | |
128 if (pes_flags & 0x80 && (pes_header_data[0] & 0xf0) == 0x20) { | |
129 pva_pts = ((long long) *pes_header_data & 0x0e) << 29; | |
130 pva_pts += (AV_RB16(pes_header_data+1) >> 1) << 15; | |
131 pva_pts += AV_RB16(pes_header_data+3) >> 1; | |
132 } | |
133 } | |
134 | |
135 pvactx->continue_pes -= length; | |
136 | |
137 if (pvactx->continue_pes < 0) { | |
138 av_log(s, AV_LOG_WARNING, "audio data corruption\n"); | |
139 pvactx->continue_pes = 0; | |
140 } | |
141 } | |
142 | |
143 if ((ret = av_get_packet(pb, pkt, length)) <= 0) | |
144 return AVERROR(EIO); | |
145 | |
146 pkt->stream_index = streamid - 1; | |
2899 | 147 if (pva_pts != AV_NOPTS_VALUE) |
2880 | 148 pkt->pts = pva_pts; |
149 | |
150 return ret; | |
151 } | |
152 | |
153 AVInputFormat pva_demuxer = { | |
154 "pva", | |
155 "pva file and stream format", | |
156 sizeof(PVAContext), | |
157 pva_probe, | |
158 pva_read_header, | |
159 pva_read_packet, | |
160 }; |