1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * AMR Audio encoder stub
3cabdff1aSopenharmony_ci * Copyright (c) 2003 The FFmpeg project
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include <vo-amrwbenc/enc_if.h>
23cabdff1aSopenharmony_ci#include <stdio.h>
24cabdff1aSopenharmony_ci#include <stdlib.h>
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "libavutil/avstring.h"
27cabdff1aSopenharmony_ci#include "libavutil/internal.h"
28cabdff1aSopenharmony_ci#include "libavutil/opt.h"
29cabdff1aSopenharmony_ci#include "avcodec.h"
30cabdff1aSopenharmony_ci#include "codec_internal.h"
31cabdff1aSopenharmony_ci#include "encode.h"
32cabdff1aSopenharmony_ci#include "internal.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci#define MAX_PACKET_SIZE  (1 + (477 + 7) / 8)
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_citypedef struct AMRWBContext {
37cabdff1aSopenharmony_ci    AVClass *av_class;
38cabdff1aSopenharmony_ci    void  *state;
39cabdff1aSopenharmony_ci    int    mode;
40cabdff1aSopenharmony_ci    int    last_bitrate;
41cabdff1aSopenharmony_ci    int    allow_dtx;
42cabdff1aSopenharmony_ci} AMRWBContext;
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_cistatic const AVOption options[] = {
45cabdff1aSopenharmony_ci    { "dtx", "Allow DTX (generate comfort noise)", offsetof(AMRWBContext, allow_dtx), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
46cabdff1aSopenharmony_ci    { NULL }
47cabdff1aSopenharmony_ci};
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_cistatic const AVClass amrwb_class = {
50cabdff1aSopenharmony_ci    .class_name = "libvo_amrwbenc",
51cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,
52cabdff1aSopenharmony_ci    .option     = options,
53cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,
54cabdff1aSopenharmony_ci};
55cabdff1aSopenharmony_ci
56cabdff1aSopenharmony_cistatic int get_wb_bitrate_mode(int bitrate, void *log_ctx)
57cabdff1aSopenharmony_ci{
58cabdff1aSopenharmony_ci    /* make the correspondence between bitrate and mode */
59cabdff1aSopenharmony_ci    static const int rates[] = {  6600,  8850, 12650, 14250, 15850, 18250,
60cabdff1aSopenharmony_ci                                 19850, 23050, 23850 };
61cabdff1aSopenharmony_ci    int i, best = -1, min_diff = 0;
62cabdff1aSopenharmony_ci    char log_buf[200];
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci    for (i = 0; i < 9; i++) {
65cabdff1aSopenharmony_ci        if (rates[i] == bitrate)
66cabdff1aSopenharmony_ci            return i;
67cabdff1aSopenharmony_ci        if (best < 0 || abs(rates[i] - bitrate) < min_diff) {
68cabdff1aSopenharmony_ci            best     = i;
69cabdff1aSopenharmony_ci            min_diff = abs(rates[i] - bitrate);
70cabdff1aSopenharmony_ci        }
71cabdff1aSopenharmony_ci    }
72cabdff1aSopenharmony_ci    /* no bitrate matching exactly, log a warning */
73cabdff1aSopenharmony_ci    snprintf(log_buf, sizeof(log_buf), "bitrate not supported: use one of ");
74cabdff1aSopenharmony_ci    for (i = 0; i < 9; i++)
75cabdff1aSopenharmony_ci        av_strlcatf(log_buf, sizeof(log_buf), "%.2fk, ", rates[i]    / 1000.f);
76cabdff1aSopenharmony_ci    av_strlcatf(log_buf, sizeof(log_buf), "using %.2fk", rates[best] / 1000.f);
77cabdff1aSopenharmony_ci    av_log(log_ctx, AV_LOG_WARNING, "%s\n", log_buf);
78cabdff1aSopenharmony_ci
79cabdff1aSopenharmony_ci    return best;
80cabdff1aSopenharmony_ci}
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_cistatic av_cold int amr_wb_encode_init(AVCodecContext *avctx)
83cabdff1aSopenharmony_ci{
84cabdff1aSopenharmony_ci    AMRWBContext *s = avctx->priv_data;
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci    if (avctx->sample_rate != 16000 && avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
87cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Only 16000Hz sample rate supported\n");
88cabdff1aSopenharmony_ci        return AVERROR(ENOSYS);
89cabdff1aSopenharmony_ci    }
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci    if (avctx->ch_layout.nb_channels != 1) {
92cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
93cabdff1aSopenharmony_ci        return AVERROR(ENOSYS);
94cabdff1aSopenharmony_ci    }
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci    s->mode            = get_wb_bitrate_mode(avctx->bit_rate, avctx);
97cabdff1aSopenharmony_ci    s->last_bitrate    = avctx->bit_rate;
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_ci    avctx->frame_size  = 320;
100cabdff1aSopenharmony_ci    avctx->initial_padding =  80;
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci    s->state     = E_IF_init();
103cabdff1aSopenharmony_ci
104cabdff1aSopenharmony_ci    return 0;
105cabdff1aSopenharmony_ci}
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_cistatic int amr_wb_encode_close(AVCodecContext *avctx)
108cabdff1aSopenharmony_ci{
109cabdff1aSopenharmony_ci    AMRWBContext *s = avctx->priv_data;
110cabdff1aSopenharmony_ci
111cabdff1aSopenharmony_ci    E_IF_exit(s->state);
112cabdff1aSopenharmony_ci    return 0;
113cabdff1aSopenharmony_ci}
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_cistatic int amr_wb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
116cabdff1aSopenharmony_ci                               const AVFrame *frame, int *got_packet_ptr)
117cabdff1aSopenharmony_ci{
118cabdff1aSopenharmony_ci    AMRWBContext *s = avctx->priv_data;
119cabdff1aSopenharmony_ci    const int16_t *samples = (const int16_t *)frame->data[0];
120cabdff1aSopenharmony_ci    int size, ret;
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    if ((ret = ff_alloc_packet(avctx, avpkt, MAX_PACKET_SIZE)) < 0)
123cabdff1aSopenharmony_ci        return ret;
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci    if (s->last_bitrate != avctx->bit_rate) {
126cabdff1aSopenharmony_ci        s->mode         = get_wb_bitrate_mode(avctx->bit_rate, avctx);
127cabdff1aSopenharmony_ci        s->last_bitrate = avctx->bit_rate;
128cabdff1aSopenharmony_ci    }
129cabdff1aSopenharmony_ci    size = E_IF_encode(s->state, s->mode, samples, avpkt->data, s->allow_dtx);
130cabdff1aSopenharmony_ci    if (size <= 0 || size > MAX_PACKET_SIZE) {
131cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Error encoding frame\n");
132cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
133cabdff1aSopenharmony_ci    }
134cabdff1aSopenharmony_ci
135cabdff1aSopenharmony_ci    if (frame->pts != AV_NOPTS_VALUE)
136cabdff1aSopenharmony_ci        avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding);
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci    avpkt->size = size;
139cabdff1aSopenharmony_ci    *got_packet_ptr = 1;
140cabdff1aSopenharmony_ci    return 0;
141cabdff1aSopenharmony_ci}
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ciconst FFCodec ff_libvo_amrwbenc_encoder = {
144cabdff1aSopenharmony_ci    .p.name         = "libvo_amrwbenc",
145cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("Android VisualOn AMR-WB "
146cabdff1aSopenharmony_ci                                           "(Adaptive Multi-Rate Wide-Band)"),
147cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_AUDIO,
148cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_AMR_WB,
149cabdff1aSopenharmony_ci    .p.priv_class   = &amrwb_class,
150cabdff1aSopenharmony_ci    .p.wrapper_name = "libvo_amrwbenc",
151cabdff1aSopenharmony_ci    .priv_data_size = sizeof(AMRWBContext),
152cabdff1aSopenharmony_ci    .init           = amr_wb_encode_init,
153cabdff1aSopenharmony_ci    FF_CODEC_ENCODE_CB(amr_wb_encode_frame),
154cabdff1aSopenharmony_ci    .close          = amr_wb_encode_close,
155cabdff1aSopenharmony_ci    .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
156cabdff1aSopenharmony_ci                                                     AV_SAMPLE_FMT_NONE },
157cabdff1aSopenharmony_ci};
158