summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authorreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-07-10 17:14:12 +0000
committerreimar <reimar@b3059339-0415-0410-9bf9-f77b7e298cf2>2005-07-10 17:14:12 +0000
commitc54b5a06bd40fba8a37c7053cd7437785e9a7314 (patch)
tree721cc55674c56e735addc44c4b647f2627f4cb1f /libmpdemux
parentcd19f28b94690a828a0304961e8b5d5721a77ea2 (diff)
downloadmpv-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/Makefile1
-rw-r--r--libmpdemux/demux_mpc.c145
-rw-r--r--libmpdemux/demuxer.c23
-rw-r--r--libmpdemux/demuxer.h3
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