mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-25 21:13:07 -04:00
Remove ssc-ffmpeg plugin
This commit is contained in:
parent
417b5e0ce3
commit
89eead66f6
@ -1,23 +1,16 @@
|
|||||||
|
|
||||||
rspdir = ${pkglibdir}/plugins
|
rspdir = ${pkglibdir}/plugins
|
||||||
out_daapdir = ${pkglibdir}/plugins
|
out_daapdir = ${pkglibdir}/plugins
|
||||||
ssc_ffmpegdir = ${pkglibdir}/plugins
|
|
||||||
|
|
||||||
rsp_LTLIBRARIES=rsp.la
|
rsp_LTLIBRARIES=rsp.la
|
||||||
rsp_la_LDFLAGS=-module -avoid-version
|
rsp_la_LDFLAGS=-module -avoid-version
|
||||||
rsp_la_SOURCES = rsp.c xml-rpc.c
|
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_LTLIBRARIES=out-daap.la
|
||||||
out_daap_la_LDFLAGS=-module -avoid-version
|
out_daap_la_LDFLAGS=-module -avoid-version
|
||||||
out_daap_la_SOURCES=out-daap.c out-daap-proto.c
|
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
|
out-daap-proto.h
|
||||||
|
|
||||||
AM_CFLAGS = -I..
|
AM_CFLAGS = -I..
|
||||||
|
@ -1,555 +0,0 @@
|
|||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user