Coverage Report

Created: 2026-02-14 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/mlvdec.c
Line
Count
Source
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
27
#include <time.h>
28
29
#include "libavcodec/bytestream.h"
30
#include "libavcodec/tiff.h"
31
#include "libavcodec/tiff_common.h"
32
#include "libavutil/imgutils.h"
33
#include "libavutil/intreadwrite.h"
34
#include "libavutil/mem.h"
35
#include "libavutil/rational.h"
36
#include "avformat.h"
37
#include "demux.h"
38
#include "internal.h"
39
#include "riff.h"
40
41
307
#define MLV_VERSION "v2.0"
42
43
572
#define MLV_VIDEO_CLASS_RAW  1
44
184
#define MLV_VIDEO_CLASS_YUV  2
45
231
#define MLV_VIDEO_CLASS_JPEG 3
46
258
#define MLV_VIDEO_CLASS_H264 4
47
48
3.40k
#define MLV_AUDIO_CLASS_WAV  1
49
50
318
#define MLV_CLASS_FLAG_LJ92  0x20
51
44.4k
#define MLV_CLASS_FLAG_DELTA 0x40
52
51.2k
#define MLV_CLASS_FLAG_LZMA  0x80
53
54
typedef struct {
55
    AVIOContext *pb[101];
56
    int class[2];
57
    int stream_index;
58
    uint64_t pts;
59
    int black_level;
60
    int white_level;
61
    int color_matrix1[9][2];
62
} MlvContext;
63
64
static int probe(const AVProbeData *p)
65
936k
{
66
936k
    if (AV_RL32(p->buf) == MKTAG('M','L','V','I') &&
67
478
        AV_RL32(p->buf + 4) >= 52 &&
68
307
        !memcmp(p->buf + 8, MLV_VERSION, 5))
69
106
        return AVPROBE_SCORE_MAX;
70
936k
    return 0;
71
936k
}
72
73
static int check_file_header(AVIOContext *pb, uint64_t guid)
74
0
{
75
0
    unsigned int size;
76
0
    uint8_t version[8];
77
78
0
    avio_skip(pb, 4);
79
0
    size = avio_rl32(pb);
80
0
    if (size < 52)
81
0
        return AVERROR_INVALIDDATA;
82
0
    avio_read(pb, version, 8);
83
0
    if (memcmp(version, MLV_VERSION, 5) || avio_rl64(pb) != guid)
84
0
        return AVERROR_INVALIDDATA;
85
0
    avio_skip(pb, size - 24);
86
0
    return 0;
87
0
}
88
89
static void read_string(AVFormatContext *avctx, AVIOContext *pb, const char *tag, unsigned size)
90
7.92k
{
91
7.92k
    char * value = av_malloc(size + 1);
92
7.92k
    int ret;
93
94
7.92k
    if (!value) {
95
500
        avio_skip(pb, size);
96
500
        return;
97
500
    }
98
99
7.42k
    ret = avio_read(pb, value, size);
100
7.42k
    if (ret != size || !value[0]) {
101
2.67k
        av_free(value);
102
2.67k
        return;
103
2.67k
    }
104
105
4.74k
    value[size] = 0;
106
4.74k
    av_dict_set(&avctx->metadata, tag, value, AV_DICT_DONT_STRDUP_VAL);
107
4.74k
}
108
109
static void read_uint8(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
110
3.35k
{
111
3.35k
    av_dict_set_int(&avctx->metadata, tag, avio_r8(pb), 0);
112
3.35k
}
113
114
static void read_uint16(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
115
5.03k
{
116
5.03k
    av_dict_set_int(&avctx->metadata, tag, avio_rl16(pb), 0);
117
5.03k
}
118
119
static void read_uint32(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
120
10.6k
{
121
10.6k
    av_dict_set_int(&avctx->metadata, tag, avio_rl32(pb), 0);
122
10.6k
}
123
124
static void read_uint64(AVFormatContext *avctx, AVIOContext *pb, const char *tag, const char *fmt)
125
608
{
126
608
    av_dict_set_int(&avctx->metadata, tag, avio_rl64(pb), 0);
127
608
}
128
129
static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int file)
130
5.36k
{
131
5.36k
    FFStream *const vsti = ffstream(vst), *const asti = ffstream(ast);
132
5.36k
    MlvContext *mlv = avctx->priv_data;
133
5.36k
    AVIOContext *pb = mlv->pb[file];
134
5.36k
    int ret;
135
1.25M
    while (!avio_feof(pb)) {
136
1.25M
        int type;
137
1.25M
        unsigned int size;
138
1.25M
        type = avio_rl32(pb);
139
1.25M
        size = avio_rl32(pb);
140
1.25M
        avio_skip(pb, 8); //timestamp
141
1.25M
        if (size < 16)
142
1.01k
            break;
143
1.24M
        size -= 16;
144
1.24M
        if (vst && type == MKTAG('R','A','W','I') && size >= 164) {
145
1.54k
            unsigned width  = avio_rl16(pb);
146
1.54k
            unsigned height = avio_rl16(pb);
147
1.54k
            unsigned bits_per_coded_sample;
148
1.54k
            ret = av_image_check_size(width, height, 0, avctx);
149
1.54k
            if (ret < 0)
150
37
                return ret;
151
1.50k
            if (avio_rl32(pb) != 1)
152
1.16k
                avpriv_request_sample(avctx, "raw api version");
153
1.50k
            avio_skip(pb, 20); // pointer, width, height, pitch, frame_size
154
1.50k
            bits_per_coded_sample = avio_rl32(pb);
155
1.50k
            if (bits_per_coded_sample > (INT_MAX - 7) / (width * height)) {
156
38
                av_log(avctx, AV_LOG_ERROR,
157
38
                       "invalid bits_per_coded_sample %u (size: %ux%u)\n",
158
38
                       bits_per_coded_sample, width, height);
159
38
                return AVERROR_INVALIDDATA;
160
38
            }
161
1.47k
            vst->codecpar->width  = width;
162
1.47k
            vst->codecpar->height = height;
163
1.47k
            vst->codecpar->bits_per_coded_sample = bits_per_coded_sample;
164
1.47k
            mlv->black_level = avio_rl32(pb);
165
1.47k
            mlv->white_level = avio_rl32(pb);
166
1.47k
            avio_skip(pb, 16 + 24); // xywh, active_area, exposure_bias
167
1.47k
            if (avio_rl32(pb) != 0x2010100) /* RGGB */
168
1.23k
                avpriv_request_sample(avctx, "cfa_pattern");
169
1.47k
            avio_skip(pb, 4); // calibration_illuminant1,
170
14.7k
            for (int i = 0; i < 9; i++) {
171
13.2k
                mlv->color_matrix1[i][0] = avio_rl32(pb);
172
13.2k
                mlv->color_matrix1[i][1] = avio_rl32(pb);
173
13.2k
            }
174
1.47k
            avio_skip(pb, 4); // dynamic_range
175
1.47k
            vst->codecpar->format    = AV_PIX_FMT_BAYER_RGGB16LE;
176
1.47k
            vst->codecpar->codec_tag = MKTAG('B', 'I', 'T', 16);
177
1.47k
            size -= 164;
178
1.24M
        } else if (ast && type == MKTAG('W', 'A', 'V', 'I') && size >= 16) {
179
6.91k
            ret = ff_get_wav_header(avctx, pb, ast->codecpar, 16, 0);
180
6.91k
            if (ret < 0)
181
169
                return ret;
182
6.74k
            size -= 16;
183
1.24M
        } else if (type == MKTAG('I','N','F','O')) {
184
1.28k
            if (size > 0)
185
643
                read_string(avctx, pb, "info", size);
186
1.28k
            continue;
187
1.24M
        } else if (type == MKTAG('I','D','N','T') && size >= 36) {
188
1.97k
            read_string(avctx, pb, "cameraName", 32);
189
1.97k
            read_uint32(avctx, pb, "cameraModel", "0x%"PRIx32);
190
1.97k
            size -= 36;
191
1.97k
            if (size >= 32) {
192
1.49k
                read_string(avctx, pb, "cameraSerial", 32);
193
1.49k
                size -= 32;
194
1.49k
            }
195
1.23M
        } else if (type == MKTAG('L','E','N','S') && size >= 48) {
196
1.67k
            read_uint16(avctx, pb, "focalLength", "%i");
197
1.67k
            read_uint16(avctx, pb, "focalDist", "%i");
198
1.67k
            read_uint16(avctx, pb, "aperture", "%i");
199
1.67k
            read_uint8(avctx, pb, "stabilizerMode", "%i");
200
1.67k
            read_uint8(avctx, pb, "autofocusMode", "%i");
201
1.67k
            read_uint32(avctx, pb, "flags", "0x%"PRIx32);
202
1.67k
            read_uint32(avctx, pb, "lensID", "%"PRIi32);
203
1.67k
            read_string(avctx, pb, "lensName", 32);
204
1.67k
            size -= 48;
205
1.67k
            if (size >= 32) {
206
756
                read_string(avctx, pb, "lensSerial", 32);
207
756
                size -= 32;
208
756
            }
209
1.23M
        } else if (vst && type == MKTAG('V', 'I', 'D', 'F') && size >= 4) {
210
31.0k
            uint64_t pts = avio_rl32(pb);
211
31.0k
            ff_add_index_entry(&vsti->index_entries, &vsti->nb_index_entries,
212
31.0k
                               &vsti->index_entries_allocated_size,
213
31.0k
                               avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME);
214
31.0k
            size -= 4;
215
1.20M
        } else if (ast && type == MKTAG('A', 'U', 'D', 'F') && size >= 4) {
216
8.67k
            uint64_t pts = avio_rl32(pb);
217
8.67k
            ff_add_index_entry(&asti->index_entries, &asti->nb_index_entries,
218
8.67k
                               &asti->index_entries_allocated_size,
219
8.67k
                               avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME);
220
8.67k
            size -= 4;
221
1.19M
        } else if (vst && type == MKTAG('W','B','A','L') && size >= 28) {
222
279
            read_uint32(avctx, pb, "wb_mode", "%"PRIi32);
223
279
            read_uint32(avctx, pb, "kelvin", "%"PRIi32);
224
279
            read_uint32(avctx, pb, "wbgain_r", "%"PRIi32);
225
279
            read_uint32(avctx, pb, "wbgain_g", "%"PRIi32);
226
279
            read_uint32(avctx, pb, "wbgain_b", "%"PRIi32);
227
279
            read_uint32(avctx, pb, "wbs_gm", "%"PRIi32);
228
279
            read_uint32(avctx, pb, "wbs_ba", "%"PRIi32);
229
279
            size -= 28;
230
1.19M
        } else if (type == MKTAG('R','T','C','I') && size >= 20) {
231
635
            char str[32];
232
635
            struct tm time = { 0 };
233
635
            time.tm_sec    = avio_rl16(pb);
234
635
            time.tm_min    = avio_rl16(pb);
235
635
            time.tm_hour   = avio_rl16(pb);
236
635
            time.tm_mday   = avio_rl16(pb);
237
635
            time.tm_mon    = avio_rl16(pb);
238
635
            time.tm_year   = avio_rl16(pb);
239
635
            time.tm_wday   = avio_rl16(pb);
240
635
            time.tm_yday   = avio_rl16(pb);
241
635
            time.tm_isdst  = avio_rl16(pb);
242
635
            avio_skip(pb, 2);
243
635
            if (strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", &time))
244
429
                av_dict_set(&avctx->metadata, "time", str, 0);
245
635
            size -= 20;
246
1.19M
        } else if (type == MKTAG('E','X','P','O') && size >= 16) {
247
812
            av_dict_set(&avctx->metadata, "isoMode", avio_rl32(pb) ? "auto" : "manual", 0);
248
812
            read_uint32(avctx, pb, "isoValue", "%"PRIi32);
249
812
            read_uint32(avctx, pb, "isoAnalog", "%"PRIi32);
250
812
            read_uint32(avctx, pb, "digitalGain", "%"PRIi32);
251
812
            size -= 16;
252
812
            if (size >= 8) {
253
608
                read_uint64(avctx, pb, "shutterValue", "%"PRIi64);
254
608
                size -= 8;
255
608
            }
256
1.19M
        } else if (type == MKTAG('S','T','Y','L') && size >= 36) {
257
181
            read_uint32(avctx, pb, "picStyleId", "%"PRIi32);
258
181
            read_uint32(avctx, pb, "contrast", "%"PRIi32);
259
181
            read_uint32(avctx, pb, "sharpness", "%"PRIi32);
260
181
            read_uint32(avctx, pb, "saturation", "%"PRIi32);
261
181
            read_uint32(avctx, pb, "colortone", "%"PRIi32);
262
181
            read_string(avctx, pb, "picStyleName", 16);
263
181
            size -= 36;
264
1.19M
        } else if (type == MKTAG('V','E','R','S') && size >= 4) {
265
1.20k
            unsigned int length = avio_rl32(pb);
266
1.20k
            read_string(avctx, pb, "version", length);
267
1.20k
            size -= length + 4;
268
1.19M
        } else if (type == MKTAG('D','A','R','K')) {
269
1.19M
        } else if (type == MKTAG('D','I','S','O')) {
270
1.19M
        } else if (type == MKTAG('M','A','R','K')) {
271
1.19M
        } else if (type == MKTAG('N','U','L','L')) {
272
1.19M
        } else if (type == MKTAG('M','L','V','I')) { /* occurs when MLV and Mnn files are concatenated */
273
1.19M
        } else if (type == MKTAG('R','A','W','C')) {
274
1.19M
        } else {
275
1.19M
            av_log(avctx, AV_LOG_INFO, "unsupported tag %s, size %u\n",
276
1.19M
                   av_fourcc2str(type), size);
277
1.19M
        }
278
1.24M
        avio_skip(pb, size);
279
1.24M
    }
280
5.11k
    return 0;
281
5.36k
}
282
283
static int read_header(AVFormatContext *avctx)
284
5.41k
{
285
5.41k
    MlvContext *mlv = avctx->priv_data;
286
5.41k
    AVIOContext *pb = avctx->pb;
287
5.41k
    AVStream *vst = NULL, *ast = NULL;
288
5.41k
    FFStream *vsti = NULL, *asti = NULL;
289
5.41k
    int size, ret;
290
5.41k
    unsigned nb_video_frames, nb_audio_frames;
291
5.41k
    uint64_t guid;
292
5.41k
    char guidstr[32];
293
294
5.41k
    avio_skip(pb, 4);
295
5.41k
    size = avio_rl32(pb);
296
5.41k
    if (size < 52)
297
58
        return AVERROR_INVALIDDATA;
298
299
5.36k
    avio_skip(pb, 8);
300
301
5.36k
    guid = avio_rl64(pb);
302
5.36k
    snprintf(guidstr, sizeof(guidstr), "0x%"PRIx64, guid);
303
5.36k
    av_dict_set(&avctx->metadata, "guid", guidstr, 0);
304
305
5.36k
    avio_skip(pb, 8); //fileNum, fileCount, fileFlags
306
307
5.36k
    mlv->class[0] = avio_rl16(pb);
308
5.36k
    mlv->class[1] = avio_rl16(pb);
309
310
5.36k
    nb_video_frames = avio_rl32(pb);
311
5.36k
    nb_audio_frames = avio_rl32(pb);
312
313
5.36k
    if (nb_video_frames && mlv->class[0]) {
314
3.41k
        vst = avformat_new_stream(avctx, NULL);
315
3.41k
        if (!vst)
316
0
            return AVERROR(ENOMEM);
317
3.41k
        vsti = ffstream(vst);
318
319
3.41k
        vst->id = 0;
320
3.41k
        vst->nb_frames = nb_video_frames;
321
3.41k
        if ((mlv->class[0] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA)))
322
1.04k
            avpriv_request_sample(avctx, "compression");
323
3.41k
        vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
324
3.41k
        switch (mlv->class[0] & ~(MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA)) {
325
254
        case MLV_VIDEO_CLASS_RAW:
326
254
            vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
327
254
            break;
328
184
        case MLV_VIDEO_CLASS_YUV:
329
184
            vst->codecpar->format   = AV_PIX_FMT_YUV420P;
330
184
            vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
331
184
            vst->codecpar->codec_tag = 0;
332
184
            break;
333
318
        case MLV_CLASS_FLAG_LJ92|MLV_VIDEO_CLASS_RAW:
334
318
            vst->codecpar->codec_id = AV_CODEC_ID_TIFF;
335
318
            break;
336
231
        case MLV_VIDEO_CLASS_JPEG:
337
231
            vst->codecpar->codec_id = AV_CODEC_ID_MJPEG;
338
231
            vst->codecpar->codec_tag = 0;
339
231
            break;
340
258
        case MLV_VIDEO_CLASS_H264:
341
258
            vst->codecpar->codec_id = AV_CODEC_ID_H264;
342
258
            vst->codecpar->codec_tag = 0;
343
258
            break;
344
2.17k
        default:
345
2.17k
            avpriv_request_sample(avctx, "unknown video class");
346
3.41k
        }
347
3.41k
    }
348
349
5.36k
    if (nb_audio_frames && mlv->class[1]) {
350
3.40k
        ast = avformat_new_stream(avctx, NULL);
351
3.40k
        if (!ast)
352
0
            return AVERROR(ENOMEM);
353
3.40k
        asti = ffstream(ast);
354
3.40k
        ast->id = 1;
355
3.40k
        ast->nb_frames = nb_audio_frames;
356
3.40k
        if ((mlv->class[1] & MLV_CLASS_FLAG_LZMA))
357
694
            avpriv_request_sample(avctx, "compression");
358
3.40k
        if ((mlv->class[1] & ~MLV_CLASS_FLAG_LZMA) != MLV_AUDIO_CLASS_WAV)
359
3.38k
            avpriv_request_sample(avctx, "unknown audio class");
360
361
3.40k
        ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
362
3.40k
        avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate);
363
3.40k
    }
364
365
5.36k
    if (vst) {
366
3.41k
       AVRational framerate;
367
3.41k
       framerate.num = avio_rl32(pb);
368
3.41k
       framerate.den = avio_rl32(pb);
369
3.41k
       avpriv_set_pts_info(vst, 64, framerate.den, framerate.num);
370
3.41k
    } else
371
1.94k
       avio_skip(pb, 8);
372
373
5.36k
    avio_skip(pb, size - 52);
374
375
    /* scan primary file */
376
5.36k
    mlv->pb[100] = avctx->pb;
377
5.36k
    ret = scan_file(avctx, vst, ast, 100);
378
5.36k
    if (ret < 0)
379
244
        return ret;
380
381
    /* scan secondary files */
382
5.11k
    if (strlen(avctx->url) > 2) {
383
1.06k
        int i;
384
1.06k
        char *filename = av_strdup(avctx->url);
385
386
1.06k
        if (!filename)
387
0
            return AVERROR(ENOMEM);
388
389
1.06k
        for (i = 0; i < 100; i++) {
390
1.06k
            snprintf(filename + strlen(filename) - 2, 3, "%02d", i);
391
1.06k
            if (avctx->io_open(avctx, &mlv->pb[i], filename, AVIO_FLAG_READ, NULL) < 0)
392
1.06k
                break;
393
0
            if (check_file_header(mlv->pb[i], guid) < 0) {
394
0
                av_log(avctx, AV_LOG_WARNING, "ignoring %s; bad format or guid mismatch\n", filename);
395
0
                ff_format_io_close(avctx, &mlv->pb[i]);
396
0
                continue;
397
0
            }
398
0
            av_log(avctx, AV_LOG_INFO, "scanning %s\n", filename);
399
0
            ret = scan_file(avctx, vst, ast, i);
400
0
            if (ret < 0) {
401
0
                av_log(avctx, AV_LOG_WARNING, "ignoring %s; %s\n", filename, av_err2str(ret));
402
0
                ff_format_io_close(avctx, &mlv->pb[i]);
403
0
                continue;
404
0
            }
405
0
        }
406
1.06k
        av_free(filename);
407
1.06k
    }
408
409
5.11k
    if (vst)
410
3.26k
        vst->duration = vsti->nb_index_entries;
411
5.11k
    if (ast)
412
3.19k
        ast->duration = asti->nb_index_entries;
413
414
5.11k
    if ((vst && !vsti->nb_index_entries) || (ast && !asti->nb_index_entries)) {
415
1.77k
        av_log(avctx, AV_LOG_ERROR, "no index entries found\n");
416
1.77k
        return AVERROR_INVALIDDATA;
417
1.77k
    }
418
419
3.34k
    if (vst && ast)
420
602
        avio_seek(pb, FFMIN(vsti->index_entries[0].pos, asti->index_entries[0].pos), SEEK_SET);
421
2.73k
    else if (vst)
422
1.17k
        avio_seek(pb, vsti->index_entries[0].pos, SEEK_SET);
423
1.56k
    else if (ast)
424
1.14k
        avio_seek(pb, asti->index_entries[0].pos, SEEK_SET);
425
426
3.34k
    return 0;
427
5.11k
}
428
429
static void write_tiff_short(PutByteContext *pb, int tag, int value)
430
8.66k
{
431
8.66k
    bytestream2_put_le16(pb, tag);
432
8.66k
    bytestream2_put_le16(pb, AV_TIFF_SHORT);
433
8.66k
    bytestream2_put_le32(pb, 1);
434
8.66k
    bytestream2_put_le16(pb, value);
435
8.66k
    bytestream2_put_le16(pb, 0);
436
8.66k
}
437
438
static void write_tiff_short2(PutByteContext *pb, int tag, int v1, int v2)
439
1.73k
{
440
1.73k
    bytestream2_put_le16(pb, tag);
441
1.73k
    bytestream2_put_le16(pb, AV_TIFF_SHORT);
442
1.73k
    bytestream2_put_le32(pb, 2);
443
1.73k
    bytestream2_put_le16(pb, v1);
444
1.73k
    bytestream2_put_le16(pb, v2);
445
1.73k
}
446
447
static void write_tiff_long(PutByteContext *pb, int tag, int value)
448
15.5k
{
449
15.5k
    bytestream2_put_le16(pb, tag);
450
15.5k
    bytestream2_put_le16(pb, AV_TIFF_LONG);
451
15.5k
    bytestream2_put_le32(pb, 1);
452
15.5k
    bytestream2_put_le32(pb, value);
453
15.5k
}
454
455
static void write_tiff_byte4(PutByteContext *pb, int tag, int v1, int v2, int v3, int v4)
456
3.46k
{
457
3.46k
    bytestream2_put_le16(pb, tag);
458
3.46k
    bytestream2_put_le16(pb, AV_TIFF_BYTE);
459
3.46k
    bytestream2_put_le32(pb, 4);
460
3.46k
    bytestream2_put_byte(pb, v1);
461
3.46k
    bytestream2_put_byte(pb, v2);
462
3.46k
    bytestream2_put_byte(pb, v3);
463
3.46k
    bytestream2_put_byte(pb, v4);
464
3.46k
}
465
466
static int get_packet_lj92(AVFormatContext *avctx, AVStream *st, AVIOContext *pbio, AVPacket *pkt, int64_t size)
467
1.77k
{
468
1.77k
    MlvContext *mlv = avctx->priv_data;
469
1.77k
    PutByteContext pbctx, *pb = &pbctx;
470
1.77k
    int ret, header_size;
471
1.77k
    uint8_t *stripofs, *matrixofs;
472
473
5.25k
#define MAX_HEADER_SIZE 2048
474
1.77k
    if ((uint64_t)size > INT32_MAX - MAX_HEADER_SIZE)
475
37
        return AVERROR_PATCHWELCOME;
476
477
1.74k
    if ((ret = av_new_packet(pkt, size + MAX_HEADER_SIZE)) < 0)
478
7
        return ret;
479
480
1.73k
    bytestream2_init_writer(pb, pkt->data, MAX_HEADER_SIZE);
481
482
1.73k
    bytestream2_put_le16(pb, 0x4949);
483
1.73k
    bytestream2_put_le16(pb, 42);
484
1.73k
    bytestream2_put_le32(pb, 8);
485
486
1.73k
    bytestream2_put_le16(pb, 18); /* nb_entries */
487
488
1.73k
    write_tiff_long(pb, TIFF_SUBFILE, 0);
489
1.73k
    write_tiff_long(pb, TIFF_WIDTH, st->codecpar->width);
490
1.73k
    write_tiff_long(pb, TIFF_HEIGHT, st->codecpar->height);
491
1.73k
    write_tiff_long(pb, TIFF_BPP,  st->codecpar->bits_per_coded_sample);
492
1.73k
    write_tiff_short(pb, TIFF_COMPR, TIFF_NEWJPEG);
493
1.73k
    write_tiff_short(pb, TIFF_PHOTOMETRIC, TIFF_PHOTOMETRIC_CFA);
494
1.73k
    write_tiff_short(pb, TIFF_FILL_ORDER, 1);
495
1.73k
    write_tiff_long(pb, TIFF_STRIP_OFFS, 0); /* stripofs */
496
1.73k
    stripofs = pb->buffer - 4;
497
498
1.73k
    write_tiff_long(pb, TIFF_SAMPLES_PER_PIXEL, 1);
499
1.73k
    write_tiff_short(pb, TIFF_ROWSPERSTRIP, st->codecpar->height);
500
1.73k
    write_tiff_long(pb, TIFF_STRIP_SIZE, size);
501
1.73k
    write_tiff_short(pb, TIFF_PLANAR, 1);
502
1.73k
    write_tiff_short2(pb, TIFF_CFA_PATTERN_DIM, 2, 2);
503
1.73k
    write_tiff_byte4(pb, TIFF_CFA_PATTERN, 0, 1, 1, 2);
504
1.73k
    write_tiff_byte4(pb, DNG_VERSION, 1, 4, 0, 0);
505
1.73k
    write_tiff_long(pb, DNG_BLACK_LEVEL, mlv->black_level);
506
1.73k
    write_tiff_long(pb, DNG_WHITE_LEVEL, mlv->white_level);
507
508
1.73k
    bytestream2_put_le16(pb, DNG_COLOR_MATRIX1);
509
1.73k
    bytestream2_put_le16(pb, AV_TIFF_SRATIONAL);
510
1.73k
    bytestream2_put_le32(pb, 9);
511
1.73k
    bytestream2_put_le32(pb, 0); /* matrixofs */
512
1.73k
    matrixofs = pb->buffer - 4;
513
1.73k
    bytestream2_put_le32(pb, 0);
514
515
1.73k
    AV_WL32(matrixofs, bytestream2_tell_p(pb));
516
17.3k
    for (int i = 0; i < 9; i++) {
517
15.5k
        bytestream2_put_le32(pb, mlv->color_matrix1[i][0]);
518
15.5k
        bytestream2_put_le32(pb, mlv->color_matrix1[i][1]);
519
15.5k
    }
520
521
1.73k
    header_size = bytestream2_tell_p(pb);
522
523
1.73k
    AV_WL32(stripofs, header_size);
524
1.73k
    ret = avio_read(pbio, pkt->data + header_size, size);
525
1.73k
    if (ret < 0)
526
150
        return ret;
527
528
1.58k
    return 0;
529
1.73k
}
530
531
static int read_packet(AVFormatContext *avctx, AVPacket *pkt)
532
41.5k
{
533
41.5k
    MlvContext *mlv = avctx->priv_data;
534
41.5k
    AVIOContext *pb;
535
41.5k
    AVStream *st;
536
41.5k
    FFStream *sti;
537
41.5k
    int index, ret;
538
41.5k
    unsigned int size, space;
539
540
41.5k
    if (!avctx->nb_streams)
541
420
        return AVERROR_EOF;
542
543
41.1k
    st = avctx->streams[mlv->stream_index];
544
41.1k
    sti = ffstream(st);
545
41.1k
    if (mlv->pts >= st->duration)
546
2.68k
        return AVERROR_EOF;
547
548
38.4k
    index = av_index_search_timestamp(st, mlv->pts, AVSEEK_FLAG_ANY);
549
38.4k
    if (index < 0) {
550
1
        av_log(avctx, AV_LOG_ERROR, "could not find index entry for frame %"PRId64"\n", mlv->pts);
551
1
        return AVERROR_INVALIDDATA;
552
1
    }
553
554
38.4k
    pb = mlv->pb[sti->index_entries[index].size];
555
38.4k
    if (!pb) {
556
0
        ret = FFERROR_REDO;
557
0
        goto next_packet;
558
0
    }
559
38.4k
    avio_seek(pb, sti->index_entries[index].pos, SEEK_SET);
560
561
38.4k
    avio_skip(pb, 4); // blockType
562
38.4k
    size = avio_rl32(pb);
563
38.4k
    if (size < 16)
564
465
        return AVERROR_INVALIDDATA;
565
38.0k
    avio_skip(pb, 12); //timestamp, frameNumber
566
38.0k
    size -= 12;
567
38.0k
    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
568
24.2k
        if (size < 8)
569
15
            return AVERROR_INVALIDDATA;
570
24.2k
        avio_skip(pb, 8); // cropPosX, cropPosY, panPosX, panPosY
571
24.2k
        size -= 8;
572
24.2k
    }
573
38.0k
    space = avio_rl32(pb);
574
38.0k
    if (size < space + 4LL)
575
438
        return AVERROR_INVALIDDATA;
576
37.5k
    avio_skip(pb, space);
577
37.5k
    size -= space;
578
579
37.5k
    if ((mlv->class[st->id] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA))) {
580
244
        ret = AVERROR_PATCHWELCOME;
581
37.3k
    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
582
23.7k
        if (st->codecpar->codec_id == AV_CODEC_ID_TIFF)
583
1.77k
            ret = get_packet_lj92(avctx, st, pb, pkt, size);
584
21.9k
        else
585
21.9k
            ret = av_get_packet(pb, pkt, (st->codecpar->width * st->codecpar->height * st->codecpar->bits_per_coded_sample + 7) >> 3);
586
23.7k
    } else { // AVMEDIA_TYPE_AUDIO
587
13.5k
        ret = av_get_packet(pb, pkt, size - 4);
588
13.5k
    }
589
590
37.5k
    if (ret < 0)
591
1.41k
        return ret;
592
593
36.1k
    pkt->stream_index = mlv->stream_index;
594
36.1k
    pkt->pts = mlv->pts;
595
596
36.1k
    ret = 0;
597
36.1k
next_packet:
598
36.1k
    mlv->stream_index++;
599
36.1k
    if (mlv->stream_index == avctx->nb_streams) {
600
25.2k
        mlv->stream_index = 0;
601
25.2k
        mlv->pts++;
602
25.2k
    }
603
36.1k
    return ret;
604
36.1k
}
605
606
static int read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
607
0
{
608
0
    MlvContext *mlv = avctx->priv_data;
609
610
0
    if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
611
0
        return AVERROR(ENOSYS);
612
613
0
    if (!(avctx->pb->seekable & AVIO_SEEKABLE_NORMAL))
614
0
        return AVERROR(ENOSYS);
615
616
0
    mlv->pts = timestamp;
617
0
    return 0;
618
0
}
619
620
static int read_close(AVFormatContext *s)
621
5.41k
{
622
5.41k
    MlvContext *mlv = s->priv_data;
623
5.41k
    int i;
624
547k
    for (i = 0; i < 100; i++)
625
541k
        ff_format_io_close(s, &mlv->pb[i]);
626
5.41k
    return 0;
627
5.41k
}
628
629
const FFInputFormat ff_mlv_demuxer = {
630
    .p.name         = "mlv",
631
    .p.long_name    = NULL_IF_CONFIG_SMALL("Magic Lantern Video (MLV)"),
632
    .priv_data_size = sizeof(MlvContext),
633
    .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
634
    .read_probe     = probe,
635
    .read_header    = read_header,
636
    .read_packet    = read_packet,
637
    .read_close     = read_close,
638
    .read_seek      = read_seek,
639
};