Coverage Report

Created: 2026-01-16 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavformat/filmstripdec.c
Line
Count
Source
1
/*
2
 * Adobe Filmstrip demuxer
3
 * Copyright (c) 2010 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
 * Adobe Filmstrip demuxer
25
 */
26
27
#include "libavutil/intreadwrite.h"
28
#include "libavutil/imgutils.h"
29
#include "avformat.h"
30
#include "demux.h"
31
#include "internal.h"
32
33
1.50k
#define RAND_TAG MKBETAG('R','a','n','d')
34
35
typedef struct FilmstripDemuxContext {
36
    int leading;
37
} FilmstripDemuxContext;
38
39
static int read_header(AVFormatContext *s)
40
1.54k
{
41
1.54k
    FilmstripDemuxContext *film = s->priv_data;
42
1.54k
    AVIOContext *pb = s->pb;
43
1.54k
    AVStream *st;
44
45
1.54k
    if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
46
44
        return AVERROR(ENOSYS);
47
48
1.50k
    avio_seek(pb, avio_size(pb) - 36, SEEK_SET);
49
1.50k
    if (avio_rb32(pb) != RAND_TAG) {
50
249
        av_log(s, AV_LOG_ERROR, "magic number not found\n");
51
249
        return AVERROR_INVALIDDATA;
52
249
    }
53
54
1.25k
    st = avformat_new_stream(s, NULL);
55
1.25k
    if (!st)
56
0
        return AVERROR(ENOMEM);
57
58
1.25k
    st->nb_frames = avio_rb32(pb);
59
1.25k
    if (avio_rb16(pb) != 0) {
60
20
        avpriv_request_sample(s, "Unsupported packing method");
61
20
        return AVERROR_PATCHWELCOME;
62
20
    }
63
64
1.23k
    avio_skip(pb, 2);
65
1.23k
    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
66
1.23k
    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
67
1.23k
    st->codecpar->format     = AV_PIX_FMT_RGBA;
68
1.23k
    st->codecpar->codec_tag  = 0; /* no fourcc */
69
1.23k
    st->codecpar->width      = avio_rb16(pb);
70
1.23k
    st->codecpar->height     = avio_rb16(pb);
71
1.23k
    film->leading         = avio_rb16(pb);
72
73
1.23k
    if (av_image_check_size(st->codecpar->width, st->codecpar->height, 0, s) < 0)
74
104
        return AVERROR_INVALIDDATA;
75
76
1.12k
    avpriv_set_pts_info(st, 64, 1, avio_rb16(pb));
77
78
1.12k
    avio_seek(pb, 0, SEEK_SET);
79
80
1.12k
    return 0;
81
1.23k
}
82
83
static int read_packet(AVFormatContext *s,
84
                       AVPacket *pkt)
85
1.18M
{
86
1.18M
    FilmstripDemuxContext *film = s->priv_data;
87
1.18M
    AVStream *st = s->streams[0];
88
89
1.18M
    if (avio_feof(s->pb))
90
1.38k
        return AVERROR_EOF;
91
1.18M
    pkt->dts = avio_tell(s->pb) / (st->codecpar->width * (int64_t)(st->codecpar->height + film->leading) * 4);
92
1.18M
    pkt->size = av_get_packet(s->pb, pkt, st->codecpar->width * st->codecpar->height * 4);
93
1.18M
    avio_skip(s->pb, st->codecpar->width * (int64_t) film->leading * 4);
94
1.18M
    if (pkt->size < 0)
95
439
        return pkt->size;
96
1.18M
    pkt->flags |= AV_PKT_FLAG_KEY;
97
1.18M
    return 0;
98
1.18M
}
99
100
static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
101
0
{
102
0
    AVStream *st = s->streams[stream_index];
103
0
    if (avio_seek(s->pb, FFMAX(timestamp, 0) * st->codecpar->width * st->codecpar->height * 4, SEEK_SET) < 0)
104
0
        return -1;
105
0
    return 0;
106
0
}
107
108
const FFInputFormat ff_filmstrip_demuxer = {
109
    .p.name         = "filmstrip",
110
    .p.long_name    = NULL_IF_CONFIG_SMALL("Adobe Filmstrip"),
111
    .p.extensions   = "flm",
112
    .priv_data_size = sizeof(FilmstripDemuxContext),
113
    .read_header    = read_header,
114
    .read_packet    = read_packet,
115
    .read_seek      = read_seek,
116
};