pva.c
Go to the documentation of this file.
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 #include "internal.h"
24 #include "mpeg.h"
25 
26 #define PVA_MAX_PAYLOAD_LENGTH 0x17f8
27 #define PVA_VIDEO_PAYLOAD 0x01
28 #define PVA_AUDIO_PAYLOAD 0x02
29 #define PVA_MAGIC (('A' << 8) + 'V')
30 
31 typedef struct {
33 } PVAContext;
34 
35 static int pva_check(const uint8_t *p) {
36  int length = AV_RB16(p + 6);
37  if (AV_RB16(p) != PVA_MAGIC || !p[2] || p[2] > 2 || p[4] != 0x55 ||
38  (p[5] & 0xe0) || length > PVA_MAX_PAYLOAD_LENGTH)
39  return -1;
40  return length + 8;
41 }
42 
43 static int pva_probe(AVProbeData * pd) {
44  const unsigned char *buf = pd->buf;
45  int len = pva_check(buf);
46 
47  if (len < 0)
48  return 0;
49 
50  if (pd->buf_size >= len + 8 &&
51  pva_check(buf + len) >= 0)
52  return AVPROBE_SCORE_MAX / 2;
53 
54  return AVPROBE_SCORE_MAX / 4;
55 }
56 
58  AVStream *st;
59 
60  if (!(st = avformat_new_stream(s, NULL)))
61  return AVERROR(ENOMEM);
65  avpriv_set_pts_info(st, 32, 1, 90000);
66  av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME);
67 
68  if (!(st = avformat_new_stream(s, NULL)))
69  return AVERROR(ENOMEM);
73  avpriv_set_pts_info(st, 33, 1, 90000);
74  av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME);
75 
76  /* the parameters will be extracted from the compressed bitstream */
77  return 0;
78 }
79 
80 #define pva_log if (read_packet) av_log
81 
82 static int read_part_of_packet(AVFormatContext *s, int64_t *pts,
83  int *len, int *strid, int read_packet) {
84  AVIOContext *pb = s->pb;
85  PVAContext *pvactx = s->priv_data;
86  int syncword, streamid, reserved, flags, length, pts_flag;
87  int64_t pva_pts = AV_NOPTS_VALUE, startpos;
88 
89 recover:
90  startpos = avio_tell(pb);
91 
92  syncword = avio_rb16(pb);
93  streamid = avio_r8(pb);
94  avio_r8(pb); /* counter not used */
95  reserved = avio_r8(pb);
96  flags = avio_r8(pb);
97  length = avio_rb16(pb);
98 
99  pts_flag = flags & 0x10;
100 
101  if (syncword != PVA_MAGIC) {
102  pva_log(s, AV_LOG_ERROR, "invalid syncword\n");
103  return AVERROR(EIO);
104  }
105  if (streamid != PVA_VIDEO_PAYLOAD && streamid != PVA_AUDIO_PAYLOAD) {
106  pva_log(s, AV_LOG_ERROR, "invalid streamid\n");
107  return AVERROR(EIO);
108  }
109  if (reserved != 0x55) {
110  pva_log(s, AV_LOG_WARNING, "expected reserved byte to be 0x55\n");
111  }
112  if (length > PVA_MAX_PAYLOAD_LENGTH) {
113  pva_log(s, AV_LOG_ERROR, "invalid payload length %u\n", length);
114  return AVERROR(EIO);
115  }
116 
117  if (streamid == PVA_VIDEO_PAYLOAD && pts_flag) {
118  pva_pts = avio_rb32(pb);
119  length -= 4;
120  } else if (streamid == PVA_AUDIO_PAYLOAD) {
121  /* PVA Audio Packets either start with a signaled PES packet or
122  * are a continuation of the previous PES packet. New PES packets
123  * always start at the beginning of a PVA Packet, never somewhere in
124  * the middle. */
125  if (!pvactx->continue_pes) {
126  int pes_signal, pes_header_data_length, pes_packet_length,
127  pes_flags;
128  unsigned char pes_header_data[256];
129 
130  pes_signal = avio_rb24(pb);
131  avio_r8(pb);
132  pes_packet_length = avio_rb16(pb);
133  pes_flags = avio_rb16(pb);
134  pes_header_data_length = avio_r8(pb);
135 
136  if (pes_signal != 1) {
137  pva_log(s, AV_LOG_WARNING, "expected signaled PES packet, "
138  "trying to recover\n");
139  avio_skip(pb, length - 9);
140  if (!read_packet)
141  return AVERROR(EIO);
142  goto recover;
143  }
144 
145  avio_read(pb, pes_header_data, pes_header_data_length);
146  length -= 9 + pes_header_data_length;
147 
148  pes_packet_length -= 3 + pes_header_data_length;
149 
150  pvactx->continue_pes = pes_packet_length;
151 
152  if (pes_flags & 0x80 && (pes_header_data[0] & 0xf0) == 0x20)
153  pva_pts = ff_parse_pes_pts(pes_header_data);
154  }
155 
156  pvactx->continue_pes -= length;
157 
158  if (pvactx->continue_pes < 0) {
159  pva_log(s, AV_LOG_WARNING, "audio data corruption\n");
160  pvactx->continue_pes = 0;
161  }
162  }
163 
164  if (pva_pts != AV_NOPTS_VALUE)
165  av_add_index_entry(s->streams[streamid-1], startpos, pva_pts, 0, 0, AVINDEX_KEYFRAME);
166 
167  *pts = pva_pts;
168  *len = length;
169  *strid = streamid;
170  return 0;
171 }
172 
174  AVIOContext *pb = s->pb;
175  int64_t pva_pts;
176  int ret, length, streamid;
177 
178  if (read_part_of_packet(s, &pva_pts, &length, &streamid, 1) < 0 ||
179  (ret = av_get_packet(pb, pkt, length)) <= 0)
180  return AVERROR(EIO);
181 
182  pkt->stream_index = streamid - 1;
183  pkt->pts = pva_pts;
184 
185  return ret;
186 }
187 
188 static int64_t pva_read_timestamp(struct AVFormatContext *s, int stream_index,
189  int64_t *pos, int64_t pos_limit) {
190  AVIOContext *pb = s->pb;
191  PVAContext *pvactx = s->priv_data;
192  int length, streamid;
193  int64_t res = AV_NOPTS_VALUE;
194 
195  pos_limit = FFMIN(*pos+PVA_MAX_PAYLOAD_LENGTH*8, (uint64_t)*pos+pos_limit);
196 
197  while (*pos < pos_limit) {
198  res = AV_NOPTS_VALUE;
199  avio_seek(pb, *pos, SEEK_SET);
200 
201  pvactx->continue_pes = 0;
202  if (read_part_of_packet(s, &res, &length, &streamid, 0)) {
203  (*pos)++;
204  continue;
205  }
206  if (streamid - 1 != stream_index || res == AV_NOPTS_VALUE) {
207  *pos = avio_tell(pb) + length;
208  continue;
209  }
210  break;
211  }
212 
213  pvactx->continue_pes = 0;
214  return res;
215 }
216 
218  .name = "pva",
219  .long_name = NULL_IF_CONFIG_SMALL("TechnoTrend PVA"),
220  .priv_data_size = sizeof(PVAContext),
224  .read_timestamp = pva_read_timestamp,
225 };
static int pva_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: pva.c:173
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
int av_add_index_entry(AVStream *st, int64_t pos, int64_t timestamp, int size, int distance, int flags)
Add an index entry into a sorted list.
#define PVA_MAGIC
Definition: pva.c:29
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
static int pva_read_header(AVFormatContext *s)
Definition: pva.c:57
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
int continue_pes
Definition: pva.c:32
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:256
unsigned int avio_rb16(AVIOContext *s)
Definition: aviobuf.c:595
Format I/O context.
Definition: avformat.h:944
#define PVA_VIDEO_PAYLOAD
Definition: pva.c:27
static int read_part_of_packet(AVFormatContext *s, int64_t *pts, int *len, int *strid, int read_packet)
Definition: pva.c:82
uint8_t
unsigned int avio_rb32(AVIOContext *s)
Definition: aviobuf.c:610
static AVPacket pkt
Definition: demuxing.c:56
enum AVStreamParseType need_parsing
Definition: avformat.h:811
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
AVStream ** streams
Definition: avformat.h:992
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
#define AVINDEX_KEYFRAME
Definition: avformat.h:599
#define AV_RB16
static int pva_check(const uint8_t *p)
Definition: pva.c:35
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: pva.c:31
static int64_t ff_parse_pes_pts(const uint8_t *buf)
Parse MPEG-PES five-byte timestamp.
Definition: mpeg.h:67
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:337
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
#define PVA_AUDIO_PAYLOAD
Definition: pva.c:28
unsigned int avio_rb24(AVIOContext *s)
Definition: aviobuf.c:603
static int64_t pva_read_timestamp(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit)
Definition: pva.c:188
#define FFMIN(a, b)
Definition: common.h:58
static int read_probe(AVProbeData *pd)
AVInputFormat ff_pva_demuxer
Definition: pva.c:217
ret
Definition: avfilter.c:821
preferred ID for MPEG-1/2 video decoding
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:517
#define PVA_MAX_PAYLOAD_LENGTH
Definition: pva.c:26
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
enum AVMediaType codec_type
enum AVCodecID codec_id
AVIOContext * pb
I/O context.
Definition: avformat.h:977
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
Definition: libcdio.c:114
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
full parsing and repack
Definition: avformat.h:582
Main libavformat public API header.
#define pva_log
Definition: pva.c:80
static int pva_probe(AVProbeData *pd)
Definition: pva.c:43
int len
void * priv_data
Format private data.
Definition: avformat.h:964
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
const char int length
Definition: avisynth_c.h:668
This structure stores compressed data.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190