FFmpeg  4.2.1
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 
23 #include "avformat.h"
24 #include "internal.h"
25 #include "avio_internal.h"
26 
27 typedef struct IFVContext {
28  uint32_t next_video_index;
29  uint32_t next_audio_index;
30  uint32_t total_vframes;
31  uint32_t total_aframes;
32 
33  int width, height;
36 
39 } IFVContext;
40 
41 static int ifv_probe(const AVProbeData *p)
42 {
43  static const uint8_t ifv_magic[] = {0x11, 0xd2, 0xd3, 0xab, 0xba, 0xa9,
44  0xcf, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65, 0x44};
45 
46  if (!memcmp(p->buf, ifv_magic, sizeof(ifv_magic)))
47  return AVPROBE_SCORE_MAX;
48 
49  return 0;
50 }
51 
53  enum AVMediaType frame_type,
54  uint32_t start_index)
55 {
56  IFVContext *ifv = s->priv_data;
57  AVStream *st;
58  int64_t pos, size, timestamp;
59  uint32_t end_index, i;
60  int ret;
61 
62  if (frame_type == AVMEDIA_TYPE_VIDEO) {
63  end_index = ifv->total_vframes;
64  st = s->streams[ifv->video_stream_index];
65  } else {
66  end_index = ifv->total_aframes;
67  st = s->streams[ifv->audio_stream_index];
68  }
69 
70  for (i = start_index; i < end_index; i++) {
71  if (avio_feof(s->pb))
72  return AVERROR_EOF;
73  pos = avio_rl32(s->pb);
74  size = avio_rl32(s->pb);
75 
76  avio_skip(s->pb, 8);
77  timestamp = avio_rl32(s->pb);
78 
79  ret = av_add_index_entry(st, pos, timestamp, size, 0, 0);
80  if (ret < 0)
81  return ret;
82 
83  avio_skip(s->pb, frame_type == AVMEDIA_TYPE_VIDEO ? 8: 4);
84  }
85 
86  return 0;
87 }
88 
90 {
91  IFVContext *ifv = s->priv_data;
92  uint32_t aud_magic;
93  uint32_t vid_magic;
94 
95  avio_skip(s->pb, 0x34);
96  avpriv_dict_set_timestamp(&s->metadata, "creation_time", avio_rl32(s->pb) * 1000000LL);
97  avio_skip(s->pb, 0x24);
98 
99  ifv->width = avio_rl16(s->pb);
100  ifv->height = avio_rl16(s->pb);
101 
102  avio_skip(s->pb, 0x8);
103  vid_magic = avio_rl32(s->pb);
104 
105  if (vid_magic != MKTAG('H','2','6','4'))
106  avpriv_request_sample(s, "Unknown video codec %x", vid_magic);
107 
108  avio_skip(s->pb, 0x2c);
109  ifv->sample_rate = avio_rl32(s->pb);
110  aud_magic = avio_rl32(s->pb);
111 
112  if (aud_magic == MKTAG('G','R','A','W')) {
113  ifv->is_audio_present = 1;
114  } else if (aud_magic == MKTAG('P','C','M','U')) {
115  ifv->is_audio_present = 0;
116  } else {
117  avpriv_request_sample(s, "Unknown audio codec %x", aud_magic);
118  }
119 
120  avio_skip(s->pb, 0x44);
121  ifv->total_vframes = avio_rl32(s->pb);
122  ifv->total_aframes = avio_rl32(s->pb);
123 
124  return 0;
125 }
126 
128 {
129  IFVContext *ifv = s->priv_data;
130  AVStream *st;
131  int ret;
132 
133  ret = parse_header(s);
134  if (ret < 0)
135  return ret;
136 
137  st = avformat_new_stream(s, NULL);
138  if (!st)
139  return AVERROR(ENOMEM);
140 
143  st->codecpar->width = ifv->width;
144  st->codecpar->height = ifv->height;
145  st->start_time = 0;
146  ifv->video_stream_index = st->index;
147 
148  avpriv_set_pts_info(st, 32, 1, 1000);
149 
150  if (ifv->is_audio_present) {
151  st = avformat_new_stream(s, NULL);
152  if (!st)
153  return AVERROR(ENOMEM);
154 
157  st->codecpar->channels = 1;
159  st->codecpar->sample_rate = ifv->sample_rate;
160  ifv->audio_stream_index = st->index;
161 
162  avpriv_set_pts_info(st, 32, 1, 1000);
163  }
164 
165  /*read video index*/
166  avio_seek(s->pb, 0xf8, SEEK_SET);
167 
168  ret = read_index(s, AVMEDIA_TYPE_VIDEO, 0);
169  if (ret < 0)
170  return ret;
171 
172  if (ifv->is_audio_present) {
173  /*read audio index*/
174  avio_seek(s->pb, 0x14918, SEEK_SET);
175 
176  ret = read_index(s, AVMEDIA_TYPE_AUDIO, 0);
177  if (ret < 0)
178  return ret;
179  }
180 
181  ifv->next_video_index = 0;
182  ifv->next_audio_index = 0;
183 
184  return 0;
185 }
186 
188 {
189  IFVContext *ifv = s->priv_data;
190  AVStream *st;
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  st = s->streams[ifv->video_stream_index];
198  if (ifv->next_video_index < st->nb_index_entries)
199  e_next = ev = &st->index_entries[ifv->next_video_index];
200  }
201 
202  if (ifv->is_audio_present &&
203  ifv->next_audio_index < ifv->total_aframes) {
204  st = s->streams[ifv->audio_stream_index];
205  if (ifv->next_audio_index < st->nb_index_entries) {
206  ea = &st->index_entries[ifv->next_audio_index];
207  if (!ev || ea->timestamp < ev->timestamp)
208  e_next = ea;
209  }
210  }
211 
212  if (!ev) {
213  if (ifv->is_audio_present && !ea) {
214  /*read new video and audio indexes*/
215 
216  ifv->next_video_index = ifv->total_vframes;
217  ifv->next_audio_index = ifv->total_aframes;
218 
219  avio_skip(s->pb, 0x1c);
220  ifv->total_vframes += avio_rl32(s->pb);
221  ifv->total_aframes += avio_rl32(s->pb);
222  avio_skip(s->pb, 0xc);
223 
224  if (avio_feof(s->pb))
225  return AVERROR_EOF;
226 
228  if (ret < 0)
229  return ret;
230 
232  if (ret < 0)
233  return ret;
234 
235  return 0;
236 
237  } else if (!ifv->is_audio_present) {
238  /*read new video index*/
239 
240  ifv->next_video_index = ifv->total_vframes;
241 
242  avio_skip(s->pb, 0x1c);
243  ifv->total_vframes += avio_rl32(s->pb);
244  avio_skip(s->pb, 0x10);
245 
246  if (avio_feof(s->pb))
247  return AVERROR_EOF;
248 
250  if (ret < 0)
251  return ret;
252 
253  return 0;
254  }
255  }
256 
257  if (!e_next) return AVERROR_EOF;
258 
259  avio_seek(s->pb, e_next->pos, SEEK_SET);
260  ret = av_get_packet(s->pb, pkt, e_next->size);
261  if (ret < 0)
262  return ret;
263 
264  if (e_next == ev) {
265  ifv->next_video_index++;
266  pkt->stream_index = ifv->video_stream_index;
267  } else {
268  ifv->next_audio_index++;
269  pkt->stream_index = ifv->audio_stream_index;
270  }
271 
272  pkt->pts = e_next->timestamp;
273  pkt->pos = e_next->pos;
274 
275  return 0;
276 }
277 
278 static int ifv_read_seek(AVFormatContext *s, int stream_index, int64_t ts, int flags)
279 {
280  IFVContext *ifv = s->priv_data;
281 
282  for (unsigned i = 0; i < s->nb_streams; i++) {
284  if (index < 0) {
285  ifv->next_video_index = ifv->total_vframes - 1;
286  ifv->next_audio_index = ifv->total_aframes - 1;
287  return 0;
288  }
289 
290  if (i == ifv->video_stream_index) {
291  ifv->next_video_index = index;
292  } else {
293  ifv->next_audio_index = index;
294  }
295  }
296 
297  return 0;
298 }
299 
301  .name = "ifv",
302  .long_name = NULL_IF_CONFIG_SMALL("IFV CCTV DVR"),
303  .priv_data_size = sizeof(IFVContext),
304  .extensions = "ifv",
309 };
#define NULL
Definition: coverity.c:32
int size
static int ifv_read_header(AVFormatContext *s)
Definition: ifv.c:127
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: utils.c:2039
int64_t pos
byte position in stream, -1 if unknown
Definition: avcodec.h:1497
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.
Definition: utils.c:4886
int64_t pos
Definition: avformat.h:810
#define AVSEEK_FLAG_ANY
seek to any frame, even non-keyframes
Definition: avformat.h:2513
#define avpriv_request_sample(...)
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition: libcdio.c:153
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3957
int index
stream index in AVFormatContext
Definition: avformat.h:882
uint32_t total_vframes
Definition: ifv.c:30
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
AVIndexEntry * index_entries
Only used if the format does not support seeking natively.
Definition: avformat.h:1110
uint32_t next_audio_index
Definition: ifv.c:29
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:331
int audio_stream_index
Definition: ifv.c:38
AVInputFormat ff_ifv_demuxer
Definition: ifv.c:300
static AVPacket pkt
static int ifv_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: ifv.c:187
int is_audio_present
Definition: ifv.c:34
int height
Definition: ifv.c:33
Format I/O context.
Definition: avformat.h:1358
int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
Set a dictionary value to an ISO-8601 compliant timestamp string.
Definition: dict.c:258
uint8_t
int width
Video only.
Definition: avcodec.h:4023
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4459
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
#define AVERROR_EOF
End of file.
Definition: error.h:55
int video_stream_index
Definition: ifv.c:37
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:310
uint64_t channel_layout
Audio only.
Definition: avcodec.h:4059
uint32_t total_aframes
Definition: ifv.c:31
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1598
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags)
Get the index for a specific timestamp.
Definition: utils.c:2148
static int ifv_probe(const AVProbeData *p)
Definition: ifv.c:41
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:769
#define AVERROR(e)
Definition: error.h:43
int64_t timestamp
Timestamp in AVStream.time_base units, preferably the time from which on correctly decoded frames are...
Definition: avformat.h:811
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3953
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:448
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
uint32_t next_video_index
Definition: ifv.c:28
#define s(width, name)
Definition: cbs_vp9.c:257
static int parse_header(AVFormatContext *s)
Definition: ifv.c:89
Definition: ifv.c:27
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:530
Stream structure.
Definition: avformat.h:881
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
static int ifv_read_seek(AVFormatContext *s, int stream_index, int64_t ts, int flags)
Definition: ifv.c:278
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
int sample_rate
Definition: ifv.c:35
static int read_index(AVFormatContext *s, enum AVMediaType frame_type, uint32_t start_index)
Definition: ifv.c:52
int nb_index_entries
Definition: avformat.h:1112
int index
Definition: gxfenc.c:89
AVMediaType
Definition: avutil.h:199
This structure contains the data a format has to probe a file.
Definition: avformat.h:446
#define flags(name, subs,...)
Definition: cbs_av1.c:561
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
int sample_rate
Audio only.
Definition: avcodec.h:4067
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:458
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:753
Main libavformat public API header.
int width
Definition: ifv.c:33
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:920
void * priv_data
Format private data.
Definition: avformat.h:1386
int channels
Audio only.
Definition: avcodec.h:4063
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:654
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:358
int stream_index
Definition: avcodec.h:1479
#define AV_CH_LAYOUT_MONO
#define MKTAG(a, b, c, d)
Definition: common.h:366
This structure stores compressed data.
Definition: avcodec.h:1454
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1470