diff options
author | reimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2005-07-10 17:14:12 +0000 |
---|---|---|
committer | reimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2005-07-10 17:14:12 +0000 |
commit | c54b5a06bd40fba8a37c7053cd7437785e9a7314 (patch) | |
tree | 721cc55674c56e735addc44c4b647f2627f4cb1f /libmpdemux | |
parent | cd19f28b94690a828a0304961e8b5d5721a77ea2 (diff) | |
download | mpv-c54b5a06bd40fba8a37c7053cd7437785e9a7314.tar.bz2 mpv-c54b5a06bd40fba8a37c7053cd7437785e9a7314.tar.xz |
musepack demuxing and decoding support (demuxing is v7 bitstream only).
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@15959 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/Makefile | 1 | ||||
-rw-r--r-- | libmpdemux/demux_mpc.c | 145 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 23 | ||||
-rw-r--r-- | libmpdemux/demuxer.h | 3 |
4 files changed, 171 insertions, 1 deletions
diff --git a/libmpdemux/Makefile b/libmpdemux/Makefile index d216790ec9..fc8b606b7e 100644 --- a/libmpdemux/Makefile +++ b/libmpdemux/Makefile @@ -69,6 +69,7 @@ SRCS += demuxer.c \ demux_lmlm4.c \ demux_mf.c \ demux_mov.c \ + demux_mpc.c \ demux_mpg.c \ demux_nsv.c \ demux_nuv.c \ diff --git a/libmpdemux/demux_mpc.c b/libmpdemux/demux_mpc.c new file mode 100644 index 0000000000..b422073841 --- /dev/null +++ b/libmpdemux/demux_mpc.c @@ -0,0 +1,145 @@ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "mp_msg.h" +#include "bswap.h" +#include "stream.h" +#include "demuxer.h" +#include "stheader.h" + + +#define HDR_SIZE (6 * 4) + +typedef struct da_priv { + float last_pts; + uint32_t dword; + int pos; +} da_priv_t; + +extern void free_sh_audio(sh_audio_t* sh); + +static uint32_t get_bits(da_priv_t* priv, stream_t* s, int bits) { + uint32_t out = priv->dword; + uint32_t mask = (1 << bits) - 1; + priv->pos += bits; + if (priv->pos < 32) { + out >>= (32 - priv->pos); + } + else { + stream_read(s, (void *)&priv->dword, 4); + le2me_32(priv->dword); + priv->pos -= 32; + if (priv->pos) { + out <<= priv->pos; + out |= priv->dword >> (32 - priv->pos); + } + } + return out & mask; +} + +int demux_mpc_open(demuxer_t* demuxer) { + stream_t *s = demuxer->stream; + sh_audio_t* sh_audio; + uint8_t hdr[HDR_SIZE]; + da_priv_t* priv; + int i; + + if (stream_read(s, hdr, HDR_SIZE) != HDR_SIZE) + return 0; + for (i = 0; i < 30000 && !s->eof; i++) { + if (hdr[0] == 'M' && hdr[1] == 'P' && hdr[2] == '+') + break; + memmove(hdr, &hdr[1], HDR_SIZE - 1); + stream_read(s, &hdr[HDR_SIZE - 1], 1); + } + + if (hdr[0] != 'M' || hdr[1] != 'P' || hdr[2] != '+') + return 0; + + sh_audio = new_sh_audio(demuxer,0); + + { + char *wf = (char *)calloc(1, sizeof(WAVEFORMATEX) + HDR_SIZE); + char *header = &wf[sizeof(WAVEFORMATEX)]; + const int freqs[4] = {44100, 48000, 37800, 32000}; + sh_audio->format = mmioFOURCC('M', 'P', 'C', ' '); + memcpy(header, hdr, HDR_SIZE); + sh_audio->wf = (WAVEFORMATEX *)wf; + sh_audio->wf->wFormatTag = sh_audio->format; + sh_audio->wf->nChannels = 2; + sh_audio->wf->nSamplesPerSec = freqs[header[10] & 3]; + sh_audio->wf->nBlockAlign = 32 * 36; + sh_audio->wf->wBitsPerSample = 16; + sh_audio->wf->nAvgBytesPerSec = 128 * 1024; // dummy to make mencoder not hang + sh_audio->wf->cbSize = HDR_SIZE; + demuxer->movi_start = stream_tell(s); + demuxer->movi_end = s->end_pos; + } + + priv = (da_priv_t *)malloc(sizeof(da_priv_t)); + priv->last_pts = -1; + priv->dword = 0; + priv->pos = 0; + stream_read(s, (void *)&priv->dword, 4); + priv->pos = 8; + demuxer->priv = priv; + demuxer->audio->id = 0; + demuxer->audio->sh = sh_audio; + sh_audio->ds = demuxer->audio; + sh_audio->samplerate = sh_audio->wf->nSamplesPerSec; + sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec; + sh_audio->audio.dwSampleSize = 0; + sh_audio->audio.dwScale = 32 * 36; + sh_audio->audio.dwRate = sh_audio->samplerate; + + return 1; +} + +int demux_mpc_fill_buffer(demux_stream_t *ds) { + int l; + int bit_len; + demux_packet_t* dp; + sh_audio_t* sh_audio = ds->sh; + demuxer_t* demux = ds->demuxer; + da_priv_t* priv = demux->priv; + stream_t* s = demux->stream; + sh_audio = ds->sh; + + if (s->eof) + return 0; + + bit_len = get_bits(priv, s, 20); + dp = new_demux_packet((bit_len + 7) / 8); + for (l = 0; l < (bit_len / 8); l++) + dp->buffer[l] = get_bits(priv, s, 8); + bit_len %= 8; + if (bit_len) + dp->buffer[l] = get_bits(priv, s, bit_len) << (8 - bit_len); + if (priv->last_pts < 0) + priv->last_pts = 0; + else + priv->last_pts += (36 * 32) / (float)sh_audio->samplerate; + 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; +} + +void demux_mpc_seek(demuxer_t *demuxer,float rel_seek_secs,int flags){ +// TODO +} + +void demux_close_mpc(demuxer_t* demuxer) { + da_priv_t* priv = demuxer->priv; + + if(!priv) + return; + free(priv); +} + +int demux_mpc_control(demuxer_t *demuxer,int cmd, void *arg){ + return DEMUXER_CTRL_NOTIMPL; +} diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index f126dd08f0..5297c0f928 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -140,6 +140,7 @@ extern void demux_close_fli(demuxer_t* demuxer); extern void demux_close_nsv(demuxer_t* demuxer); extern void demux_close_nuv(demuxer_t* demuxer); extern void demux_close_audio(demuxer_t* demuxer); +extern void demux_close_mpc(demuxer_t* demuxer); extern void demux_close_ogg(demuxer_t* demuxer); extern void demux_close_mpg(demuxer_t* demuxer); extern void demux_close_rtp(demuxer_t* demuxer); @@ -211,6 +212,8 @@ void free_demuxer(demuxer_t *demuxer){ #endif case DEMUXER_TYPE_AUDIO: demux_close_audio(demuxer); break; + case DEMUXER_TYPE_MPC: + demux_close_mpc(demuxer); break; #ifdef HAVE_OGGVORBIS case DEMUXER_TYPE_OGG: demux_close_ogg(demuxer); break; @@ -337,6 +340,7 @@ int demux_rtp_fill_buffer(demuxer_t *demux, demux_stream_t* ds); int demux_rawdv_fill_buffer(demuxer_t *demuxer); int demux_y4m_fill_buffer(demuxer_t *demux); int demux_audio_fill_buffer(demux_stream_t *ds); +int demux_mpc_fill_buffer(demux_stream_t *ds); int demux_pva_fill_buffer(demuxer_t *demux); int demux_xmms_fill_buffer(demuxer_t *demux,demux_stream_t *ds); int demux_gif_fill_buffer(demuxer_t *demux); @@ -388,6 +392,7 @@ int demux_fill_buffer(demuxer_t *demux,demux_stream_t *ds){ #endif case DEMUXER_TYPE_Y4M: return demux_y4m_fill_buffer(demux); case DEMUXER_TYPE_AUDIO: return demux_audio_fill_buffer(ds); + case DEMUXER_TYPE_MPC: return demux_mpc_fill_buffer(ds); #ifdef HAVE_XMMS case DEMUXER_TYPE_XMMS: return demux_xmms_fill_buffer(demux,ds); #endif @@ -636,6 +641,7 @@ extern int nuv_check_file(demuxer_t *demuxer); extern void demux_open_nsv(demuxer_t *demuxer); extern void demux_open_nuv(demuxer_t *demuxer); extern int demux_audio_open(demuxer_t* demuxer); +extern int demux_mpc_open(demuxer_t* demuxer); extern int demux_ogg_open(demuxer_t* demuxer); extern int demux_mpg_open(demuxer_t* demuxer); extern int demux_rawaudio_open(demuxer_t* demuxer); @@ -1063,6 +1069,17 @@ if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_AUDIO){ demuxer = NULL; } } +//=============== Try to open as musepack file: ================= +if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_MPC){ + demuxer=new_demuxer(stream,DEMUXER_TYPE_MPC,audio_id,video_id,dvdsub_id); + if(demux_mpc_open(demuxer)){ + mp_msg(MSGT_DEMUXER,MSGL_INFO,MSGTR_Detected_XXX_FileFormat, "MPC"); + file_format=DEMUXER_TYPE_MPC; + } else { + free_demuxer(demuxer); + demuxer = NULL; + } +} #ifdef HAVE_XMMS //=============== Try to open as XMMS file: ================= if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_XMMS){ @@ -1446,6 +1463,7 @@ int demux_seek_rawdv(demuxer_t *demuxer, float pts, int flags); #endif extern void demux_audio_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); +extern void demux_mpc_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); extern void demux_demuxers_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); extern void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); extern void demux_rawaudio_seek(demuxer_t *demuxer,float rel_seek_secs,int flags); @@ -1532,6 +1550,8 @@ switch(demuxer->file_format){ demux_seek_nuv(demuxer,rel_seek_secs,flags); break; case DEMUXER_TYPE_AUDIO: demux_audio_seek(demuxer,rel_seek_secs,flags); break; + case DEMUXER_TYPE_MPC: + demux_mpc_seek(demuxer,rel_seek_secs,flags); break; case DEMUXER_TYPE_DEMUXERS: demux_demuxers_seek(demuxer,rel_seek_secs,flags); break; #ifdef HAVE_OGGVORBIS @@ -1635,6 +1655,7 @@ extern int demux_avi_control(demuxer_t *demuxer, int cmd, void *arg); extern int demux_xmms_control(demuxer_t *demuxer, int cmd, void *arg); extern int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg); extern int demux_audio_control(demuxer_t *demuxer, int cmd, void *arg); +extern int demux_mpc_control(demuxer_t *demuxer, int cmd, void *arg); extern int demux_ogg_control(demuxer_t *demuxer, int cmd, void *arg); extern int demux_real_control(demuxer_t *demuxer, int cmd, void *arg); extern int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg); @@ -1663,6 +1684,8 @@ int demux_control(demuxer_t *demuxer, int cmd, void *arg) { return demux_avi_control(demuxer,cmd,arg); case DEMUXER_TYPE_AUDIO: return demux_audio_control(demuxer,cmd,arg); + case DEMUXER_TYPE_MPC: + return demux_mpc_control(demuxer,cmd,arg); #ifdef HAVE_OGGVORBIS case DEMUXER_TYPE_OGG: return demux_ogg_control(demuxer,cmd,arg); diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index dd783f089f..de8f678178 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -47,11 +47,12 @@ #define DEMUXER_TYPE_VQF 37 #define DEMUXER_TYPE_AVS 38 #define DEMUXER_TYPE_AAC 39 +#define DEMUXER_TYPE_MPC 40 // This should always match the higest demuxer type number. // Unless you want to disallow users to force the demuxer to some types #define DEMUXER_TYPE_MIN 0 -#define DEMUXER_TYPE_MAX 39 +#define DEMUXER_TYPE_MAX 40 #define DEMUXER_TYPE_DEMUXERS (1<<16) // A virtual demuxer type for the network code |