FFmpeg
Loading...
Searching...
No Matches
ifv.c
Go to the documentation of this file.
1/*
2 * IFV demuxer
3 *
4 * Copyright (c) 2019 Swaraj Hota
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
24#include "avformat.h"
25#include "demux.h"
26#include "internal.h"
27#include "avio_internal.h"
28
42
43static int ifv_probe(const AVProbeData *p)
44{
45 static const uint8_t ifv_magic[] = {0x11, 0xd2, 0xd3, 0xab, 0xba, 0xa9,
46 0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65, 0x44};
47
48 if (!memcmp(p->buf, ifv_magic, sizeof(ifv_magic)))
49 return AVPROBE_SCORE_MAX;
50
51 return 0;
52}
53
56 uint32_t start_index)
57{
58 IFVContext *ifv = s->priv_data;
59 AVStream *st;
60 int64_t pos, size, timestamp;
61 uint32_t end_index, i;
62 int ret;
63
65 end_index = ifv->total_vframes;
66 st = s->streams[ifv->video_stream_index];
67 } else {
68 end_index = ifv->total_aframes;
69 st = s->streams[ifv->audio_stream_index];
70 }
71
72 for (i = start_index; i < end_index; i++) {
73 if (avio_feof(s->pb))
74 return AVERROR_EOF;
75 pos = avio_rl32(s->pb);
76 size = avio_rl32(s->pb);
77
78 avio_skip(s->pb, 8);
79 timestamp = avio_rl32(s->pb);
80
81 ret = av_add_index_entry(st, pos, timestamp, size, 0, 0);
82 if (ret < 0)
83 return ret;
84
86 }
87
88 return 0;
89}
90
92{
93 IFVContext *ifv = s->priv_data;
94 uint32_t aud_magic;
95 uint32_t vid_magic;
96
97 avio_skip(s->pb, 0x34);
98 ff_dict_set_timestamp(&s->metadata, "creation_time", avio_rl32(s->pb) * 1000000LL);
99 avio_skip(s->pb, 0x24);
100
101 ifv->width = avio_rl16(s->pb);
102 ifv->height = avio_rl16(s->pb);
103
104 avio_skip(s->pb, 0x8);
105 vid_magic = avio_rl32(s->pb);
106
107 if (vid_magic != MKTAG('H','2','6','4'))
108 avpriv_request_sample(s, "Unknown video codec %x", vid_magic);
109
110 avio_skip(s->pb, 0x2c);
111 ifv->sample_rate = avio_rl32(s->pb);
112 aud_magic = avio_rl32(s->pb);
113
114 if (aud_magic == MKTAG('G','R','A','W')) {
115 ifv->is_audio_present = 1;
116 } else if (aud_magic == MKTAG('P','C','M','U')) {
117 ifv->is_audio_present = 0;
118 } else {
119 avpriv_request_sample(s, "Unknown audio codec %x", aud_magic);
120 }
121
122 avio_skip(s->pb, 0x44);
123 ifv->total_vframes = avio_rl32(s->pb);
124 ifv->total_aframes = avio_rl32(s->pb);
125
126 return 0;
127}
128
130{
131 IFVContext *ifv = s->priv_data;
132 AVStream *st;
133 int ret;
134
135 ret = parse_header(s);
136 if (ret < 0)
137 return ret;
138
140 if (!st)
141 return AVERROR(ENOMEM);
142
145 st->codecpar->width = ifv->width;
146 st->codecpar->height = ifv->height;
147 st->start_time = 0;
148 ifv->video_stream_index = st->index;
149
150 avpriv_set_pts_info(st, 32, 1, 1000);
151
152 if (ifv->is_audio_present) {
154 if (!st)
155 return AVERROR(ENOMEM);
156
160 st->codecpar->sample_rate = ifv->sample_rate;
161 ifv->audio_stream_index = st->index;
162
163 avpriv_set_pts_info(st, 32, 1, 1000);
164 }
165
166 /*read video index*/
167 avio_seek(s->pb, 0xf8, SEEK_SET);
168
170 if (ret < 0)
171 return ret;
172
173 if (ifv->is_audio_present) {
174 /*read audio index*/
175 avio_seek(s->pb, 0x14918, SEEK_SET);
176
178 if (ret < 0)
179 return ret;
180 }
181
182 ifv->next_video_index = 0;
183 ifv->next_audio_index = 0;
184
185 return 0;
186}
187
189{
190 IFVContext *ifv = s->priv_data;
191 AVIndexEntry *ev, *ea, *e_next;
192 int ret;
193
194 ev = ea = e_next = NULL;
195
196 if (ifv->next_video_index < ifv->total_vframes) {
197 AVStream *const st = s->streams[ifv->video_stream_index];
198 FFStream *const sti = ffstream(st);
199
200 if (ifv->next_video_index < sti->nb_index_entries)
201 e_next = ev = &sti->index_entries[ifv->next_video_index];
202 }
203
204 if (ifv->is_audio_present &&
205 ifv->next_audio_index < ifv->total_aframes) {
206 AVStream *const st = s->streams[ifv->audio_stream_index];
207 FFStream *const sti = ffstream(st);
208
209 if (ifv->next_audio_index < sti->nb_index_entries) {
210 ea = &sti->index_entries[ifv->next_audio_index];
211 if (!ev || ea->timestamp < ev->timestamp)
212 e_next = ea;
213 }
214 }
215
216 if (!ev) {
217 uint64_t vframes, aframes;
218 if (ifv->is_audio_present && !ea) {
219 /*read new video and audio indexes*/
220
223
224 avio_skip(s->pb, 0x1c);
225 vframes = ifv->total_vframes + (uint64_t)avio_rl32(s->pb);
226 aframes = ifv->total_aframes + (uint64_t)avio_rl32(s->pb);
227 if (vframes > INT_MAX || aframes > INT_MAX)
228 return AVERROR_INVALIDDATA;
229 ifv->total_vframes = vframes;
230 ifv->total_aframes = aframes;
231 avio_skip(s->pb, 0xc);
232
233 if (avio_feof(s->pb))
234 return AVERROR_EOF;
235
237 if (ret < 0)
238 return ret;
239
241 if (ret < 0)
242 return ret;
243
244 return 0;
245
246 } else if (!ifv->is_audio_present) {
247 /*read new video index*/
248
250
251 avio_skip(s->pb, 0x1c);
252 vframes = ifv->total_vframes + (uint64_t)avio_rl32(s->pb);
253 if (vframes > INT_MAX)
254 return AVERROR_INVALIDDATA;
255 ifv->total_vframes = vframes;
256 avio_skip(s->pb, 0x10);
257
258 if (avio_feof(s->pb))
259 return AVERROR_EOF;
260
262 if (ret < 0)
263 return ret;
264
265 return 0;
266 }
267 }
268
269 if (!e_next) return AVERROR_EOF;
270
271 avio_seek(s->pb, e_next->pos, SEEK_SET);
272 ret = av_get_packet(s->pb, pkt, e_next->size);
273 if (ret < 0)
274 return ret;
275
276 if (e_next == ev) {
277 ifv->next_video_index++;
278 pkt->stream_index = ifv->video_stream_index;
279 } else {
280 ifv->next_audio_index++;
281 pkt->stream_index = ifv->audio_stream_index;
282 }
283
284 pkt->pts = e_next->timestamp;
285 pkt->pos = e_next->pos;
286
287 return 0;
288}
289
290static int ifv_read_seek(AVFormatContext *s, int stream_index, int64_t ts, int flags)
291{
292 IFVContext *ifv = s->priv_data;
293
294 for (unsigned i = 0; i < s->nb_streams; i++) {
295 int index = av_index_search_timestamp(s->streams[i], ts, AVSEEK_FLAG_ANY);
296 if (index < 0) {
297 ifv->next_video_index = ifv->total_vframes - 1;
298 ifv->next_audio_index = ifv->total_aframes - 1;
299 return 0;
300 }
301
302 if (i == ifv->video_stream_index) {
303 ifv->next_video_index = index;
304 } else {
305 ifv->next_audio_index = index;
306 }
307 }
308
309 return 0;
310}
311
313 .p.name = "ifv",
314 .p.long_name = NULL_IF_CONFIG_SMALL("IFV CCTV DVR"),
315 .p.extensions = "ifv",
316 .priv_data_size = sizeof(IFVContext),
321};
const FFInputFormat ff_ifv_demuxer
Definition ifv.c:312
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:834
Main libavformat public API header.
#define AVPROBE_SCORE_MAX
maximum score
Definition avformat.h:483
#define AVSEEK_FLAG_ANY
seek to any frame, even non-keyframes
Definition avformat.h:2618
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.
Definition utils.c:98
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
unsigned int avio_rl16(AVIOContext *s)
Definition aviobuf.c:717
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition aviobuf.c:321
unsigned int avio_rl32(AVIOContext *s)
Definition aviobuf.c:733
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
static int read_probe(const AVProbeData *p)
Definition cdg.c:30
Public libavutil channel layout APIs header.
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVPacket * pkt
static int read_header(FFV1Context *f, RangeCoder *c)
Definition ffv1dec.c:578
@ AV_CODEC_ID_PCM_S16LE
Definition codec_id.h:330
@ AV_CODEC_ID_H264
Definition codec_id.h:77
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
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.
Definition seek.c:122
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags)
Get the index for a specific timestamp.
Definition seek.c:245
#define AV_CHANNEL_LAYOUT_MONO
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
AVMediaType
Definition avutil.h:198
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int index
Definition gxfenc.c:90
static int read_index(AVFormatContext *s, enum AVMediaType frame_type, uint32_t start_index)
Definition ifv.c:54
static int parse_header(AVFormatContext *s)
Definition ifv.c:91
static int ifv_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition ifv.c:188
static int ifv_probe(const AVProbeData *p)
Definition ifv.c:43
static int ifv_read_header(AVFormatContext *s)
Definition ifv.c:129
static int ifv_read_seek(AVFormatContext *s, int stream_index, int64_t ts, int flags)
Definition ifv.c:290
frame_type
int ff_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
Set a dictionary value to an ISO-8601 compliant timestamp string.
Definition utils.c:616
static av_always_inline FFStream * ffstream(AVStream *st)
Definition internal.h:365
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition libcdio.c:151
#define MKTAG(a, b, c, d)
Definition macros.h:55
unsigned int pos
Definition spdifenc.c:431
An AVChannelLayout holds information about the channel layout of audio data.
int height
The height of the video frame in pixels.
Definition codec_par.h:150
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
int width
The width of the video frame in pixels.
Definition codec_par.h:143
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
Format I/O context.
Definition avformat.h:1333
int64_t pos
Definition avformat.h:621
int64_t timestamp
Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are...
Definition avformat.h:622
This structure stores compressed data.
Definition packet.h:580
This structure contains the data a format has to probe a file.
Definition avformat.h:471
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
int index
stream index in AVFormatContext
Definition avformat.h:772
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base.
Definition avformat.h:815
int nb_index_entries
Definition internal.h:193
AVIndexEntry * index_entries
Only used if the format does not support seeking natively.
Definition internal.h:191
int video_stream_index
Definition ifv.c:39
int audio_stream_index
Definition ifv.c:40
int height
Definition ifv.c:35
uint32_t next_video_index
Definition ifv.c:30
int width
Definition ifv.c:35
uint32_t next_audio_index
Definition ifv.c:31
uint32_t total_aframes
Definition ifv.c:33
int sample_rate
Definition ifv.c:37
int is_audio_present
Definition ifv.c:36
uint32_t total_vframes
Definition ifv.c:32
#define avpriv_request_sample(...)
int size