/src/ffmpeg/libavformat/vocdec.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Creative Voice File demuxer. |
3 | | * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org> |
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 | | #include "libavutil/intreadwrite.h" |
23 | | #include "demux.h" |
24 | | #include "voc.h" |
25 | | #include "internal.h" |
26 | | |
27 | | static int voc_probe(const AVProbeData *p) |
28 | 358k | { |
29 | 358k | int version, check; |
30 | | |
31 | 358k | if (memcmp(p->buf, ff_voc_magic, sizeof(ff_voc_magic) - 1)) |
32 | 358k | return 0; |
33 | 259 | version = AV_RL16(p->buf + 22); |
34 | 259 | check = AV_RL16(p->buf + 24); |
35 | 259 | if (~version + 0x1234 != check) |
36 | 241 | return 10; |
37 | | |
38 | 18 | return AVPROBE_SCORE_MAX; |
39 | 259 | } |
40 | | |
41 | | static int voc_read_header(AVFormatContext *s) |
42 | 6.40k | { |
43 | 6.40k | VocDecContext *voc = s->priv_data; |
44 | 6.40k | AVIOContext *pb = s->pb; |
45 | 6.40k | int header_size; |
46 | | |
47 | 6.40k | avio_skip(pb, 20); |
48 | 6.40k | header_size = avio_rl16(pb) - 22; |
49 | 6.40k | if (header_size != 4) { |
50 | 4.28k | av_log(s, AV_LOG_ERROR, "unknown header size: %d\n", header_size); |
51 | 4.28k | return AVERROR(ENOSYS); |
52 | 4.28k | } |
53 | 2.11k | avio_skip(pb, header_size); |
54 | | |
55 | 2.11k | s->ctx_flags |= AVFMTCTX_NOHEADER; |
56 | | |
57 | 2.11k | voc->remaining_size = 0; |
58 | 2.11k | return 0; |
59 | 6.40k | } |
60 | | |
61 | | static int voc_read_packet(AVFormatContext *s, AVPacket *pkt) |
62 | 947k | { |
63 | 947k | if (!s->nb_streams) { |
64 | 2.11k | AVStream *st = avformat_new_stream(s, NULL); |
65 | 2.11k | if (!st) |
66 | 0 | return AVERROR(ENOMEM); |
67 | 2.11k | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; |
68 | 2.11k | } |
69 | 947k | return ff_voc_get_packet(s, pkt, s->streams[0], 0); |
70 | 947k | } |
71 | | |
72 | | static int voc_read_seek(AVFormatContext *s, int stream_index, |
73 | | int64_t timestamp, int flags) |
74 | 0 | { |
75 | 0 | VocDecContext *voc = s->priv_data; |
76 | 0 | AVStream *st; |
77 | 0 | FFStream *sti; |
78 | 0 | int index; |
79 | |
|
80 | 0 | if (s->nb_streams < 1) { |
81 | 0 | av_log(s, AV_LOG_ERROR, "cannot seek while no stream was found yet\n"); |
82 | 0 | return AVERROR(EINVAL); |
83 | 0 | } |
84 | | |
85 | 0 | st = s->streams[stream_index]; |
86 | 0 | sti = ffstream(st); |
87 | 0 | index = av_index_search_timestamp(st, timestamp, flags); |
88 | |
|
89 | 0 | if (index >= 0 && index < sti->nb_index_entries - 1) { |
90 | 0 | const AVIndexEntry *const e = &sti->index_entries[index]; |
91 | 0 | avio_seek(s->pb, e->pos, SEEK_SET); |
92 | 0 | voc->pts = e->timestamp; |
93 | 0 | voc->remaining_size = e->size; |
94 | 0 | return 0; |
95 | 0 | } else if (sti->nb_index_entries && sti->index_entries[0].timestamp <= timestamp) { |
96 | 0 | const AVIndexEntry *const e = &sti->index_entries[sti->nb_index_entries - 1]; |
97 | | // prepare context for seek_frame_generic() |
98 | 0 | voc->pts = e->timestamp; |
99 | 0 | voc->remaining_size = e->size; |
100 | 0 | } |
101 | 0 | return -1; |
102 | 0 | } |
103 | | |
104 | | const FFInputFormat ff_voc_demuxer = { |
105 | | .p.name = "voc", |
106 | | .p.long_name = NULL_IF_CONFIG_SMALL("Creative Voice"), |
107 | | .p.codec_tag = ff_voc_codec_tags_list, |
108 | | .priv_data_size = sizeof(VocDecContext), |
109 | | .read_probe = voc_probe, |
110 | | .read_header = voc_read_header, |
111 | | .read_packet = voc_read_packet, |
112 | | .read_seek = voc_read_seek, |
113 | | }; |