1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Copyright (c) 2006  Aurelien Jacobs <aurel@gnuage.org>
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * This file is part of FFmpeg.
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
10cabdff1aSopenharmony_ci *
11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14cabdff1aSopenharmony_ci * Lesser General Public License for more details.
15cabdff1aSopenharmony_ci *
16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19cabdff1aSopenharmony_ci */
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
22cabdff1aSopenharmony_ci#include "avformat.h"
23cabdff1aSopenharmony_ci#include "internal.h"
24cabdff1aSopenharmony_ci#include "voc.h"
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ciint
27cabdff1aSopenharmony_ciff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
28cabdff1aSopenharmony_ci{
29cabdff1aSopenharmony_ci    VocDecContext *voc = s->priv_data;
30cabdff1aSopenharmony_ci    AVCodecParameters *par = st->codecpar;
31cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
32cabdff1aSopenharmony_ci    VocType type;
33cabdff1aSopenharmony_ci    int size, tmp_codec=-1;
34cabdff1aSopenharmony_ci    int sample_rate = 0;
35cabdff1aSopenharmony_ci    int channels = 1;
36cabdff1aSopenharmony_ci    int64_t duration;
37cabdff1aSopenharmony_ci    int ret;
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ci    av_add_index_entry(st,
40cabdff1aSopenharmony_ci                       avio_tell(pb),
41cabdff1aSopenharmony_ci                       voc->pts,
42cabdff1aSopenharmony_ci                       voc->remaining_size,
43cabdff1aSopenharmony_ci                       0,
44cabdff1aSopenharmony_ci                       AVINDEX_KEYFRAME);
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_ci    while (!voc->remaining_size) {
47cabdff1aSopenharmony_ci        if (max_size < 4)
48cabdff1aSopenharmony_ci            max_size = 0;
49cabdff1aSopenharmony_ci        type = avio_r8(pb);
50cabdff1aSopenharmony_ci        if (type == VOC_TYPE_EOF)
51cabdff1aSopenharmony_ci            return AVERROR_EOF;
52cabdff1aSopenharmony_ci        voc->remaining_size = avio_rl24(pb);
53cabdff1aSopenharmony_ci        if (!voc->remaining_size) {
54cabdff1aSopenharmony_ci            int64_t filesize;
55cabdff1aSopenharmony_ci            if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
56cabdff1aSopenharmony_ci                return AVERROR(EIO);
57cabdff1aSopenharmony_ci            filesize = avio_size(pb);
58cabdff1aSopenharmony_ci            if (filesize - avio_tell(pb) > INT_MAX)
59cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
60cabdff1aSopenharmony_ci            voc->remaining_size = filesize - avio_tell(pb);
61cabdff1aSopenharmony_ci        }
62cabdff1aSopenharmony_ci        max_size -= 4;
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci        switch (type) {
65cabdff1aSopenharmony_ci        case VOC_TYPE_VOICE_DATA:
66cabdff1aSopenharmony_ci            if (voc->remaining_size < 2) {
67cabdff1aSopenharmony_ci                voc->remaining_size = 0;
68cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
69cabdff1aSopenharmony_ci            }
70cabdff1aSopenharmony_ci            if (!par->sample_rate) {
71cabdff1aSopenharmony_ci                par->sample_rate = 1000000 / (256 - avio_r8(pb));
72cabdff1aSopenharmony_ci                if (sample_rate)
73cabdff1aSopenharmony_ci                    par->sample_rate = sample_rate;
74cabdff1aSopenharmony_ci                avpriv_set_pts_info(st, 64, 1, par->sample_rate);
75cabdff1aSopenharmony_ci                par->ch_layout.nb_channels = channels;
76cabdff1aSopenharmony_ci                par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
77cabdff1aSopenharmony_ci            } else
78cabdff1aSopenharmony_ci                avio_skip(pb, 1);
79cabdff1aSopenharmony_ci            tmp_codec = avio_r8(pb);
80cabdff1aSopenharmony_ci            voc->remaining_size -= 2;
81cabdff1aSopenharmony_ci            max_size -= 2;
82cabdff1aSopenharmony_ci            channels = 1;
83cabdff1aSopenharmony_ci            break;
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_ci        case VOC_TYPE_VOICE_DATA_CONT:
86cabdff1aSopenharmony_ci            break;
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci        case VOC_TYPE_EXTENDED:
89cabdff1aSopenharmony_ci            sample_rate = avio_rl16(pb);
90cabdff1aSopenharmony_ci            avio_r8(pb);
91cabdff1aSopenharmony_ci            channels = avio_r8(pb) + 1;
92cabdff1aSopenharmony_ci            sample_rate = 256000000 / (channels * (65536 - sample_rate));
93cabdff1aSopenharmony_ci            voc->remaining_size = 0;
94cabdff1aSopenharmony_ci            max_size -= 4;
95cabdff1aSopenharmony_ci            break;
96cabdff1aSopenharmony_ci
97cabdff1aSopenharmony_ci        case VOC_TYPE_NEW_VOICE_DATA:
98cabdff1aSopenharmony_ci            if (voc->remaining_size < 12) {
99cabdff1aSopenharmony_ci                voc->remaining_size = 0;
100cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
101cabdff1aSopenharmony_ci            }
102cabdff1aSopenharmony_ci            if (!par->sample_rate) {
103cabdff1aSopenharmony_ci                par->sample_rate = avio_rl32(pb);
104cabdff1aSopenharmony_ci                avpriv_set_pts_info(st, 64, 1, par->sample_rate);
105cabdff1aSopenharmony_ci                par->bits_per_coded_sample = avio_r8(pb);
106cabdff1aSopenharmony_ci                channels = avio_r8(pb);
107cabdff1aSopenharmony_ci                par->ch_layout.nb_channels = channels;
108cabdff1aSopenharmony_ci            } else
109cabdff1aSopenharmony_ci                avio_skip(pb, 6);
110cabdff1aSopenharmony_ci            tmp_codec = avio_rl16(pb);
111cabdff1aSopenharmony_ci            avio_skip(pb, 4);
112cabdff1aSopenharmony_ci            voc->remaining_size -= 12;
113cabdff1aSopenharmony_ci            max_size -= 12;
114cabdff1aSopenharmony_ci            break;
115cabdff1aSopenharmony_ci
116cabdff1aSopenharmony_ci        default:
117cabdff1aSopenharmony_ci            avio_skip(pb, voc->remaining_size);
118cabdff1aSopenharmony_ci            max_size -= voc->remaining_size;
119cabdff1aSopenharmony_ci            voc->remaining_size = 0;
120cabdff1aSopenharmony_ci            break;
121cabdff1aSopenharmony_ci        }
122cabdff1aSopenharmony_ci    }
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci    if (par->sample_rate <= 0) {
125cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Invalid sample rate %d\n", par->sample_rate);
126cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
127cabdff1aSopenharmony_ci    }
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci    if (tmp_codec >= 0) {
130cabdff1aSopenharmony_ci        tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec);
131cabdff1aSopenharmony_ci        if (par->codec_id == AV_CODEC_ID_NONE)
132cabdff1aSopenharmony_ci            par->codec_id = tmp_codec;
133cabdff1aSopenharmony_ci        else if (par->codec_id != tmp_codec)
134cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n");
135cabdff1aSopenharmony_ci        if (par->codec_id == AV_CODEC_ID_NONE) {
136cabdff1aSopenharmony_ci            if (s->audio_codec_id == AV_CODEC_ID_NONE) {
137cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "unknown codec tag\n");
138cabdff1aSopenharmony_ci                return AVERROR(EINVAL);
139cabdff1aSopenharmony_ci            }
140cabdff1aSopenharmony_ci            av_log(s, AV_LOG_WARNING, "unknown codec tag\n");
141cabdff1aSopenharmony_ci        }
142cabdff1aSopenharmony_ci    }
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci    par->bit_rate = (int64_t)par->sample_rate * par->ch_layout.nb_channels * par->bits_per_coded_sample;
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci    if (max_size <= 0)
147cabdff1aSopenharmony_ci        max_size = 2048;
148cabdff1aSopenharmony_ci    size = FFMIN(voc->remaining_size, max_size);
149cabdff1aSopenharmony_ci    voc->remaining_size -= size;
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_ci    ret = av_get_packet(pb, pkt, size);
152cabdff1aSopenharmony_ci    pkt->dts = pkt->pts = voc->pts;
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_ci    duration = av_get_audio_frame_duration2(st->codecpar, size);
155cabdff1aSopenharmony_ci    if (duration > 0 && voc->pts != AV_NOPTS_VALUE)
156cabdff1aSopenharmony_ci        voc->pts += duration;
157cabdff1aSopenharmony_ci    else
158cabdff1aSopenharmony_ci        voc->pts = AV_NOPTS_VALUE;
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci    return ret;
161cabdff1aSopenharmony_ci}
162