diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index b2dfb09f..ef5d6454 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -1,23 +1,16 @@ rspdir = ${pkglibdir}/plugins out_daapdir = ${pkglibdir}/plugins -ssc_ffmpegdir = ${pkglibdir}/plugins rsp_LTLIBRARIES=rsp.la rsp_la_LDFLAGS=-module -avoid-version rsp_la_SOURCES = rsp.c xml-rpc.c -ssc_ffmpeg_LTLIBRARIES=ssc-ffmpeg.la -ssc_ffmpeg_la_CPPFLAGS = @FFMPEG_CFLAGS@ -ssc_ffmpeg_la_LIBADD = @FFMPEG_LIBS@ -ssc_ffmpeg_la_LDFLAGS=-module -avoid-version -ssc_ffmpeg_la_SOURCES=ssc-ffmpeg.c - out_daap_LTLIBRARIES=out-daap.la out_daap_la_LDFLAGS=-module -avoid-version out_daap_la_SOURCES=out-daap.c out-daap-proto.c -EXTRA_DIST = rsp.h xml-rpc.h ssc-ffmpeg.c out-daap.h \ +EXTRA_DIST = rsp.h xml-rpc.h out-daap.h \ out-daap-proto.h AM_CFLAGS = -I.. diff --git a/src/plugins/ssc-ffmpeg.c b/src/plugins/ssc-ffmpeg.c deleted file mode 100644 index 1e030e29..00000000 --- a/src/plugins/ssc-ffmpeg.c +++ /dev/null @@ -1,555 +0,0 @@ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include - -#include -#include - -#include "ff-plugins.h" - -typedef struct tag_scan_id3header { - unsigned char id[3]; - unsigned char version[2]; - unsigned char flags; - unsigned char size[4]; -} __attribute__((packed)) SCAN_ID3HEADER; - -#ifndef TRUE -# define TRUE 1 -# define FALSE 0 -#endif - -#define BUFFER_SIZE (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3)/2 - -typedef struct tag_ssc_handle { - AVCodec *pCodec; - AVCodecContext *pCodecCtx; - AVFormatContext *pFmtCtx; - AVFrame *pFrame; - AVPacket packet; - AVInputFormat *pFormat; - - uint8_t *packet_data; - int packet_size; - int audio_stream; - - char buffer[BUFFER_SIZE]; - - char *buf_remainder; - int buf_remainder_len; - int first_frame; - - int duration; - - int total_decoded; - int total_written; - - int errnum; - int swab; - - char *error; - - int raw; - - int channels; - int sample_rate; - int bits_per_sample; - uint32_t samples; - - FILE *fin; - char file_buffer[256]; - char *file_buffer_ptr; - int file_bytes_read; - - char wav_header[44]; - int wav_offset; -} SSCHANDLE; - -#define SSC_FFMPEG_E_SUCCESS 0 -#define SSC_FFMPEG_E_BADCODEC 1 -#define SSC_FFMPEG_E_CODECOPEN 2 -#define SSC_FFMPEG_E_FILEOPEN 3 -#define SSC_FFMPEG_E_NOSTREAM 4 -#define SSC_FFMPEG_E_NOAUDIO 5 - -char *ssc_ffmpeg_errors[] = { - "Success", - "Don't have appropriate codec", - "Can't open codec", - "Cannot open file", - "Cannot find any streams", - "No audio streams" -}; - - - -/* Forwards */ -void *ssc_ffmpeg_init(void); -void ssc_ffmpeg_deinit(void *pv); -int ssc_ffmpeg_open(void *pv, MP3FILE *pmp3); -int ssc_ffmpeg_close(void *pv); -int ssc_ffmpeg_read(void *pv, char *buffer, int len); -char *ssc_ffmpeg_error(void *pv); - -/* Globals */ -PLUGIN_TRANSCODE_FN _ptfn = { - ssc_ffmpeg_init, - ssc_ffmpeg_deinit, - ssc_ffmpeg_open, - ssc_ffmpeg_close, - ssc_ffmpeg_read, - ssc_ffmpeg_error -}; - -PLUGIN_INFO _pi = { - PLUGIN_VERSION, /* version */ - PLUGIN_TRANSCODE, /* type */ - "ssc-ffmpeg/" VERSION, /* server */ - NULL, /* output fns */ - NULL, /* event fns */ - &_ptfn, /* fns */ - NULL, /* rend info */ - "flac,alac,ogg,wma" /* codeclist */ -}; - -char *ssc_ffmpeg_error(void *pv) { - SSCHANDLE *handle = (SSCHANDLE*)pv; - - return ssc_ffmpeg_errors[handle->errnum]; -} - -PLUGIN_INFO *plugin_info(void) { - /* Now done in main() */ - /* av_register_all(); */ - - return &_pi; -} - -void *ssc_ffmpeg_init(void) { - SSCHANDLE *handle; - - handle=(SSCHANDLE *)malloc(sizeof(SSCHANDLE)); - if(handle) { - memset(handle,0,sizeof(SSCHANDLE)); - } - - return (void*)handle; -} - -void ssc_ffmpeg_deinit(void *vp) { - SSCHANDLE *handle = (SSCHANDLE *)vp; - ssc_ffmpeg_close(handle); - if(handle) { - free(handle); - } - - return; -} - -int ssc_ffmpeg_open(void *vp, MP3FILE *pmp3) { - int i; - enum CodecID id=CODEC_ID_FLAC; - SSCHANDLE *handle = (SSCHANDLE*)vp; - SCAN_ID3HEADER id3; - unsigned int size = 0; - char *file; - char *codec; - int duration; - - file = pmp3->path; - codec = pmp3->codectype; - duration = pmp3->song_length; - - if(!handle) - return FALSE; - - handle->duration = duration; - handle->first_frame = 1; - handle->raw=0; - - pi_log(E_DBG,"opening %s\n",file); - - if(strcasecmp(codec,"flac") == 0) { - handle->raw=1; - id=CODEC_ID_FLAC; - } - - if(handle->raw) { - handle->bits_per_sample = 16; - handle->sample_rate = 44100; - - if(pmp3->bits_per_sample) - handle->bits_per_sample = pmp3->bits_per_sample; - handle->channels = 2; - handle->samples = (uint32_t)pmp3->sample_count; - handle->sample_rate = pmp3->samplerate; - - pi_log(E_DBG,"opening file raw\n"); - handle->pCodec = avcodec_find_decoder(id); - if(!handle->pCodec) { - handle->errnum = SSC_FFMPEG_E_BADCODEC; - return FALSE; - } - - handle->pCodecCtx = avcodec_alloc_context(); - if(avcodec_open(handle->pCodecCtx,handle->pCodec) < 0) { - handle->errnum = SSC_FFMPEG_E_CODECOPEN; - return FALSE; - } - - handle->fin = fopen(file,"rb"); - - if(!handle->fin) { - pi_log(E_DBG,"could not open file\n"); - handle->errnum = SSC_FFMPEG_E_FILEOPEN; - return FALSE; - } - - /* check to see if there is an id3 tag there... if so, skip it. */ - if(fread((unsigned char *)&id3,1,sizeof(id3),handle->fin) != sizeof(id3)) { - if(ferror(handle->fin)) { - pi_log(E_LOG,"Error reading file: %s\n",file); - } else { - pi_log(E_LOG,"Short file: %s\n",file); - } - handle->errnum = SSC_FFMPEG_E_FILEOPEN; - fclose(handle->fin); - return FALSE; - - } - - if(strncmp((char *)id3.id,"ID3",3)==0) { - /* found an ID3 header... */ - pi_log(E_DBG,"Found ID3 header\n"); - size = (id3.size[0] << 21 | id3.size[1] << 14 | - id3.size[2] << 7 | id3.size[3]); - fseek(handle->fin,size + sizeof(SCAN_ID3HEADER),SEEK_SET); - pi_log(E_DBG,"Header length: %d\n",size); - } else { - fseek(handle->fin,0,SEEK_SET); - } - - return TRUE; - } - - pi_log(E_DBG,"opening file with format\n"); - if(av_open_input_file(&handle->pFmtCtx,file,handle->pFormat,0,NULL) < 0) { - handle->errnum = SSC_FFMPEG_E_FILEOPEN; - return FALSE; - } - - /* find the streams */ - if(av_find_stream_info(handle->pFmtCtx) < 0) { - handle->errnum = SSC_FFMPEG_E_NOSTREAM; - return FALSE; - } - - // dump_format(handle->pFmtCtx,0,file,FALSE); - - handle->audio_stream = -1; - for(i=0; i < handle->pFmtCtx->nb_streams; i++) { - if(handle->pFmtCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) { - handle->audio_stream = i; - break; - } - } - - if(handle->audio_stream == -1) { - handle->errnum = SSC_FFMPEG_E_NOAUDIO; - return FALSE; - } - - handle->pCodecCtx = handle->pFmtCtx->streams[handle->audio_stream]->codec; - - handle->pCodec = avcodec_find_decoder(handle->pCodecCtx->codec_id); - if(!handle->pCodec) { - handle->errnum = SSC_FFMPEG_E_BADCODEC; - return FALSE; - } - - if(handle->pCodec->capabilities & CODEC_CAP_TRUNCATED) - handle->pCodecCtx->flags |= CODEC_FLAG_TRUNCATED; - - if(avcodec_open(handle->pCodecCtx, handle->pCodec) < 0) { - handle->errnum = SSC_FFMPEG_E_CODECOPEN; - return FALSE; - } - - handle->pFrame = avcodec_alloc_frame(); - - return TRUE; -} - -int ssc_ffmpeg_close(void *vp) { - SSCHANDLE *handle = (SSCHANDLE *)vp; - - if(!handle) - return TRUE; - - if(handle->fin) - fclose(handle->fin); - - if(handle->pFrame) - av_free(handle->pFrame); - - if(handle->raw) { - if(handle->pCodecCtx) - avcodec_close(handle->pCodecCtx); - } - - if(handle->pFmtCtx) - av_close_input_file(handle->pFmtCtx); - - memset(handle,0,sizeof(SSCHANDLE)); - return TRUE; -} - - -int _ssc_ffmpeg_read_frame(void *vp, char *buffer, int buflen) { - SSCHANDLE *handle = (SSCHANDLE *)vp; - int data_size; - int len1; - int out_size; - - if(handle->raw) { - while(1) { - if(!handle->file_bytes_read) { - /* need to grab a new chunk */ - handle->file_buffer_ptr = handle->file_buffer; - handle->file_bytes_read = (int)fread(handle->file_buffer, - 1, sizeof(handle->file_buffer), - handle->fin); - handle->file_buffer_ptr = handle->file_buffer; - } - - if(!handle->file_bytes_read) - return 0; - - out_size = buflen; - len1 = avcodec_decode_audio2(handle->pCodecCtx,(short*)buffer, - &out_size, - (uint8_t*)handle->file_buffer_ptr, - handle->file_bytes_read); - - if(len1 < 0) /* FIXME: Decode Error */ - return 0; - - handle->file_bytes_read -= len1; - handle->file_buffer_ptr += len1; - - if(out_size > 0) { - return out_size; - } - } - } - - - if(handle->first_frame) { - handle->first_frame = 0; - handle->packet.data = NULL; - } - - while(1) { - while(handle->packet_size > 0) { - data_size = buflen; - len1=avcodec_decode_audio2(handle->pCodecCtx, - (int16_t*)buffer, - &data_size, - handle->packet_data, - handle->packet_size); - - if(len1 < 0) { - /* skip frame */ - handle->packet_size=0; - break; - } - - handle->packet_data += len1; - handle->packet_size -= len1; - - if(data_size <= 0) - continue; - - handle->total_decoded += data_size; - return data_size; - } - - do { - if(handle->packet.data) - av_free_packet(&handle->packet); - - if(av_read_packet(handle->pFmtCtx, &handle->packet) < 0) - return -1; - } while(handle->packet.stream_index != handle->audio_stream); - - handle->packet_size = handle->packet.size; - handle->packet_data = handle->packet.data; - } -} - -void _ssc_ffmpeg_swab(char *buffer, int bytes_returned) { - int blocks = bytes_returned / 2; - int index; - char tmp; - - for(index = 0; index < blocks; index++) { - tmp = buffer[index*2]; - buffer[index*2] = buffer[index*2 + 1]; - buffer[index*2 + 1] = tmp; - } -} - -void _ssc_ffmpeg_le32(char *dst, int value) { - dst[0] = value & 0xFF; - dst[1] = (value >> 8) & 0xFF; - dst[2] = (value >> 16) & 0xFF; - dst[3] = (value >> 24) & 0xFF; -} - -void _ssc_ffmpeg_le16(char *dst, int value) { - dst[0] = value & 0xFF; - dst[1] = (value >> 8) & 0xFF; -} - -int ssc_ffmpeg_read(void *vp, char *buffer, int len) { - SSCHANDLE *handle = (SSCHANDLE *)vp; - int bytes_returned = 0; - int bytes_to_copy; - int size; - - int channels; - int sample_rate; - int bits_per_sample; - int byte_rate; - int duration = 180000; /* in ms -- 3 min */ - int data_len; - int block_align; - uint16_t test1 = 0xaabb; - char test2[2] = { 0xaa, 0xbb }; - - /* if we have not yet sent the header, let's do that first */ - if(handle->wav_offset != sizeof(handle->wav_header)) { - /* still have some to send */ - if(!handle->wav_offset) { - /* generate the wav header */ - if(handle->raw) { - channels = handle->channels; - sample_rate = handle->sample_rate; - bits_per_sample = handle->bits_per_sample; - } else { - channels = handle->pCodecCtx->channels; - sample_rate = handle->pCodecCtx->sample_rate; - switch(handle->pCodecCtx->sample_fmt) { - case SAMPLE_FMT_S16: - bits_per_sample = 16; - break; - case SAMPLE_FMT_S32: - /* BROKEN */ - bits_per_sample = 32; - break; - default: - bits_per_sample = 16; - break; - } - } - - handle->swab = (bits_per_sample == 16) && - (memcmp((void*)&test1,test2,2) == 0); - - if(handle->duration) - duration = handle->duration; - - if(handle->samples) { - data_len = ((bits_per_sample * channels / 8) * handle->samples); - } else { - data_len = ((bits_per_sample * sample_rate * channels / 8) * (duration/1000)); - } - - byte_rate = sample_rate * channels * bits_per_sample / 8; - block_align = channels * bits_per_sample / 8; - - pi_log(E_DBG,"Channels.......: %d\n",channels); - pi_log(E_DBG,"Sample rate....: %d\n",sample_rate); - pi_log(E_DBG,"Bits/Sample....: %d\n",bits_per_sample); - pi_log(E_DBG,"Swab...........: %d\n",handle->swab); - - memcpy(&handle->wav_header[0],"RIFF",4); - _ssc_ffmpeg_le32(&handle->wav_header[4],36 + data_len); - memcpy(&handle->wav_header[8],"WAVE",4); - memcpy(&handle->wav_header[12],"fmt ",4); - _ssc_ffmpeg_le32(&handle->wav_header[16],16); - _ssc_ffmpeg_le16(&handle->wav_header[20],1); - _ssc_ffmpeg_le16(&handle->wav_header[22],channels); - _ssc_ffmpeg_le32(&handle->wav_header[24],sample_rate); - _ssc_ffmpeg_le32(&handle->wav_header[28],byte_rate); - _ssc_ffmpeg_le16(&handle->wav_header[32],block_align); - _ssc_ffmpeg_le16(&handle->wav_header[34],bits_per_sample); - memcpy(&handle->wav_header[36],"data",4); - _ssc_ffmpeg_le32(&handle->wav_header[40],data_len); - } - - bytes_to_copy = sizeof(handle->wav_header) - handle->wav_offset; - if(len < bytes_to_copy) - bytes_to_copy = len; - - memcpy(buffer,&handle->wav_header[handle->wav_offset],bytes_to_copy); - handle->wav_offset += bytes_to_copy; - return bytes_to_copy; - } - - /* could test for good len here */ - - /* otherwise, start pumping out data */ - if(handle->buf_remainder_len) { - /* dump remainder into the buffer */ - bytes_to_copy = handle->buf_remainder_len; - if(handle->buf_remainder_len > len) { - bytes_to_copy = len; - } - - memcpy(buffer,handle->buf_remainder,bytes_to_copy); - bytes_returned = bytes_to_copy; - handle->buf_remainder_len -= bytes_to_copy; - if(handle->buf_remainder_len) { - handle->buf_remainder += bytes_returned; - } - } - - /* keep reading until we have filled the output buffer */ - while(bytes_returned < len) { - size = _ssc_ffmpeg_read_frame(handle,handle->buffer,BUFFER_SIZE); - if(size == 0) { - /* oops, we're done */ - if(handle->swab) - _ssc_ffmpeg_swab(buffer,bytes_returned); - return bytes_returned; - } - - if(size < 0) { - return 0; - } - - bytes_to_copy = len - bytes_returned; - if(size < bytes_to_copy) - bytes_to_copy = size; - - memcpy(buffer + bytes_returned, handle->buffer, bytes_to_copy); - bytes_returned += bytes_to_copy; - - if(size > bytes_to_copy) { - handle->buf_remainder = handle->buffer + bytes_to_copy; - handle->buf_remainder_len = size - bytes_to_copy; - } - - } - - if(handle->swab) - _ssc_ffmpeg_swab(buffer,bytes_returned); - - return bytes_returned; -}