1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Interface to libmp3lame for mp3 encoding 3cabdff1aSopenharmony_ci * Copyright (c) 2002 Lennert Buytenhek <buytenh@gnu.org> 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/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Interface to libmp3lame for mp3 encoding. 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include <lame/lame.h> 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 30cabdff1aSopenharmony_ci#include "libavutil/common.h" 31cabdff1aSopenharmony_ci#include "libavutil/float_dsp.h" 32cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 33cabdff1aSopenharmony_ci#include "libavutil/log.h" 34cabdff1aSopenharmony_ci#include "libavutil/opt.h" 35cabdff1aSopenharmony_ci#include "avcodec.h" 36cabdff1aSopenharmony_ci#include "audio_frame_queue.h" 37cabdff1aSopenharmony_ci#include "codec_internal.h" 38cabdff1aSopenharmony_ci#include "encode.h" 39cabdff1aSopenharmony_ci#include "mpegaudio.h" 40cabdff1aSopenharmony_ci#include "mpegaudiodecheader.h" 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci#define BUFFER_SIZE (7200 + 2 * MPA_FRAME_SIZE + MPA_FRAME_SIZE / 4+1000) // FIXME: Buffer size to small? Adding 1000 to make up for it. 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_citypedef struct LAMEContext { 45cabdff1aSopenharmony_ci AVClass *class; 46cabdff1aSopenharmony_ci AVCodecContext *avctx; 47cabdff1aSopenharmony_ci lame_global_flags *gfp; 48cabdff1aSopenharmony_ci uint8_t *buffer; 49cabdff1aSopenharmony_ci int buffer_index; 50cabdff1aSopenharmony_ci int buffer_size; 51cabdff1aSopenharmony_ci int reservoir; 52cabdff1aSopenharmony_ci int joint_stereo; 53cabdff1aSopenharmony_ci int abr; 54cabdff1aSopenharmony_ci int delay_sent; 55cabdff1aSopenharmony_ci float *samples_flt[2]; 56cabdff1aSopenharmony_ci AudioFrameQueue afq; 57cabdff1aSopenharmony_ci AVFloatDSPContext *fdsp; 58cabdff1aSopenharmony_ci} LAMEContext; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_cistatic int realloc_buffer(LAMEContext *s) 62cabdff1aSopenharmony_ci{ 63cabdff1aSopenharmony_ci if (!s->buffer || s->buffer_size - s->buffer_index < BUFFER_SIZE) { 64cabdff1aSopenharmony_ci int new_size = s->buffer_index + 2 * BUFFER_SIZE, err; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci ff_dlog(s->avctx, "resizing output buffer: %d -> %d\n", s->buffer_size, 67cabdff1aSopenharmony_ci new_size); 68cabdff1aSopenharmony_ci if ((err = av_reallocp(&s->buffer, new_size)) < 0) { 69cabdff1aSopenharmony_ci s->buffer_size = s->buffer_index = 0; 70cabdff1aSopenharmony_ci return err; 71cabdff1aSopenharmony_ci } 72cabdff1aSopenharmony_ci s->buffer_size = new_size; 73cabdff1aSopenharmony_ci } 74cabdff1aSopenharmony_ci return 0; 75cabdff1aSopenharmony_ci} 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_cistatic av_cold int mp3lame_encode_close(AVCodecContext *avctx) 78cabdff1aSopenharmony_ci{ 79cabdff1aSopenharmony_ci LAMEContext *s = avctx->priv_data; 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_ci av_freep(&s->samples_flt[0]); 82cabdff1aSopenharmony_ci av_freep(&s->samples_flt[1]); 83cabdff1aSopenharmony_ci av_freep(&s->buffer); 84cabdff1aSopenharmony_ci av_freep(&s->fdsp); 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci ff_af_queue_close(&s->afq); 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci lame_close(s->gfp); 89cabdff1aSopenharmony_ci return 0; 90cabdff1aSopenharmony_ci} 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_cistatic av_cold int mp3lame_encode_init(AVCodecContext *avctx) 93cabdff1aSopenharmony_ci{ 94cabdff1aSopenharmony_ci LAMEContext *s = avctx->priv_data; 95cabdff1aSopenharmony_ci int ret; 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci s->avctx = avctx; 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci /* initialize LAME and get defaults */ 100cabdff1aSopenharmony_ci if (!(s->gfp = lame_init())) 101cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci lame_set_num_channels(s->gfp, avctx->ch_layout.nb_channels); 105cabdff1aSopenharmony_ci lame_set_mode(s->gfp, avctx->ch_layout.nb_channels > 1 ? 106cabdff1aSopenharmony_ci s->joint_stereo ? JOINT_STEREO : STEREO : MONO); 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci /* sample rate */ 109cabdff1aSopenharmony_ci lame_set_in_samplerate (s->gfp, avctx->sample_rate); 110cabdff1aSopenharmony_ci lame_set_out_samplerate(s->gfp, avctx->sample_rate); 111cabdff1aSopenharmony_ci 112cabdff1aSopenharmony_ci /* algorithmic quality */ 113cabdff1aSopenharmony_ci if (avctx->compression_level != FF_COMPRESSION_DEFAULT) 114cabdff1aSopenharmony_ci lame_set_quality(s->gfp, avctx->compression_level); 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci /* rate control */ 117cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_QSCALE) { // VBR 118cabdff1aSopenharmony_ci lame_set_VBR(s->gfp, vbr_default); 119cabdff1aSopenharmony_ci lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA); 120cabdff1aSopenharmony_ci } else { 121cabdff1aSopenharmony_ci if (avctx->bit_rate) { 122cabdff1aSopenharmony_ci if (s->abr) { // ABR 123cabdff1aSopenharmony_ci lame_set_VBR(s->gfp, vbr_abr); 124cabdff1aSopenharmony_ci lame_set_VBR_mean_bitrate_kbps(s->gfp, avctx->bit_rate / 1000); 125cabdff1aSopenharmony_ci } else // CBR 126cabdff1aSopenharmony_ci lame_set_brate(s->gfp, avctx->bit_rate / 1000); 127cabdff1aSopenharmony_ci } 128cabdff1aSopenharmony_ci } 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci /* lowpass cutoff frequency */ 131cabdff1aSopenharmony_ci if (avctx->cutoff) 132cabdff1aSopenharmony_ci lame_set_lowpassfreq(s->gfp, avctx->cutoff); 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci /* do not get a Xing VBR header frame from LAME */ 135cabdff1aSopenharmony_ci lame_set_bWriteVbrTag(s->gfp,0); 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci /* bit reservoir usage */ 138cabdff1aSopenharmony_ci lame_set_disable_reservoir(s->gfp, !s->reservoir); 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci /* set specified parameters */ 141cabdff1aSopenharmony_ci if (lame_init_params(s->gfp) < 0) { 142cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 143cabdff1aSopenharmony_ci goto error; 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci /* get encoder delay */ 147cabdff1aSopenharmony_ci avctx->initial_padding = lame_get_encoder_delay(s->gfp) + 528 + 1; 148cabdff1aSopenharmony_ci ff_af_queue_init(avctx, &s->afq); 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci avctx->frame_size = lame_get_framesize(s->gfp); 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci /* allocate float sample buffers */ 153cabdff1aSopenharmony_ci if (avctx->sample_fmt == AV_SAMPLE_FMT_FLTP) { 154cabdff1aSopenharmony_ci int ch; 155cabdff1aSopenharmony_ci for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { 156cabdff1aSopenharmony_ci s->samples_flt[ch] = av_malloc_array(avctx->frame_size, 157cabdff1aSopenharmony_ci sizeof(*s->samples_flt[ch])); 158cabdff1aSopenharmony_ci if (!s->samples_flt[ch]) { 159cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 160cabdff1aSopenharmony_ci goto error; 161cabdff1aSopenharmony_ci } 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci } 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci ret = realloc_buffer(s); 166cabdff1aSopenharmony_ci if (ret < 0) 167cabdff1aSopenharmony_ci goto error; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); 170cabdff1aSopenharmony_ci if (!s->fdsp) { 171cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 172cabdff1aSopenharmony_ci goto error; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci return 0; 177cabdff1aSopenharmony_cierror: 178cabdff1aSopenharmony_ci mp3lame_encode_close(avctx); 179cabdff1aSopenharmony_ci return ret; 180cabdff1aSopenharmony_ci} 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci#define ENCODE_BUFFER(func, buf_type, buf_name) do { \ 183cabdff1aSopenharmony_ci lame_result = func(s->gfp, \ 184cabdff1aSopenharmony_ci (const buf_type *)buf_name[0], \ 185cabdff1aSopenharmony_ci (const buf_type *)buf_name[1], frame->nb_samples, \ 186cabdff1aSopenharmony_ci s->buffer + s->buffer_index, \ 187cabdff1aSopenharmony_ci s->buffer_size - s->buffer_index); \ 188cabdff1aSopenharmony_ci} while (0) 189cabdff1aSopenharmony_ci 190cabdff1aSopenharmony_cistatic int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, 191cabdff1aSopenharmony_ci const AVFrame *frame, int *got_packet_ptr) 192cabdff1aSopenharmony_ci{ 193cabdff1aSopenharmony_ci LAMEContext *s = avctx->priv_data; 194cabdff1aSopenharmony_ci MPADecodeHeader hdr; 195cabdff1aSopenharmony_ci int len, ret, ch, discard_padding; 196cabdff1aSopenharmony_ci int lame_result; 197cabdff1aSopenharmony_ci uint32_t h; 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci if (frame) { 200cabdff1aSopenharmony_ci switch (avctx->sample_fmt) { 201cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S16P: 202cabdff1aSopenharmony_ci ENCODE_BUFFER(lame_encode_buffer, int16_t, frame->data); 203cabdff1aSopenharmony_ci break; 204cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_S32P: 205cabdff1aSopenharmony_ci ENCODE_BUFFER(lame_encode_buffer_int, int32_t, frame->data); 206cabdff1aSopenharmony_ci break; 207cabdff1aSopenharmony_ci case AV_SAMPLE_FMT_FLTP: 208cabdff1aSopenharmony_ci if (frame->linesize[0] < 4 * FFALIGN(frame->nb_samples, 8)) { 209cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "inadequate AVFrame plane padding\n"); 210cabdff1aSopenharmony_ci return AVERROR(EINVAL); 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { 213cabdff1aSopenharmony_ci s->fdsp->vector_fmul_scalar(s->samples_flt[ch], 214cabdff1aSopenharmony_ci (const float *)frame->data[ch], 215cabdff1aSopenharmony_ci 32768.0f, 216cabdff1aSopenharmony_ci FFALIGN(frame->nb_samples, 8)); 217cabdff1aSopenharmony_ci } 218cabdff1aSopenharmony_ci ENCODE_BUFFER(lame_encode_buffer_float, float, s->samples_flt); 219cabdff1aSopenharmony_ci break; 220cabdff1aSopenharmony_ci default: 221cabdff1aSopenharmony_ci return AVERROR_BUG; 222cabdff1aSopenharmony_ci } 223cabdff1aSopenharmony_ci } else if (!s->afq.frame_alloc) { 224cabdff1aSopenharmony_ci lame_result = 0; 225cabdff1aSopenharmony_ci } else { 226cabdff1aSopenharmony_ci lame_result = lame_encode_flush(s->gfp, s->buffer + s->buffer_index, 227cabdff1aSopenharmony_ci s->buffer_size - s->buffer_index); 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci if (lame_result < 0) { 230cabdff1aSopenharmony_ci if (lame_result == -1) { 231cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 232cabdff1aSopenharmony_ci "lame: output buffer too small (buffer index: %d, free bytes: %d)\n", 233cabdff1aSopenharmony_ci s->buffer_index, s->buffer_size - s->buffer_index); 234cabdff1aSopenharmony_ci } 235cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 236cabdff1aSopenharmony_ci } 237cabdff1aSopenharmony_ci s->buffer_index += lame_result; 238cabdff1aSopenharmony_ci ret = realloc_buffer(s); 239cabdff1aSopenharmony_ci if (ret < 0) { 240cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "error reallocating output buffer\n"); 241cabdff1aSopenharmony_ci return ret; 242cabdff1aSopenharmony_ci } 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci /* add current frame to the queue */ 245cabdff1aSopenharmony_ci if (frame) { 246cabdff1aSopenharmony_ci if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) 247cabdff1aSopenharmony_ci return ret; 248cabdff1aSopenharmony_ci } 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci /* Move 1 frame from the LAME buffer to the output packet, if available. 251cabdff1aSopenharmony_ci We have to parse the first frame header in the output buffer to 252cabdff1aSopenharmony_ci determine the frame size. */ 253cabdff1aSopenharmony_ci if (s->buffer_index < 4) 254cabdff1aSopenharmony_ci return 0; 255cabdff1aSopenharmony_ci h = AV_RB32(s->buffer); 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci ret = avpriv_mpegaudio_decode_header(&hdr, h); 258cabdff1aSopenharmony_ci if (ret < 0) { 259cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid mp3 header at start of buffer\n"); 260cabdff1aSopenharmony_ci return AVERROR_BUG; 261cabdff1aSopenharmony_ci } else if (ret) { 262cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "free format output not supported\n"); 263cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 264cabdff1aSopenharmony_ci } 265cabdff1aSopenharmony_ci len = hdr.frame_size; 266cabdff1aSopenharmony_ci ff_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, 267cabdff1aSopenharmony_ci s->buffer_index); 268cabdff1aSopenharmony_ci if (len <= s->buffer_index) { 269cabdff1aSopenharmony_ci if ((ret = ff_get_encode_buffer(avctx, avpkt, len, 0)) < 0) 270cabdff1aSopenharmony_ci return ret; 271cabdff1aSopenharmony_ci memcpy(avpkt->data, s->buffer, len); 272cabdff1aSopenharmony_ci s->buffer_index -= len; 273cabdff1aSopenharmony_ci memmove(s->buffer, s->buffer + len, s->buffer_index); 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci /* Get the next frame pts/duration */ 276cabdff1aSopenharmony_ci ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts, 277cabdff1aSopenharmony_ci &avpkt->duration); 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_ci discard_padding = avctx->frame_size - avpkt->duration; 280cabdff1aSopenharmony_ci // Check if subtraction resulted in an overflow 281cabdff1aSopenharmony_ci if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) { 282cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n"); 283cabdff1aSopenharmony_ci av_packet_unref(avpkt); 284cabdff1aSopenharmony_ci return AVERROR(EINVAL); 285cabdff1aSopenharmony_ci } 286cabdff1aSopenharmony_ci if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0) { 287cabdff1aSopenharmony_ci uint8_t* side_data = av_packet_new_side_data(avpkt, 288cabdff1aSopenharmony_ci AV_PKT_DATA_SKIP_SAMPLES, 289cabdff1aSopenharmony_ci 10); 290cabdff1aSopenharmony_ci if(!side_data) { 291cabdff1aSopenharmony_ci av_packet_unref(avpkt); 292cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 293cabdff1aSopenharmony_ci } 294cabdff1aSopenharmony_ci if (!s->delay_sent) { 295cabdff1aSopenharmony_ci AV_WL32(side_data, avctx->initial_padding); 296cabdff1aSopenharmony_ci s->delay_sent = 1; 297cabdff1aSopenharmony_ci } 298cabdff1aSopenharmony_ci AV_WL32(side_data + 4, discard_padding); 299cabdff1aSopenharmony_ci } 300cabdff1aSopenharmony_ci 301cabdff1aSopenharmony_ci *got_packet_ptr = 1; 302cabdff1aSopenharmony_ci } 303cabdff1aSopenharmony_ci return 0; 304cabdff1aSopenharmony_ci} 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(LAMEContext, x) 307cabdff1aSopenharmony_ci#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 308cabdff1aSopenharmony_cistatic const AVOption options[] = { 309cabdff1aSopenharmony_ci { "reservoir", "use bit reservoir", OFFSET(reservoir), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AE }, 310cabdff1aSopenharmony_ci { "joint_stereo", "use joint stereo", OFFSET(joint_stereo), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AE }, 311cabdff1aSopenharmony_ci { "abr", "use ABR", OFFSET(abr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, AE }, 312cabdff1aSopenharmony_ci { NULL }, 313cabdff1aSopenharmony_ci}; 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_cistatic const AVClass libmp3lame_class = { 316cabdff1aSopenharmony_ci .class_name = "libmp3lame encoder", 317cabdff1aSopenharmony_ci .item_name = av_default_item_name, 318cabdff1aSopenharmony_ci .option = options, 319cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 320cabdff1aSopenharmony_ci}; 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_cistatic const FFCodecDefault libmp3lame_defaults[] = { 323cabdff1aSopenharmony_ci { "b", "0" }, 324cabdff1aSopenharmony_ci { NULL }, 325cabdff1aSopenharmony_ci}; 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_cistatic const int libmp3lame_sample_rates[] = { 328cabdff1aSopenharmony_ci 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000, 0 329cabdff1aSopenharmony_ci}; 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ciconst FFCodec ff_libmp3lame_encoder = { 332cabdff1aSopenharmony_ci .p.name = "libmp3lame", 333cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), 334cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_AUDIO, 335cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_MP3, 336cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | 337cabdff1aSopenharmony_ci AV_CODEC_CAP_SMALL_LAST_FRAME, 338cabdff1aSopenharmony_ci .priv_data_size = sizeof(LAMEContext), 339cabdff1aSopenharmony_ci .init = mp3lame_encode_init, 340cabdff1aSopenharmony_ci FF_CODEC_ENCODE_CB(mp3lame_encode_frame), 341cabdff1aSopenharmony_ci .close = mp3lame_encode_close, 342cabdff1aSopenharmony_ci .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, 343cabdff1aSopenharmony_ci AV_SAMPLE_FMT_FLTP, 344cabdff1aSopenharmony_ci AV_SAMPLE_FMT_S16P, 345cabdff1aSopenharmony_ci AV_SAMPLE_FMT_NONE }, 346cabdff1aSopenharmony_ci .p.supported_samplerates = libmp3lame_sample_rates, 347cabdff1aSopenharmony_ci#if FF_API_OLD_CHANNEL_LAYOUT 348cabdff1aSopenharmony_ci .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 349cabdff1aSopenharmony_ci AV_CH_LAYOUT_STEREO, 350cabdff1aSopenharmony_ci 0 }, 351cabdff1aSopenharmony_ci#endif 352cabdff1aSopenharmony_ci .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, 353cabdff1aSopenharmony_ci AV_CHANNEL_LAYOUT_STEREO, 354cabdff1aSopenharmony_ci { 0 }, 355cabdff1aSopenharmony_ci }, 356cabdff1aSopenharmony_ci .p.priv_class = &libmp3lame_class, 357cabdff1aSopenharmony_ci .defaults = libmp3lame_defaults, 358cabdff1aSopenharmony_ci .p.wrapper_name = "libmp3lame", 359cabdff1aSopenharmony_ci}; 360