diff -Naur main/configure main.flac/configure --- main/configure 2003-08-31 21:03:39.000000000 +0400 +++ main.flac/configure 2003-08-31 21:02:46.000000000 +0400 @@ -196,6 +196,7 @@ --disable-libdv disable libdv 0.9.5 en/decoding support [autodetect] --disable-mad disable libmad (mpeg audio) support [autodetect] --enable-xmms build with XMMS inputplugin support [disabled] + --enable-flac build with FLAC support [autodetect] Video output: --disable-vidix disable VIDIX stuff [enable on x86 *nix] @@ -1078,6 +1079,7 @@ _tremor=no _faad=auto _xmms=no +_flac=auto _css=auto # dvdnav disabled, it does not work #_dvdnav=no @@ -1240,6 +1242,8 @@ --enable-faad) _faad=yes ;; --disable-faad) _faad=no ;; --enable-xmms) _xmms=yes ;; + --enable-flac) _flac=yes ;; + --disable-flac) _flac=no ;; --enable-css) _css=yes ;; --disable-css) _css=no ;; --enable-dvdread) _dvdread=yes ;; @@ -5094,6 +5098,34 @@ fi echores "$_xmms" +echocheck "FLAC support" +if test "$_flac" = auto ; then + cat > $TMPC << EOF +#include +#include +#include + +int main() +{ + FLAC__StreamDecoder *fdec = FLAC__stream_decoder_new(); + return fdec != NULL; +} +EOF + _flac=no + if cc_check -lFLAC ; then + _flac=yes + fi +fi + +if test "$_flac" = yes ; then + _def_flac='#define HAVE_FLAC 1' + _ld_flac='-lFLAC' + _codecmodules="flac $_codecmodules" +else + _def_flac='#undef HAVE_FLAC' + _nocodecmodules="flac $_nocodecmodules" +fi +echores "$_flac" echocheck "inet6" if test "$_inet6" = auto ; then @@ -5528,6 +5560,7 @@ XMMS_LIB = $_xmms_lib MACOSX = $_macosx MACOSX_FRAMEWORKS = $_macosx_frameworks +FLAC_LIB = $_ld_flac # --- Some stuff for autoconfigure ---- $_target_arch @@ -5746,6 +5779,11 @@ */ $_def_lircc +/* + * FLAC decoding + */ +$_def_flac + /* DeCSS support using libcss */ $_def_css diff -Naur main/etc/codecs.conf main.flac/etc/codecs.conf --- main/etc/codecs.conf 2003-07-28 00:54:56.000000000 +0400 +++ main.flac/etc/codecs.conf 2003-08-31 21:02:46.000000000 +0400 @@ -2003,3 +2003,11 @@ format 0x1104 ; SBC driver acm dll "lhacm.acm" + +audiocodec flac + info "Free Lossless Audio Codec" + status untested + comment "WIP, using libFLAC. Internal format No" + format 0x43614C66 ; fLaC with mmioFOURCC + driver flac + dll "libFLAC" diff -Naur main/libmpcodecs/ad.c main.flac/libmpcodecs/ad.c --- main/libmpcodecs/ad.c 2003-06-09 00:27:25.000000000 +0400 +++ main.flac/libmpcodecs/ad.c 2003-08-31 21:02:46.000000000 +0400 @@ -39,6 +39,7 @@ extern ad_functions_t mpcodecs_ad_libdv; extern ad_functions_t mpcodecs_ad_qtaudio; extern ad_functions_t mpcodecs_ad_ra1428; +extern ad_functions_t mpcodecs_ad_flac; ad_functions_t* mpcodecs_ad_drivers[] = { @@ -87,5 +88,6 @@ &mpcodecs_ad_libdv, #endif &mpcodecs_ad_ra1428, + &mpcodecs_ad_flac, NULL }; diff -Naur main/libmpcodecs/ad_flac.c main.flac/libmpcodecs/ad_flac.c --- main/libmpcodecs/ad_flac.c 1970-01-01 03:00:00.000000000 +0300 +++ main.flac/libmpcodecs/ad_flac.c 2003-08-31 21:02:46.000000000 +0400 @@ -0,0 +1,379 @@ + +#include +#include +#include + +#include "config.h" +#ifdef HAVE_FLAC +#include "ad_internal.h" +#include "mp_msg.h" + +static ad_info_t info = { + "FLAC audio decoder", // name of the driver + "flac", // driver name. should be the same as filename without ad_ + "Dmitry Baryshkov", // writer/maintainer of _this_ file + "http://flac.sf.net/", // writer/maintainer/site of the _codec_ + "uses libFLAC" // comments +}; + +LIBAD_EXTERN(flac) + +#include "FLAC/stream_decoder.h" + +typedef struct flac_struct_st +{ + FLAC__StreamDecoder *flac_dec; /*decoder handle*/ + sh_audio_t *sh; + + /* set this fields before calling FLAC__stream_decoder_process_single*/ + unsigned char *buf; + int minlen; + int maxlen; + /*Here goes number written at write_callback*/ + int written; +} flac_struct_t; + +FLAC__StreamDecoderReadStatus flac_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + int b = demux_read_data(((flac_struct_t*)client_data)->sh->ds, buffer, *bytes); + fprintf(stdout, "\nread %d bytes\n", b); + *bytes = b; + if (b <= 0) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} + +/*FIXME: we need to support format conversion:(flac specs allow bits/sample to be from 4 to 32. Not only 8 and 16 !!!)*/ +FLAC__StreamDecoderWriteStatus flac_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + int channel, sample; + FLAC__byte *buf = ((flac_struct_t*)(client_data))->buf; + int bps = ((flac_struct_t*)(client_data))->sh->samplesize; + if (buf == NULL) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "flac_write_callback called with NULL buf in context!!!\n"); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + fprintf(stdout, "\nWrite callback (%d bytes)!!!!\n", bps*frame->header.blocksize*frame->header.channels); + for (sample = 0; sample < frame->header.blocksize; sample ++) + for (channel = 0; channel < frame->header.channels; channel ++) + switch (bps) + { + case 3: + buf[bps*(sample*frame->header.channels+channel)+2] = (FLAC__byte)(buffer[channel][sample]>>16); + case 2: + buf[bps*(sample*frame->header.channels+channel)+1] = (FLAC__byte)(buffer[channel][sample]>>8); + buf[bps*(sample*frame->header.channels+channel)+0] = (FLAC__byte)(buffer[channel][sample]); + break; + case 1: + buf[bps*(sample*frame->header.channels+channel)] = buffer[channel][sample]^0x80; + break; + } + ((flac_struct_t*)(client_data))->written += bps*frame->header.blocksize*frame->header.channels; + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +void flac_meta_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) +{ + int i, j; + sh_audio_t *sh = ((flac_struct_t*)client_data)->sh; +// fprintf(stdout, "Metadata received\n"); + switch (metadata->type) + { + case FLAC__METADATA_TYPE_STREAMINFO: + fprintf(stdout, "STREAMINFO block (%u bytes):\n", metadata->length); + fprintf(stdout, "min_blocksize: %u samples\n", metadata->data.stream_info.min_blocksize); + fprintf(stdout, "max_blocksize: %u samples\n", metadata->data.stream_info.max_blocksize); + fprintf(stdout, "min_framesize: %u bytes\n", metadata->data.stream_info.min_framesize); + fprintf(stdout, "max_framesize: %u bytes\n", metadata->data.stream_info.max_framesize); + fprintf(stdout, "sample_rate: %u Hz\n", metadata->data.stream_info.sample_rate); + sh->samplerate = metadata->data.stream_info.sample_rate; + fprintf(stdout, "channels: %u\n", metadata->data.stream_info.channels); + sh->channels = metadata->data.stream_info.channels; + fprintf(stdout, "bits_per_sample: %u\n", metadata->data.stream_info.bits_per_sample); + sh->samplesize = (metadata->data.stream_info.bits_per_sample+7)/8; /*FIXME: what to pass if samplesize is e.g 4 bits/sample ????*/ + sh->sample_format=(sh->samplesize==1)?AFMT_U8:AFMT_S16_LE; // sample format, see libao2/afmt.h + /*FIXME: we need to support format conversion:(flac specs allow bits/sample to be from 4 to 32. Not only 8 and 16 !!!)*/ + sh->o_bps = metadata->data.stream_info.bits_per_sample * metadata->data.stream_info.channels * metadata->data.stream_info.sample_rate / 8; + sh->i_bps=sh->o_bps/2; // input data rate (compressed bytes per second) + // Compression rate is near 0.5 + fprintf(stdout, "total_samples: %llu\n", metadata->data.stream_info.total_samples); + fprintf(stdout, "md5sum: "); + for (i = 0; i < 16; i++) + fprintf(stdout, "%02hhx", metadata->data.stream_info.md5sum[i]); + fprintf(stdout, "\n"); + + break; + case FLAC__METADATA_TYPE_PADDING: + fprintf(stdout, "PADDING block (%u bytes)\n", metadata->length); + break; + case FLAC__METADATA_TYPE_APPLICATION: + fprintf(stdout, "APPLICATION block (%u bytes):\n", metadata->length); + fprintf(stdout, "Application id: 0x"); + for (i = 0; i < 4; i++) + fprintf(stdout, "%02hhx", metadata->data.application.id[i]); + fprintf(stdout, "\nData: \n"); + for (i = 0; i < (metadata->length-4)/8; i++) + { + for(j = 0; j < 8; j++) + fprintf(stdout, "%c", (unsigned char)metadata->data.application.data[i*8+j]<0x20?'.':metadata->data.application.data[i*8+j]); + fprintf(stdout, " | "); + for(j = 0; j < 8; j++) + fprintf(stdout, "%#02hhx ", metadata->data.application.data[i*8+j]); + fprintf(stdout, "\n"); + } + if (metadata->length-4-i*8 != 0) + { + for(j = 0; j < metadata->length-4-i*8; j++) + fprintf(stdout, "%c", (unsigned char)metadata->data.application.data[i*8+j]<0x20?'.':metadata->data.application.data[i*8+j]); + for(; j <8; j++) + fprintf(stdout, " "); + fprintf(stdout, " | "); + for(j = 0; j < metadata->length-4-i*8; j++) + fprintf(stdout, "%#02hhx ", metadata->data.application.data[i*8+j]); + fprintf(stdout, "\n"); + } + break; + case FLAC__METADATA_TYPE_SEEKTABLE: + fprintf(stdout, "SEEKTABLE block (%u bytes):\n", metadata->length); + fprintf(stdout, "%d seekpoints:\n", metadata->data.seek_table.num_points); + for (i = 0; i < metadata->data.seek_table.num_points; i++) + if (metadata->data.seek_table.points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) + fprintf(stdout, " %3d) sample_number=%llu stream_offset=%llu frame_samples=%u\n", i, + metadata->data.seek_table.points[i].sample_number, + metadata->data.seek_table.points[i].stream_offset, + metadata->data.seek_table.points[i].frame_samples); + else + fprintf(stdout, " %3d) PLACEHOLDER\n", i); + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + fprintf(stdout, "VORBISCOMMENT block (%u bytes):\n", metadata->length); + { + char entry[metadata->data.vorbis_comment.vendor_string.length+1]; + memcpy(&entry, metadata->data.vorbis_comment.vendor_string.entry, metadata->data.vorbis_comment.vendor_string.length); + entry[metadata->data.vorbis_comment.vendor_string.length] = '\0'; + fprintf(stdout, "vendor_string: %s\n", entry); + } + fprintf(stdout, "%d comment(s):\n", metadata->data.vorbis_comment.num_comments); + for (i = 0; i < metadata->data.vorbis_comment.num_comments; i++) + { + char entry[metadata->data.vorbis_comment.comments[i].length]; + memcpy(&entry, metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length); + entry[metadata->data.vorbis_comment.comments[i].length] = '\0'; + fprintf(stdout, "%s\n", entry); + } + break; + case FLAC__METADATA_TYPE_CUESHEET: + fprintf(stdout, "CUESHEET block (%u bytes):\n", metadata->length); + fprintf(stdout, "mcn: '%s'\n", metadata->data.cue_sheet.media_catalog_number); + fprintf(stdout, "lead_in: %llu\n", metadata->data.cue_sheet.lead_in); + fprintf(stdout, "is_cd: %s\n", metadata->data.cue_sheet.is_cd?"true":"false"); + fprintf(stdout, "num_tracks: %u\n", metadata->data.cue_sheet.num_tracks); + for (i = 0; i < metadata->data.cue_sheet.num_tracks; i++) + { + fprintf(stdout, "track[%d]:\n", i); + fprintf(stdout, "offset: %llu\n", metadata->data.cue_sheet.tracks[i].offset); + fprintf(stdout, "number: %hhu%s\n", metadata->data.cue_sheet.tracks[i].number, metadata->data.cue_sheet.tracks[i].number==170?"(LEAD-OUT)":""); + fprintf(stdout, "isrc: '%s'\n", metadata->data.cue_sheet.tracks[i].isrc); + fprintf(stdout, "type: %s\n", metadata->data.cue_sheet.tracks[i].type?"non-audio":"audio"); + fprintf(stdout, "pre_emphasis: %s\n", metadata->data.cue_sheet.tracks[i].pre_emphasis?"true":"false"); + fprintf(stdout, "num_indices: %hhu\n", metadata->data.cue_sheet.tracks[i].num_indices); + for (j = 0; j < metadata->data.cue_sheet.tracks[i].num_indices; j++) + { + fprintf(stdout, "index[%d]:\n", j); + fprintf(stdout, "offset:%llu\n", metadata->data.cue_sheet.tracks[i].indices[j].offset); + fprintf(stdout, "number:%hhu\n", metadata->data.cue_sheet.tracks[i].indices[j].number); + } + } + break; + default: if (metadata->type >= FLAC__METADATA_TYPE_UNDEFINED) + fprintf(stdout, "UNKNOWN block (%u bytes):\n", metadata->length); + else + fprintf(stdout, "Strange block: UNKNOWN #%d < FLAC__METADATA_TYPE_UNDEFINED (%u bytes):\n", metadata->type, metadata->length); + for (i = 0; i < (metadata->length)/8; i++) + { + for(j = 0; j < 8; j++) + fprintf(stdout, "%c", (unsigned char)metadata->data.unknown.data[i*8+j]<0x20?'.':metadata->data.unknown.data[i*8+j]); + fprintf(stdout, " | "); + for(j = 0; j < 8; j++) + fprintf(stdout, "%#02hhx ", metadata->data.unknown.data[i*8+j]); + fprintf(stdout, "\n"); + } + if (metadata->length-i*8 != 0) + { + for(j = 0; j < metadata->length-i*8; j++) + fprintf(stdout, "%c", (unsigned char)metadata->data.unknown.data[i*8+j]<0x20?'.':metadata->data.unknown.data[i*8+j]); + for(; j <8; j++) + fprintf(stdout, " "); + fprintf(stdout, " | "); + for(j = 0; j < metadata->length-i*8; j++) + fprintf(stdout, "%#02hhx ", metadata->data.unknown.data[i*8+j]); + fprintf(stdout, "\n"); + } + break; + } +} + +void flac_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error callback called (%s)!!!\n", FLAC__StreamDecoderErrorStatusString[status]); +} + +static int preinit(sh_audio_t *sh){ + // there are default values set for buffering, but you can override them: + + sh->audio_out_minsize=8*4*65535; // due to specs: we assume max 8 channels, + // 4 bytes/sample and 65535 samples/frame + // So allocating 2Mbytes buffer :) + + // minimum input buffer size (set only if you need input buffering) + // (should be the max compressed frame size) + sh->audio_in_minsize=2048; // Default: 0 (no input buffer) + + // if you set audio_in_minsize non-zero, the buffer will be allocated + // before the init() call by the core, and you can access it via + // pointer: sh->audio_in_buffer + // it will free'd after uninit(), so you don't have to use malloc/free here! + + return 1; // return values: 1=OK 0=ERROR +} + +static int init(sh_audio_t *sh_audio){ + flac_struct_t *context = (flac_struct_t*)calloc(sizeof(flac_struct_t), 1); + + sh_audio->context = context; + context->sh = sh_audio; + if (context == NULL) + { + mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "flac_init: error allocating context.\n"); + return 0; + } + + context->flac_dec = FLAC__stream_decoder_new(); + if (context->flac_dec == NULL) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "flac_init: error allocaing FLAC decoder.\n"); + return 0; + } + + if (!FLAC__stream_decoder_set_client_data(context->flac_dec, context)) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting private data for callbacks.\n"); + return 0; + } + + if (!FLAC__stream_decoder_set_read_callback(context->flac_dec, &flac_read_callback)) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting read callback.\n"); + return 0; + } + + if (!FLAC__stream_decoder_set_write_callback(context->flac_dec, &flac_write_callback)) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting write callback.\n"); + return 0; + } + + if (!FLAC__stream_decoder_set_metadata_callback(context->flac_dec, &flac_meta_callback)) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting metadata callback.\n"); + return 0; + } + + if (!FLAC__stream_decoder_set_error_callback(context->flac_dec, &flac_error_callback)) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error setting error callback.\n"); + return 0; + } + + if (!FLAC__stream_decoder_set_metadata_respond_all(context->flac_dec)) + { + mp_msg(MSGT_DECAUDIO, MSGL_ERR, "error during setting metadata_respond_all.\n"); + return 0; + } + + if (FLAC__stream_decoder_init(context->flac_dec) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) + { + fprintf(stdout, "Error initializing decoder!\n"); + exit(1); + } + + context->buf = NULL; + context->minlen = context->maxlen = 0; + + FLAC__stream_decoder_process_until_end_of_metadata(context->flac_dec); + + return 1; // return values: 1=OK 0=ERROR +} + +static void uninit(sh_audio_t *sh){ + // uninit the decoder etc... + FLAC__stream_decoder_finish(((flac_struct_t*)(sh->context))->flac_dec); + FLAC__stream_decoder_delete(((flac_struct_t*)(sh->context))->flac_dec); + // again: you don't have to free() a_in_buffer here! it's done by the core. +} + +static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen){ + FLAC__StreamDecoderState decstate; + FLAC__bool status; + + // audio decoding. the most important thing :) + // parameters you get: + // buf = pointer to the output buffer, you have to store uncompressed + // samples there + // minlen = requested minimum size (in bytes!) of output. it's just a + // _recommendation_, you can decode more or less, it just tell you that + // the caller process needs 'minlen' bytes. if it gets less, it will + // call decode_audio() again. + // maxlen = maximum size (bytes) of output. you MUST NOT write more to the + // buffer, it's the upper-most limit! + // note: maxlen will be always greater or equal to sh->audio_out_minsize + +// Store params in private context for callback: + ((flac_struct_t*)(sh_audio->context))->buf = buf; + ((flac_struct_t*)(sh_audio->context))->minlen = minlen; + ((flac_struct_t*)(sh_audio->context))->maxlen = maxlen; + ((flac_struct_t*)(sh_audio->context))->written = 0; + + status = FLAC__stream_decoder_process_single(((flac_struct_t*)(sh_audio->context))->flac_dec); + decstate = FLAC__stream_decoder_get_state(((flac_struct_t*)(sh_audio->context))->flac_dec); + if (!status || ( + decstate != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && + decstate != FLAC__STREAM_DECODER_READ_METADATA && + decstate != FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC && + decstate != FLAC__STREAM_DECODER_READ_FRAME + )) + { + if (decstate == FLAC__STREAM_DECODER_END_OF_STREAM) + { + fprintf(stdout, "End of stream. exiting.\n"); + return -1; + } + fprintf(stdout, "process_single problem: returned %s, state is %s!\n", status?"true":"false", FLAC__StreamDecoderStateString[decstate]); + return -1; + } + + + return ((flac_struct_t*)(sh_audio->context))->written; // return value: number of _bytes_ written to output buffer, + // or -1 for EOF (or uncorrectable error) +} + +static int control(sh_audio_t *sh,int cmd,void* arg, ...){ + // various optional functions you MAY implement: +/* switch(cmd){ + case ADCTRL_RESYNC_STREAM: + // it is called once after seeking, to resync. + // Note: sh_audio->a_in_buffer_len=0; is done _before_ this call! +// ... + return CONTROL_TRUE; + case ADCTRL_SKIP_FRAME: + // it is called to skip (jump over) small amount (1/10 sec or 1 frame) + // of audio data - used to sync audio to video after seeking + // if you don't return CONTROL_TRUE, it will defaults to: + // ds_fill_buffer(sh_audio->ds); // skip 1 demux packet +// ... + return CONTROL_TRUE; + }*/ + return CONTROL_UNKNOWN; +} +#endif diff -Naur main/libmpcodecs/Makefile main.flac/libmpcodecs/Makefile --- main/libmpcodecs/Makefile 2003-08-18 19:24:08.000000000 +0400 +++ main.flac/libmpcodecs/Makefile 2003-08-31 21:02:46.000000000 +0400 @@ -6,7 +6,7 @@ AUDIO_SRCS_LIB=ad_liba52.c ad_hwac3.c ad_mp3lib.c AUDIO_SRCS_NAT=ad_alaw.c ad_dk3adpcm.c ad_pcm.c ad_dvdpcm.c ad_imaadpcm.c ad_msadpcm.c ad_msgsm.c ad_roqaudio.c ad_ra1428.c -AUDIO_SRCS_OPT=ad_acm.c ad_dshow.c ad_dmo.c ad_qtaudio.c ad_ffmpeg.c ad_faad.c ad_libvorbis.c ad_libmad.c ad_realaud.c ad_libdv.c +AUDIO_SRCS_OPT=ad_acm.c ad_dshow.c ad_dmo.c ad_qtaudio.c ad_ffmpeg.c ad_faad.c ad_libvorbis.c ad_libmad.c ad_realaud.c ad_libdv.c ad_flac.c AUDIO_SRCS=dec_audio.c ad.c $(AUDIO_SRCS_LIB) $(AUDIO_SRCS_NAT) $(AUDIO_SRCS_OPT) VIDEO_SRCS_LIB=vd_libmpeg2.c vd_nuv.c vd_lzo.c diff -Naur main/libmpdemux/demux_audio.c main.flac/libmpdemux/demux_audio.c --- main/libmpdemux/demux_audio.c 2003-06-04 14:52:58.000000000 +0400 +++ main.flac/libmpdemux/demux_audio.c 2003-08-31 21:02:46.000000000 +0400 @@ -17,6 +17,7 @@ #define MP3 1 #define WAV 2 +#define fLaC 3 #define HDR_SIZE 4 @@ -79,6 +80,10 @@ } else if((n = mp_get_mp3_header(hdr,&mp3_chans,&mp3_freq)) > 0) { frmt = MP3; break; + } else if( hdr[0] == 'f' && hdr[1] == 'L' && hdr[2] == 'a' && hdr[3] == 'C' ) { + frmt = fLaC; + stream_skip(s,-4); + break; } // Add here some other audio format detection if(step < HDR_SIZE) @@ -202,6 +207,11 @@ demuxer->movi_end = s->end_pos; // printf("wav: %X .. %X\n",(int)demuxer->movi_start,(int)demuxer->movi_end); } break; + case fLaC: + sh_audio->format = mmioFOURCC('f', 'L', 'a', 'C'); + demuxer->movi_start = stream_tell(s); + demuxer->movi_end = s->end_pos; + break; } priv = (da_priv_t*)malloc(sizeof(da_priv_t)); @@ -271,6 +281,16 @@ ds_add_packet(ds,dp); return 1; } + case fLaC: + { + int l = 32768; + demux_packet_t* dp = new_demux_packet(l); + stream_read(s,dp->buffer,l); + priv->last_pts = priv->last_pts < 0 ? 0 : priv->last_pts + l/(float)sh_audio->i_bps; + ds->pts = priv->last_pts - (ds_tell_pts(demux->audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps; + ds_add_packet(ds,dp); + return 1; + } default: printf("Audio demuxer : unknown format %d\n",priv->frmt); } diff -Naur main/libmpdemux/demux_ogg.c main.flac/libmpdemux/demux_ogg.c --- main/libmpdemux/demux_ogg.c 2003-08-18 17:13:26.000000000 +0400 +++ main.flac/libmpdemux/demux_ogg.c 2003-08-31 21:02:46.000000000 +0400 @@ -112,6 +112,7 @@ int hdr_packets; int vorbis; int theora; + int flac; } ogg_stream_t; typedef struct ogg_demuxer { @@ -359,6 +360,11 @@ } } #endif /* HAVE_OGGTHEORA */ +# ifdef HAVE_FLAC + } else if (os->flac) { + /* we pass complete packets to flac, mustn't strip the header! */ + data = pack->packet; +#endif /* HAVE_FLAC */ } else { // Find data start int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6; @@ -676,6 +682,16 @@ if(verbose>0) print_video_header(sh_v->bih); } # endif /* HAVE_OGGTHEORA */ +# ifdef HAVE_FLAC + } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) { + sh_a = new_sh_audio(demuxer,ogg_d->num_sub); + sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); + n_audio++; + ogg_d->subs[ogg_d->num_sub].flac = 1; + sh_a->wf = NULL; + mp_msg(MSGT_DEMUX,MSGL_V,"OGG : stream %d is FLAC\n",ogg_d->num_sub); +# endif /* HAVE_FLAC */ + /// Check for old header } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) { diff -Naur main/Makefile main.flac/Makefile --- main/Makefile 2003-08-18 00:56:10.000000000 +0400 +++ main.flac/Makefile 2003-08-31 21:02:46.000000000 +0400 @@ -35,7 +35,7 @@ VO_LIBS = $(AA_LIB) $(X_LIB) $(SDL_LIB) $(GGI_LIB) $(MP1E_LIB) $(MLIB_LIB) $(SVGA_LIB) $(DIRECTFB_LIB) AO_LIBS = $(ARTS_LIB) $(ESD_LIB) $(NAS_LIB) $(SGIAUDIO_LIB) -CODEC_LIBS = $(AV_LIB) $(FAME_LIB) $(MAD_LIB) $(VORBIS_LIB) $(THEORA_LIB) $(FAAD_LIB) $(LIBLZO_LIB) $(DECORE_LIB) $(XVID_LIB) $(PNG_LIB) $(Z_LIB) $(JPEG_LIB) $(ALSA_LIB) $(XMMS_LIB) $(MATROSKA_LIB) +CODEC_LIBS = $(AV_LIB) $(FAME_LIB) $(MAD_LIB) $(VORBIS_LIB) $(THEORA_LIB) $(FAAD_LIB) $(LIBLZO_LIB) $(DECORE_LIB) $(XVID_LIB) $(PNG_LIB) $(Z_LIB) $(JPEG_LIB) $(ALSA_LIB) $(XMMS_LIB) $(MATROSKA_LIB) $(FLAC_LIB) COMMON_LIBS = libmpcodecs/libmpcodecs.a mp3lib/libMP3.a liba52/liba52.a libmpeg2/libmpeg2.a $(W32_LIB) $(DS_LIB) libaf/libaf.a libmpdemux/libmpdemux.a input/libinput.a postproc/libswscale.a osdep/libosdep.a $(CSS_LIB) $(CODEC_LIBS) $(FREETYPE_LIB) $(TERMCAP_LIB) $(CDPARANOIA_LIB) $(MPLAYER_NETWORK_LIB) $(WIN32_LIB) $(GIF_LIB) $(MACOSX_FRAMEWORKS) $(SMBSUPPORT_LIB) $(FRIBIDI_LIB) CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader -Ilibvo $(FREETYPE_INC) $(EXTRA_INC) $(CDPARANOIA_INC) $(SDL_INC) $(X11_INC) $(FRIBIDI_INC) $(DVB_INC) # -Wall