1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Interface to libgsm for GSM encoding
3cabdff1aSopenharmony_ci * Copyright (c) 2005 Alban Bedel <albeu@free.fr>
4cabdff1aSopenharmony_ci * Copyright (c) 2006, 2007 Michel Bardiaux <mbardiaux@mediaxim.be>
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci/**
24cabdff1aSopenharmony_ci * @file
25cabdff1aSopenharmony_ci * Interface to libgsm for GSM encoding
26cabdff1aSopenharmony_ci */
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci// The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci#include "config.h"
31cabdff1aSopenharmony_ci#include "config_components.h"
32cabdff1aSopenharmony_ci#if HAVE_GSM_H
33cabdff1aSopenharmony_ci#include <gsm.h>
34cabdff1aSopenharmony_ci#else
35cabdff1aSopenharmony_ci#include <gsm/gsm.h>
36cabdff1aSopenharmony_ci#endif
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
39cabdff1aSopenharmony_ci#include "libavutil/common.h"
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_ci#include "avcodec.h"
42cabdff1aSopenharmony_ci#include "codec_internal.h"
43cabdff1aSopenharmony_ci#include "encode.h"
44cabdff1aSopenharmony_ci#include "gsm.h"
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_cistatic av_cold int libgsm_encode_close(AVCodecContext *avctx) {
47cabdff1aSopenharmony_ci    gsm_destroy(avctx->priv_data);
48cabdff1aSopenharmony_ci    avctx->priv_data = NULL;
49cabdff1aSopenharmony_ci    return 0;
50cabdff1aSopenharmony_ci}
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_cistatic av_cold int libgsm_encode_init(AVCodecContext *avctx) {
53cabdff1aSopenharmony_ci    if (avctx->sample_rate != 8000) {
54cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n",
55cabdff1aSopenharmony_ci               avctx->sample_rate);
56cabdff1aSopenharmony_ci        if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
57cabdff1aSopenharmony_ci            return -1;
58cabdff1aSopenharmony_ci    }
59cabdff1aSopenharmony_ci    if (avctx->bit_rate != 13000 /* Official */ &&
60cabdff1aSopenharmony_ci        avctx->bit_rate != 13200 /* Very common */ &&
61cabdff1aSopenharmony_ci        avctx->bit_rate != 0 /* Unknown; a.o. mov does not set bitrate when decoding */ ) {
62cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Bitrate 13000bps required for GSM, got %"PRId64"bps\n",
63cabdff1aSopenharmony_ci               avctx->bit_rate);
64cabdff1aSopenharmony_ci        if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL)
65cabdff1aSopenharmony_ci            return -1;
66cabdff1aSopenharmony_ci    }
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_ci    avctx->priv_data = gsm_create();
69cabdff1aSopenharmony_ci    if (!avctx->priv_data)
70cabdff1aSopenharmony_ci        goto error;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    switch(avctx->codec_id) {
73cabdff1aSopenharmony_ci    case AV_CODEC_ID_GSM:
74cabdff1aSopenharmony_ci        avctx->frame_size = GSM_FRAME_SIZE;
75cabdff1aSopenharmony_ci        avctx->block_align = GSM_BLOCK_SIZE;
76cabdff1aSopenharmony_ci        break;
77cabdff1aSopenharmony_ci    case AV_CODEC_ID_GSM_MS: {
78cabdff1aSopenharmony_ci        int one = 1;
79cabdff1aSopenharmony_ci        gsm_option(avctx->priv_data, GSM_OPT_WAV49, &one);
80cabdff1aSopenharmony_ci        avctx->frame_size = 2*GSM_FRAME_SIZE;
81cabdff1aSopenharmony_ci        avctx->block_align = GSM_MS_BLOCK_SIZE;
82cabdff1aSopenharmony_ci        }
83cabdff1aSopenharmony_ci    }
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_ci    return 0;
86cabdff1aSopenharmony_cierror:
87cabdff1aSopenharmony_ci    libgsm_encode_close(avctx);
88cabdff1aSopenharmony_ci    return -1;
89cabdff1aSopenharmony_ci}
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_cistatic int libgsm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
92cabdff1aSopenharmony_ci                               const AVFrame *frame, int *got_packet_ptr)
93cabdff1aSopenharmony_ci{
94cabdff1aSopenharmony_ci    int ret;
95cabdff1aSopenharmony_ci    gsm_signal *samples = (gsm_signal *)frame->data[0];
96cabdff1aSopenharmony_ci    struct gsm_state *state = avctx->priv_data;
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_ci    if ((ret = ff_get_encode_buffer(avctx, avpkt, avctx->block_align, 0)) < 0)
99cabdff1aSopenharmony_ci        return ret;
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_ci    switch(avctx->codec_id) {
102cabdff1aSopenharmony_ci    case AV_CODEC_ID_GSM:
103cabdff1aSopenharmony_ci        gsm_encode(state, samples, avpkt->data);
104cabdff1aSopenharmony_ci        break;
105cabdff1aSopenharmony_ci    case AV_CODEC_ID_GSM_MS:
106cabdff1aSopenharmony_ci        gsm_encode(state, samples,                  avpkt->data);
107cabdff1aSopenharmony_ci        gsm_encode(state, samples + GSM_FRAME_SIZE, avpkt->data + 32);
108cabdff1aSopenharmony_ci    }
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci    *got_packet_ptr = 1;
111cabdff1aSopenharmony_ci    return 0;
112cabdff1aSopenharmony_ci}
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_cistatic const FFCodecDefault libgsm_defaults[] = {
115cabdff1aSopenharmony_ci    { "b",                "13000" },
116cabdff1aSopenharmony_ci    { NULL },
117cabdff1aSopenharmony_ci};
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci#if CONFIG_LIBGSM_ENCODER
120cabdff1aSopenharmony_ciconst FFCodec ff_libgsm_encoder = {
121cabdff1aSopenharmony_ci    .p.name         = "libgsm",
122cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("libgsm GSM"),
123cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_AUDIO,
124cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_GSM,
125cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1,
126cabdff1aSopenharmony_ci    .init           = libgsm_encode_init,
127cabdff1aSopenharmony_ci    FF_CODEC_ENCODE_CB(libgsm_encode_frame),
128cabdff1aSopenharmony_ci    .close          = libgsm_encode_close,
129cabdff1aSopenharmony_ci    .defaults       = libgsm_defaults,
130cabdff1aSopenharmony_ci#if FF_API_OLD_CHANNEL_LAYOUT
131cabdff1aSopenharmony_ci    .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 },
132cabdff1aSopenharmony_ci#endif
133cabdff1aSopenharmony_ci    .p.ch_layouts   = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } },
134cabdff1aSopenharmony_ci    .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
135cabdff1aSopenharmony_ci                                                     AV_SAMPLE_FMT_NONE },
136cabdff1aSopenharmony_ci    .p.wrapper_name = "libgsm",
137cabdff1aSopenharmony_ci};
138cabdff1aSopenharmony_ci#endif
139cabdff1aSopenharmony_ci#if CONFIG_LIBGSM_MS_ENCODER
140cabdff1aSopenharmony_ciconst FFCodec ff_libgsm_ms_encoder = {
141cabdff1aSopenharmony_ci    .p.name         = "libgsm_ms",
142cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"),
143cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_AUDIO,
144cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_GSM_MS,
145cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1,
146cabdff1aSopenharmony_ci    .init           = libgsm_encode_init,
147cabdff1aSopenharmony_ci    FF_CODEC_ENCODE_CB(libgsm_encode_frame),
148cabdff1aSopenharmony_ci    .close          = libgsm_encode_close,
149cabdff1aSopenharmony_ci    .defaults       = libgsm_defaults,
150cabdff1aSopenharmony_ci#if FF_API_OLD_CHANNEL_LAYOUT
151cabdff1aSopenharmony_ci    .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 },
152cabdff1aSopenharmony_ci#endif
153cabdff1aSopenharmony_ci    .p.ch_layouts   = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } },
154cabdff1aSopenharmony_ci    .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
155cabdff1aSopenharmony_ci                                                     AV_SAMPLE_FMT_NONE },
156cabdff1aSopenharmony_ci    .p.wrapper_name = "libgsm",
157cabdff1aSopenharmony_ci};
158cabdff1aSopenharmony_ci#endif
159