Update help output with previous --extra-ldflags change.
[mplayer/glamo.git] / libmpdemux / demux_mpc.c
blobb4e244f2de78f2a6e106a650334c7bf8b509c56d
1 /**
2 * Demuxer for Musepack v7 bitstream
3 * by Reimar Doeffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de>
4 * This code may be be relicensed under the terms of the GNU LGPL when it
5 * becomes part of the FFmpeg project (ffmpeg.org)
6 */
8 #include "config.h"
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include "mp_msg.h"
14 #include "libavutil/common.h"
15 #include "mpbswap.h"
16 #include "stream/stream.h"
17 #include "demuxer.h"
18 #include "stheader.h"
21 #define HDR_SIZE (6 * 4)
23 typedef struct da_priv {
24 float last_pts;
25 float pts_per_packet;
26 uint32_t dword;
27 int pos;
28 float length;
29 } da_priv_t;
31 static uint32_t get_bits(da_priv_t* priv, stream_t* s, int bits) {
32 uint32_t out = priv->dword;
33 uint32_t mask = (1 << bits) - 1;
34 priv->pos += bits;
35 if (priv->pos < 32) {
36 out >>= (32 - priv->pos);
38 else {
39 stream_read(s, (void *)&priv->dword, 4);
40 priv->dword = le2me_32(priv->dword);
41 priv->pos -= 32;
42 if (priv->pos) {
43 out <<= priv->pos;
44 out |= priv->dword >> (32 - priv->pos);
47 return out & mask;
50 static int demux_mpc_check(demuxer_t* demuxer) {
51 stream_t *s = demuxer->stream;
52 uint8_t hdr[HDR_SIZE];
53 int i;
55 if (stream_read(s, hdr, HDR_SIZE) != HDR_SIZE)
56 return 0;
57 for (i = 0; i < 30000 && !s->eof; i++) {
58 if (hdr[0] == 'M' && hdr[1] == 'P' && hdr[2] == '+')
59 break;
60 memmove(hdr, &hdr[1], HDR_SIZE - 1);
61 stream_read(s, &hdr[HDR_SIZE - 1], 1);
64 if (hdr[0] != 'M' || hdr[1] != 'P' || hdr[2] != '+')
65 return 0;
66 demuxer->movi_start = stream_tell(s) - HDR_SIZE;
67 demuxer->movi_end = s->end_pos;
68 demuxer->priv = malloc(HDR_SIZE);
69 memcpy(demuxer->priv, hdr, HDR_SIZE);
70 return DEMUXER_TYPE_MPC;
73 static demuxer_t *demux_mpc_open(demuxer_t* demuxer) {
74 float seconds = 0;
75 stream_t *s = demuxer->stream;
76 sh_audio_t* sh_audio;
77 da_priv_t* priv = demuxer->priv;
79 sh_audio = new_sh_audio(demuxer,0);
82 char *wf = calloc(1, sizeof(WAVEFORMATEX) + HDR_SIZE);
83 char *header = &wf[sizeof(WAVEFORMATEX)];
84 const int freqs[4] = {44100, 48000, 37800, 32000};
85 int frames;
86 sh_audio->format = mmioFOURCC('M', 'P', 'C', ' ');
87 memcpy(header, priv, HDR_SIZE);
88 free(priv);
89 frames = header[4] | header[5] << 8 | header[6] << 16 | header[7] << 24;
90 sh_audio->wf = (WAVEFORMATEX *)wf;
91 sh_audio->wf->wFormatTag = sh_audio->format;
92 sh_audio->wf->nChannels = 2;
93 sh_audio->wf->nSamplesPerSec = freqs[header[10] & 3];
94 sh_audio->wf->nBlockAlign = 32 * 36;
95 sh_audio->wf->wBitsPerSample = 16;
96 seconds = 1152 * frames / (float)sh_audio->wf->nSamplesPerSec;
97 if (demuxer->movi_end > demuxer->movi_start && seconds > 1)
98 sh_audio->wf->nAvgBytesPerSec = (demuxer->movi_end - demuxer->movi_start) / seconds;
99 else
100 sh_audio->wf->nAvgBytesPerSec = 32 * 1024; // dummy to make mencoder not hang
101 sh_audio->wf->cbSize = HDR_SIZE;
102 demuxer->movi_start = stream_tell(s);
103 demuxer->movi_end = s->end_pos;
106 priv = malloc(sizeof(da_priv_t));
107 priv->last_pts = -1;
108 priv->pts_per_packet = (32 * 36) / (float)sh_audio->wf->nSamplesPerSec;
109 priv->length = seconds;
110 priv->dword = 0;
111 priv->pos = 32; // empty bit buffer
112 get_bits(priv, s, 8); // discard first 8 bits
113 demuxer->priv = priv;
114 demuxer->audio->id = 0;
115 demuxer->audio->sh = sh_audio;
116 sh_audio->ds = demuxer->audio;
117 sh_audio->samplerate = sh_audio->wf->nSamplesPerSec;
118 sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;
119 sh_audio->audio.dwSampleSize = 0;
120 sh_audio->audio.dwScale = 32 * 36;
121 sh_audio->audio.dwRate = sh_audio->samplerate;
123 return demuxer;
126 static int demux_mpc_fill_buffer(demuxer_t *demux, demux_stream_t *ds) {
127 int l;
128 int bit_len;
129 demux_packet_t* dp;
130 sh_audio_t* sh_audio = ds->sh;
131 da_priv_t* priv = demux->priv;
132 stream_t* s = demux->stream;
133 sh_audio = ds->sh;
135 if (s->eof)
136 return 0;
138 bit_len = get_bits(priv, s, 20);
139 dp = new_demux_packet((bit_len + 7) / 8);
140 for (l = 0; l < (bit_len / 8); l++)
141 dp->buffer[l] = get_bits(priv, s, 8);
142 bit_len %= 8;
143 if (bit_len)
144 dp->buffer[l] = get_bits(priv, s, bit_len) << (8 - bit_len);
145 if (priv->last_pts < 0)
146 priv->last_pts = 0;
147 else
148 priv->last_pts += priv->pts_per_packet;
149 dp->pts = priv->last_pts;
150 ds_add_packet(ds, dp);
151 return 1;
154 static void demux_mpc_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){
155 sh_audio_t* sh_audio = demuxer->audio->sh;
156 da_priv_t* priv = demuxer->priv;
157 stream_t* s = demuxer->stream;
158 float target = rel_seek_secs;
159 if (flags & SEEK_FACTOR)
160 target *= priv->length;
161 if (!(flags & SEEK_ABSOLUTE))
162 target += priv->last_pts;
163 if (target < priv->last_pts) {
164 stream_seek(s, demuxer->movi_start);
165 priv->pos = 32; // empty bit buffer
166 get_bits(priv, s, 8); // discard first 8 bits
167 priv->last_pts = 0;
169 while (target > priv->last_pts) {
170 int bit_len = get_bits(priv, s, 20);
171 if (bit_len > 32) {
172 stream_skip(s, bit_len / 32 * 4 - 4);
173 get_bits(priv, s, 32); // make sure dword is reloaded
175 get_bits(priv, s, bit_len % 32);
176 priv->last_pts += priv->pts_per_packet;
177 if (s->eof) break;
179 if (!sh_audio) return;
182 static void demux_close_mpc(demuxer_t* demuxer) {
183 da_priv_t* priv = demuxer->priv;
185 if(!priv)
186 return;
187 free(priv);
190 static int demux_mpc_control(demuxer_t *demuxer,int cmd, void *arg){
191 da_priv_t* priv = demuxer->priv;
192 switch (cmd) {
193 case DEMUXER_CTRL_GET_TIME_LENGTH:
194 if (priv->length < 1) return DEMUXER_CTRL_DONTKNOW;
195 *((double *)arg) = priv->length;
196 return DEMUXER_CTRL_OK;
197 case DEMUXER_CTRL_GET_PERCENT_POS:
198 if (priv->length < 1) return DEMUXER_CTRL_DONTKNOW;
199 *((int *)arg) = priv->last_pts * 100 / priv->length;
200 return DEMUXER_CTRL_OK;
202 return DEMUXER_CTRL_NOTIMPL;
206 const demuxer_desc_t demuxer_desc_mpc = {
207 "Musepack demuxer",
208 "mpc",
209 "MPC",
210 "Reza Jelveh, Reimar Doeffinger",
211 "supports v7 bitstream only",
212 DEMUXER_TYPE_MPC,
213 0, // unsafe autodetect
214 demux_mpc_check,
215 demux_mpc_fill_buffer,
216 demux_mpc_open,
217 demux_close_mpc,
218 demux_mpc_seek,
219 demux_mpc_control