Commit 03e512ac authored by Rafaël Carré's avatar Rafaël Carré

shine: use external library

https://github.com/savonet/shine
parent 6ba6d9fc
......@@ -2107,14 +2107,10 @@ then
fi
dnl
dnl shine fixed point mp3 encoder
dnl shine encoder plugin
dnl
AC_ARG_ENABLE(shine,
[ --enable-shine shine mp3 encoding module (default disabled)])
if test "${enable_shine}" = "yes"
then
VLC_ADD_PLUGIN([shine])
fi
PKG_ENABLE_MODULES_VLC([SHINE], [], [shine >= 3.0.0], [MPEG Audio Layer 3 encoder], [auto], [], [], [])
dnl
dnl openmax il codec plugin
......
......@@ -392,9 +392,9 @@ libfdkaac_plugin_la_LIBADD = $(FDKAAC_LIBS)
EXTRA_LTLIBRARIES += libfdkaac_plugin.la
codec_LTLIBRARIES += $(LTLIBfdkaac)
libshine_plugin_la_SOURCES = codec/shine/shine_mod.c codec/shine/enc_base.h
EXTRA_libshine_plugin_la_SOURCES = codec/shine/shine.c
libshine_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'
libshine_plugin_la_SOURCES = codec/shine.c
libshine_plugin_la_CFLAGS = $(AM_CFLAGS) $(SHINE_CFLAGS)
libshine_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)' $(SHINE_LIBS)
EXTRA_LTLIBRARIES += libshine_plugin.la
codec_LTLIBRARIES += $(LTLIBshine)
......
......@@ -33,18 +33,17 @@
#include <vlc_block.h>
#include <vlc_block_helper.h>
#include <vlc_bits.h>
#include <vlc_aout.h>
#include <assert.h>
#include <inttypes.h>
/* shine.c uses a lot of static variables, so we include the C file to keep
* the scope.
* Note that it makes this decoder non reentrant, this is why we have the
* struct entrant below */
#include "shine.c"
#include <shine/layer3.h>
struct encoder_sys_t
{
shine_t s;
unsigned int samples_per_frame;
block_fifo_t *p_fifo;
unsigned int i_buffer;
......@@ -121,12 +120,30 @@ static int OpenEncoder( vlc_object_t *p_this )
goto enomem;
}
init_mp3_encoder_engine( p_enc->fmt_out.audio.i_rate,
p_enc->fmt_out.audio.i_channels, p_enc->fmt_out.i_bitrate / 1000 );
shine_config_t cfg = {
.wave = {
.channels = p_enc->fmt_out.audio.i_channels,
.samplerate = p_enc->fmt_out.audio.i_rate,
},
};
shine_set_config_mpeg_defaults(&cfg.mpeg);
cfg.mpeg.bitr = p_enc->fmt_out.i_bitrate / 1000;
if (shine_check_config(cfg.wave.samplerate, cfg.mpeg.bitr) == -1) {
msg_Err(p_enc, "Invalid bitrate %d\n", cfg.mpeg.bitr);
free(p_sys);
return VLC_EGENERIC;
}
p_sys->s = shine_initialise(&cfg);
p_sys->samples_per_frame = shine_samples_per_pass(p_sys->s);
p_enc->pf_encode_audio = EncodeFrame;
p_enc->fmt_out.i_cat = AUDIO_ES;
p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
return VLC_SUCCESS;
enomem:
......@@ -136,7 +153,7 @@ enomem:
return VLC_ENOMEM;
}
/* We split/pack PCM blocks to a fixed size: pcm_chunk_size bytes */
/* We split/pack PCM blocks to a fixed size: p_sys->samples_per_frame * 4 bytes */
static block_t *GetPCM( encoder_t *p_enc, block_t *p_block )
{
encoder_sys_t *p_sys = p_enc->p_sys;
......@@ -145,10 +162,10 @@ static block_t *GetPCM( encoder_t *p_enc, block_t *p_block )
if( !p_block ) goto buffered; /* just return a block if we can */
/* Put the PCM samples sent by VLC in the Fifo */
while( p_sys->i_buffer + p_block->i_buffer >= pcm_chunk_size )
while( p_sys->i_buffer + p_block->i_buffer >= p_sys->samples_per_frame * 4 )
{
unsigned int i_buffer = 0;
p_pcm_block = block_Alloc( pcm_chunk_size );
p_pcm_block = block_Alloc( p_sys->samples_per_frame * 4 );
if( !p_pcm_block )
break;
......@@ -162,10 +179,10 @@ static block_t *GetPCM( encoder_t *p_enc, block_t *p_block )
}
memcpy( p_pcm_block->p_buffer + i_buffer,
p_block->p_buffer, pcm_chunk_size - i_buffer );
p_block->p_buffer += pcm_chunk_size - i_buffer;
p_block->p_buffer, p_sys->samples_per_frame * 4 - i_buffer );
p_block->p_buffer += p_sys->samples_per_frame * 4 - i_buffer;
p_block->i_buffer -= pcm_chunk_size - i_buffer;
p_block->i_buffer -= p_sys->samples_per_frame * 4 - i_buffer;
block_FifoPut( p_sys->p_fifo, p_pcm_block );
}
......@@ -202,6 +219,10 @@ buffered:
static block_t *EncodeFrame( encoder_t *p_enc, block_t *p_block )
{
if (!p_block) /* TODO: flush */
return NULL;
encoder_sys_t *p_sys = p_enc->p_sys;
block_t *p_pcm_block;
block_t *p_chain = NULL;
unsigned int i_samples = p_block->i_buffer >> 2 /* s16l stereo */;
......@@ -216,28 +237,35 @@ static block_t *EncodeFrame( encoder_t *p_enc, block_t *p_block )
break;
p_block = NULL; /* we don't need it anymore */
uint32_t enc_buffer[16384]; /* storage for 65536 Bytes XXX: too much */
struct enc_chunk_hdr *chunk = (void*) enc_buffer;
chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
encode_frame( (char*)p_pcm_block->p_buffer, chunk );
int16_t pcm_planar_buf[SHINE_MAX_SAMPLES * 2];
int16_t *pcm_planar_buf_chans[2] = {
&pcm_planar_buf[0],
&pcm_planar_buf[p_sys->samples_per_frame],
};
aout_Deinterleave( pcm_planar_buf, p_pcm_block->p_buffer,
p_sys->samples_per_frame, p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.i_codec);
long written;
unsigned char *buf = shine_encode_buffer(p_sys->s, pcm_planar_buf_chans, &written);
block_Release( p_pcm_block );
block_t *p_mp3_block = block_Alloc( chunk->enc_size );
if (written <= 0)
break;
block_t *p_mp3_block = block_Alloc( written );
if( !p_mp3_block )
break;
memcpy( p_mp3_block->p_buffer, chunk->enc_data, chunk->enc_size );
memcpy( p_mp3_block->p_buffer, buf, written );
/* date management */
p_mp3_block->i_length = SAMP_PER_FRAME1 * 1000000 /
p_mp3_block->i_length = p_sys->samples_per_frame * 1000000 /
p_enc->fmt_out.audio.i_rate;
start_date += p_mp3_block->i_length;
p_mp3_block->i_dts = p_mp3_block->i_pts = start_date;
p_mp3_block->i_nb_samples = SAMP_PER_FRAME1;
p_mp3_block->i_nb_samples = p_sys->samples_per_frame;
block_ChainAppend( &p_chain, p_mp3_block );
......@@ -259,6 +287,8 @@ static void CloseEncoder( vlc_object_t *p_this )
if( p_sys->i_buffer )
free( p_sys->p_buffer );
shine_close(p_sys->s);
block_FifoRelease( p_sys->p_fifo );
free( p_sys );
}
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Base declarations for working with software encoders
*
* Copyright (C) 2006 Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef ENC_BASE_H
#define ENC_BASE_H
/* firmware/export/system.h */
/* return p incremented by specified number of bytes */
#define SKIPBYTES(p, count) ((typeof (p))((char *)(p) + (count)))
#define P2_M1(p2) ((1 << (p2))-1)
/* align up or down to nearest 2^p2 */
#define ALIGN_DOWN_P2(n, p2) ((n) & ~P2_M1(p2))
#define ALIGN_UP_P2(n, p2) ALIGN_DOWN_P2((n) + P2_M1(p2),p2)
/* end of firmware/export/system.h */
/** encoder config structures **/
/** aiff_enc.codec **/
struct aiff_enc_config
{
#if 0
unsigned long sample_depth;
#endif
};
/** mp3_enc.codec **/
#define MP3_BITR_CAP_8 (1 << 0)
#define MP3_BITR_CAP_16 (1 << 1)
#define MP3_BITR_CAP_24 (1 << 2)
#define MP3_BITR_CAP_32 (1 << 3)
#define MP3_BITR_CAP_40 (1 << 4)
#define MP3_BITR_CAP_48 (1 << 5)
#define MP3_BITR_CAP_56 (1 << 6)
#define MP3_BITR_CAP_64 (1 << 7)
#define MP3_BITR_CAP_80 (1 << 8)
#define MP3_BITR_CAP_96 (1 << 9)
#define MP3_BITR_CAP_112 (1 << 10)
#define MP3_BITR_CAP_128 (1 << 11)
#define MP3_BITR_CAP_144 (1 << 12)
#define MP3_BITR_CAP_160 (1 << 13)
#define MP3_BITR_CAP_192 (1 << 14)
#define MP3_BITR_CAP_224 (1 << 15)
#define MP3_BITR_CAP_256 (1 << 16)
#define MP3_BITR_CAP_320 (1 << 17)
#define MP3_ENC_NUM_BITR 18
/* MPEG 1 */
#define MPEG1_SAMPR_CAPS (SAMPR_CAP_32 | SAMPR_CAP_48 | SAMPR_CAP_44)
#define MPEG1_BITR_CAPS (MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \
MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \
MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \
MP3_BITR_CAP_160 | MP3_BITR_CAP_192 | MP3_BITR_CAP_224 | \
MP3_BITR_CAP_256 | MP3_BITR_CAP_320)
/* MPEG 2 */
#define MPEG2_SAMPR_CAPS (SAMPR_CAP_22 | SAMPR_CAP_24 | SAMPR_CAP_16)
#define MPEG2_BITR_CAPS (MP3_BITR_CAP_8 | MP3_BITR_CAP_16 | MP3_BITR_CAP_24 | \
MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \
MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \
MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \
MP3_BITR_CAP_144 | MP3_BITR_CAP_160)
#if 0
/* MPEG 2.5 */
#define MPEG2_5_SAMPR_CAPS (SAMPR_CAP_8 | SAMPR_CAP_12 | SAMPR_CAP_11)
#define MPEG2_5_BITR_CAPS MPEG2_BITR_CAPS
#endif
#if 0
/* HAVE_MPEG* defines mainly apply to the bitrate menu */
#if (REC_SAMPR_CAPS & MPEG1_SAMPR_CAPS) || defined (HAVE_SPDIF_REC)
#define HAVE_MPEG1_SAMPR
#endif
#if (REC_SAMPR_CAPS & MPEG2_SAMPR_CAPS) || defined (HAVE_SPDIF_REC)
#define HAVE_MPEG2_SAMPR
#endif
#endif
#if 0
#if (REC_SAMPR_CAPS & MPEG2_5_SAMPR_CAPS) || defined (HAVE_SPDIF_REC)
#define HAVE_MPEG2_5_SAMPR
#endif
#endif /* 0 */
#define MP3_ENC_SAMPR_CAPS (MPEG1_SAMPR_CAPS | MPEG2_SAMPR_CAPS)
/* This number is count of full encoder set */
#define MP3_ENC_NUM_SAMPR 6
extern const unsigned long mp3_enc_sampr[MP3_ENC_NUM_SAMPR];
extern const unsigned long mp3_enc_bitr[MP3_ENC_NUM_BITR];
struct mp3_enc_config
{
unsigned long bitrate;
};
#define MP3_ENC_BITRATE_CFG_DEFAULT 11 /* 128 */
#define MP3_ENC_BITRATE_CFG_VALUE_LIST "8,16,24,32,40,48,56,64,80,96," \
"112,128,144,160,192,224,256,320"
/** wav_enc.codec **/
#define WAV_ENC_SAMPR_CAPS SAMPR_CAP_ALL
struct wav_enc_config
{
#if 0
unsigned long sample_depth;
#endif
};
/** wavpack_enc.codec **/
#define WAVPACK_ENC_SAMPR_CAPS SAMPR_CAP_ALL
struct wavpack_enc_config
{
#if 0
unsigned long sample_depth;
#endif
};
struct encoder_config
{
union
{
/* states which *_enc_config member is valid */
int rec_format; /* REC_FORMAT_* value */
int afmt; /* AFMT_* value */
};
union
{
struct mp3_enc_config mp3_enc;
struct wavpack_enc_config wavpack_enc;
struct wav_enc_config wav_enc;
};
};
/** Encoder chunk macros and definitions **/
#define CHUNKF_START_FILE 0x0001ul /* This chunk starts a new file */
#define CHUNKF_END_FILE 0x0002ul /* This chunk ends the current file */
#define CHUNKF_PRERECORD 0x0010ul /* This chunk is prerecord data,
a new file could start anytime */
#define CHUNKF_ABORT 0x0020ul /* Encoder should not finish this
chunk */
#define CHUNKF_ERROR (~0ul ^ (~0ul >> 1)) /* An error has occurred
(passed to/from encoder). Use the
sign bit to check (long)flags < 0. */
#define CHUNKF_ALLFLAGS (0x0033ul | CHUNKF_ERROR)
/* Header at the beginning of every encoder chunk */
#ifdef DEBUG
#define ENC_CHUNK_MAGIC H_TO_BE32(('P' << 24) | ('T' << 16) | ('Y' << 8) | 'R')
#endif
struct enc_chunk_hdr
{
#ifdef DEBUG
unsigned long id; /* overflow detection - 'PTYR' - acronym for
"PTYR Tells You Right" ;) */
#endif
unsigned long flags; /* in/out: flags used by encoder and file
writing */
size_t enc_size; /* out: amount of encoder data written to
chunk */
unsigned long num_pcm; /* out: number of PCM samples eaten during
processing
(<= size of allocated buffer) */
unsigned char *enc_data; /* out: pointer to enc_size_written bytes
of encoded audio data in chunk */
/* Encoder defined data follows header. Can be audio data + any other
stuff the encoder needs to handle on a per chunk basis */
};
/* Paranoia: be sure header size is 4-byte aligned */
#define ENC_CHUNK_HDR_SIZE \
ALIGN_UP_P2(sizeof (struct enc_chunk_hdr), 2)
/* Skip the chunk header and return data */
#define ENC_CHUNK_SKIP_HDR(t, hdr) \
((typeof (t))((char *)hdr + ENC_CHUNK_HDR_SIZE))
/* Cast p to struct enc_chunk_hdr * */
#define ENC_CHUNK_HDR(p) \
((struct enc_chunk_hdr *)(p))
enum enc_events
{
/* File writing events - data points to enc_file_event_data */
ENC_START_FILE = 0, /* a new file has been opened and no data has yet
been written */
ENC_WRITE_CHUNK, /* write the current chunk to disk */
ENC_END_FILE, /* current file about to be closed and all valid
data has been written */
/* Encoder buffer events - data points to enc_buffer_event_data */
ENC_REC_NEW_STREAM, /* Take steps to finish current stream and start
new */
};
/**
* encoder can write extra data to the file such as headers or more encoded
* samples and must update sizes and samples accordingly.
*/
struct enc_file_event_data
{
struct enc_chunk_hdr *chunk; /* Current chunk */
size_t new_enc_size; /* New size of chunk */
unsigned long new_num_pcm; /* New number of pcm in chunk */
const char *filename; /* filename to open if ENC_START_FILE */
int rec_file; /* Current file or < 0 if none */
unsigned long num_pcm_samples; /* Current pcm sample count written to
file so far. */
};
/**
* encoder may add some data to the end of the last and start of the next
* but must never yield when called so any encoding done should be absolutely
* minimal.
*/
struct enc_buffer_event_data
{
unsigned long flags; /* in: One or more of:
* CHUNKF_PRERECORD
* CHUNKF_END_FILE
* CHUNKF_START_FILE
*/
struct enc_chunk_hdr *pre_chunk; /* in: pointer to first prerecord
* chunk
*/
struct enc_chunk_hdr *chunk; /* in,out: chunk were split occurs -
* first chunk of start
*/
};
/** Callbacks called by encoder codec **/
/* parameters passed to encoder by enc_get_inputs */
struct enc_inputs
{
unsigned long sample_rate; /* out - pcm frequency */
int num_channels; /* out - number of audio channels */
struct encoder_config *config; /* out - encoder settings */
};
void enc_get_inputs(struct enc_inputs *inputs);
/* parameters pass from encoder to enc_set_parameters */
struct enc_parameters
{
/* IN parameters */
int afmt; /* AFMT_* id - sanity checker */
size_t chunk_size; /* max chunk size required */
unsigned long enc_sample_rate; /* actual sample rate used by encoder
(for recorded time calculation) */
size_t reserve_bytes; /* number of bytes to reserve immediately
following chunks */
void (*events_callback)(enum enc_events event,
void *data); /* pointer to events callback */
/* OUT parameters */
unsigned char *enc_buffer; /* pointer to enc_buffer */
size_t buf_chunk_size; /* size of chunks in enc_buffer */
int num_chunks; /* number of chunks allotted to encoder */
unsigned char *reserve_buffer; /* pointer to reserve_bytes bytes */
};
/* set the encoder dimensions - called by encoder codec at initialization
and termination */
void enc_set_parameters(struct enc_parameters *params);
/* returns pointer to next write chunk in circular buffer */
struct enc_chunk_hdr * enc_get_chunk(void);
/* releases the current chunk into the available chunks */
void enc_finish_chunk(void);
#define PCM_MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */
/* passes a pointer to next chunk of unprocessed wav data */
unsigned char * enc_get_pcm_data(size_t size);
/* puts some pcm data back in the queue */
size_t enc_unget_pcm_data(size_t size);
#endif /* ENC_BASE_H */
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment