1 /*
2 * Magic Lantern Video (MLV) demuxer
3 * Copyright (c) 2014 Peter Ross
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 /**
23 * @file
24 * Magic Lantern Video (MLV) demuxer
25 */
26
35
36 #define MLV_VERSION "v2.0"
37
38 #define MLV_VIDEO_CLASS_RAW 1
39 #define MLV_VIDEO_CLASS_YUV 2
40 #define MLV_VIDEO_CLASS_JPEG 3
41 #define MLV_VIDEO_CLASS_H264 4
42
43 #define MLV_AUDIO_CLASS_WAV 1
44
45 #define MLV_CLASS_FLAG_DELTA 0x40
46 #define MLV_CLASS_FLAG_LZMA 0x80
47
54
56 {
61 return 0;
62 }
63
65 {
68
71 if (size < 52)
77 return 0;
78 }
79
81 {
83 if (!value) {
85 return;
86 }
87
89 if (!value[0]) {
91 return;
92 }
93
96 }
97
99 {
101 }
102
104 {
106 }
107
109 {
111 }
112
114 {
116 }
117
119 {
122 int ret;
129 if (size < 16)
130 break;
131 size -= 16;
132 if (vst && type ==
MKTAG(
'R',
'A',
'W',
'I') && size >= 164) {
136 if (ret < 0)
137 return ret;
140 avio_skip(pb, 20);
// pointer, width, height, pitch, frame_size
145 "invalid bits_per_coded_sample %d (size: %dx%d)\n",
149 }
150 avio_skip(pb, 8 + 16 + 24);
// black_level, white_level, xywh, active_area, exposure_bias
151 if (
avio_rl32(pb) != 0x2010100)
/* RGGB */
153 avio_skip(pb, 80);
// calibration_illuminant1, color_matrix1, dynamic_range
156 size -= 164;
157 }
else if (ast && type ==
MKTAG(
'W',
'A',
'V',
'I') && size >= 16) {
159 if (ret < 0)
160 return ret;
161 size -= 16;
162 }
else if (type ==
MKTAG(
'I',
'N',
'F',
'O')) {
163 if (size > 0)
165 continue;
166 }
else if (type ==
MKTAG(
'I',
'D',
'N',
'T') && size >= 36) {
168 read_uint32(avctx, pb,
"cameraModel",
"0x%"PRIx32);
169 size -= 36;
170 if (size >= 32) {
172 size -= 32;
173 }
174 }
else if (type ==
MKTAG(
'L',
'E',
'N',
'S') && size >= 48) {
178 read_uint8(avctx, pb,
"stabilizerMode",
"%i");
183 size -= 48;
184 if (size >= 32) {
186 size -= 32;
187 }
188 }
else if (vst && type ==
MKTAG(
'V',
'I',
'D',
'F') && size >= 4) {
192 size -= 4;
193 }
else if (ast && type ==
MKTAG(
'A',
'U',
'D',
'F') && size >= 4) {
197 size -= 4;
198 }
else if (vst && type ==
MKTAG(
'W',
'B',
'A',
'L') && size >= 28) {
206 size -= 28;
207 }
else if (type ==
MKTAG(
'R',
'T',
'C',
'I') && size >= 20) {
208 char str[32];
209 struct tm time = { 0 };
220 if (strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &time))
222 size -= 20;
223 }
else if (type ==
MKTAG(
'E',
'X',
'P',
'O') && size >= 16) {
228 size -= 16;
229 if (size >= 8) {
231 size -= 8;
232 }
233 }
else if (type ==
MKTAG(
'S',
'T',
'Y',
'L') && size >= 36) {
240 size -= 36;
241 }
else if (type ==
MKTAG(
'M',
'A',
'R',
'K')) {
242 }
else if (type ==
MKTAG(
'N',
'U',
'L',
'L')) {
243 }
else if (type ==
MKTAG(
'M',
'L',
'V',
'I')) {
/* occurs when MLV and Mnn files are concatenated */
244 } else {
247 }
249 }
250 return 0;
251 }
252
254 {
259 unsigned nb_video_frames, nb_audio_frames;
260 uint64_t guid;
261 char guidstr[32];
262
265 if (size < 52)
267
269
271 snprintf(guidstr,
sizeof(guidstr),
"0x%"PRIx64, guid);
273
274 avio_skip(pb, 8);
//fileNum, fileCount, fileFlags
275
278
281
282 if (nb_video_frames && mlv->
class[0]) {
284 if (!vst)
294 break;
299 break;
303 break;
307 break;
308 default:
310 }
311 }
312
313 if (nb_audio_frames && mlv->
class[1]) {
315 if (!ast)
317 ast->id = 1;
318 ast->nb_frames = nb_audio_frames;
323
326 }
327
328 if (vst) {
333 } else
335
337
338 /* scan primary file */
339 mlv->
pb[100] = avctx->
pb;
341 if (ret < 0)
342 return ret;
343
344 /* scan secondary files */
345 if (strlen(avctx->
url) > 2) {
346 int i;
348
349 if (!filename)
351
352 for (i = 0; i < 100; i++) {
353 snprintf(filename + strlen(filename) - 2, 3,
"%02d", i);
355 break;
359 continue;
360 }
363 if (ret < 0) {
366 continue;
367 }
368 }
370 }
371
372 if (vst)
374 if (ast)
375 ast->duration = ast->nb_index_entries;
376
380 }
381
382 if (vst && ast)
384 else if (vst)
386 else if (ast)
388
389 return 0;
390 }
391
393 {
398 unsigned int size, space;
399
402
404 if (index < 0) {
407 }
408
411
414 if (size < 16)
416 avio_skip(pb, 12);
//timestamp, frameNumber
418 avio_skip(pb, 8);
// cropPosX, cropPosY, panPosX, panPosY
421
426 } else { // AVMEDIA_TYPE_AUDIO
427 if (space > UINT_MAX - 24 || size < (24 + space))
430 }
431
432 if (ret < 0)
433 return ret;
434
437
442 }
443 return 0;
444 }
445
447 {
449
452
455
456 mlv->
pts = timestamp;
457 return 0;
458 }
459
461 {
463 int i;
464 for (i = 0; i < 100; i++)
467 return 0;
468 }
469
479 };
static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int file)
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
static int check_file_header(AVIOContext *pb, uint64_t guid)
#define AV_LOG_WARNING
Something somehow does not look correct.
#define MLV_CLASS_FLAG_LZMA
static int read_close(AVFormatContext *s)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
#define AVIO_FLAG_READ
read-only
AVIndexEntry * index_entries
Only used if the format does not support seeking natively.
static int read_packet(AVFormatContext *avctx, AVPacket *pkt)
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
#define MLV_CLASS_FLAG_DELTA
void void avpriv_request_sample(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
int id
Format-specific stream ID.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
AVStream ** streams
A list of all streams in the file.
#define MLV_VIDEO_CLASS_RAW
#define AVERROR_EOF
End of file.
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int size, int big_endian)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
AVDictionary * metadata
Metadata that applies to the whole file.
int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags)
Get the index for a specific timestamp.
unsigned int avio_rl32(AVIOContext *s)
#define MLV_VIDEO_CLASS_H264
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
char * url
input or output URL.
#define av_fourcc2str(fourcc)
enum AVMediaType codec_type
General type of the encoded data.
int avio_r8(AVIOContext *s)
static int read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
#define MLV_VIDEO_CLASS_YUV
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
AVInputFormat ff_mlv_demuxer
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
GLsizei GLboolean const GLfloat * value
static void read_string(AVFormatContext *avctx, AVIOContext *pb, const char *tag, int size)
internal header for RIFF based (de)muxers do NOT include this in end user applications ...
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AVIO_SEEKABLE_NORMAL
Seeking works like for a local file.
#define AV_LOG_INFO
Standard information.
char * av_strdup(const char *s)
Duplicate a string.
AVIOContext * pb
I/O context.
static int probe(AVProbeData *p)
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
static void read_uint32(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
Rational number (pair of numerator and denominator).
static int read_header(AVFormatContext *avctx)
This structure contains the data a format has to probe a file.
static void read_uint64(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */
int64_t duration
Decoding: duration of the stream, in stream time base.
unsigned int avio_rl16(AVIOContext *s)
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Utilties for rational number calculation.
#define MLV_VIDEO_CLASS_JPEG
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set that converts the value to a string and stores it...
int64_t pos
position in the file of the current buffer
int64_t nb_frames
number of frames in this stream if known or 0
unsigned int index_entries_allocated_size
#define MLV_AUDIO_CLASS_WAV
void * priv_data
Format private data.
static void read_uint8(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
int bits_per_coded_sample
The number of bits per sample in the codedwords.
AVCodecParameters * codecpar
Codec parameters associated with this stream.
int avio_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
#define MKTAG(a, b, c, d)
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
This structure stores compressed data.
uint64_t avio_rl64(AVIOContext *s)
static void read_uint16(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
simple arithmetic expression evaluator