1.1 --- a/src/demuxers/demux_mpgaudio.c Tue Sep 27 02:05:31 2005 +0000
1.2 +++ b/src/demuxers/demux_mpgaudio.c Sat Oct 01 08:03:36 2005 +0000
1.3 @@ -17,12 +17,12 @@
1.4 * along with this program; if not, write to the Free Software
1.5 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
1.6 *
1.7 - * $Id: demux_mpgaudio.c,v 1.141 2005/09/15 18:45:15 tmattern Exp $
1.8 + * $Id: demux_mpgaudio.c,v 1.142 2005/10/01 08:03:36 tmattern Exp $
1.9 *
1.10 * demultiplexer for mpeg audio (i.e. mp3) streams
1.11 *
1.12 * mp3 file structure:
1.13 - * [id3v2] [Xing] Frame1 Frame2 Frame3... [id3v1]
1.14 + * [id3v2][Xing|Vbri] Frame1 Frame2 Frame3...FrameX [Lyrics][id3v2][id3v1]
1.15 *
1.16 */
1.17
1.18 @@ -49,8 +49,11 @@
1.19 #include "group_audio.h"
1.20 #include "id3.h"
1.21
1.22 -#define NUM_PREVIEW_BUFFERS 10
1.23 -#define SNIFF_BUFFER_LENGTH 1024
1.24 +/* 2 preview buffers are enough,
1.25 + * the first mp3 frame is potentially a vbr header (xing, vbri)
1.26 + * the second mp3 frame is sent to the decoder
1.27 + */
1.28 +#define NUM_PREVIEW_BUFFERS 2
1.29
1.30 #define WRAP_THRESHOLD 120000
1.31
1.32 @@ -70,6 +73,10 @@
1.33 #define XING_VBR_SCALE_FLAG 0x0008
1.34 #define XING_TOC_LENGTH 100
1.35
1.36 +/* Xing header stuff */
1.37 +#define VBRI_TAG FOURCC_TAG('V', 'B', 'R', 'I')
1.38 +
1.39 +/* mp3 frame struct */
1.40 typedef struct {
1.41 /* header */
1.42 uint16_t frame_sync;
1.43 @@ -87,48 +94,65 @@
1.44 uint8_t original;
1.45 uint8_t emphasis;
1.46
1.47 - uint8_t version_idx;
1.48 - int bitrate;
1.49 - int samplerate;
1.50 - int length; /* in bytes */
1.51 - double duration; /* in 1/90000 s */
1.52 + uint8_t version_idx; /* 0: mpeg1, 1: mpeg2, 2: mpeg2.5 */
1.53 + int bitrate; /* in bit per second */
1.54 + int freq; /* in Hz */
1.55 + int samples; /* samples per frame */
1.56 + int padding; /* padding bytes (0, 1 or 4)*/
1.57 + int size; /* in bytes */
1.58 + double duration; /* in xine pts */
1.59 } mpg_audio_frame_t;
1.60
1.61 +/* Xing Vbr Header struct */
1.62 +typedef struct {
1.63 + uint32_t flags;
1.64 + uint32_t stream_frames;
1.65 + uint32_t stream_size;
1.66 + uint8_t toc[XING_TOC_LENGTH];
1.67 + uint32_t vbr_scale;
1.68 +} xing_header_t;
1.69
1.70 +/* Vbri Vbr Header struct */
1.71 +typedef struct {
1.72 + uint16_t version;
1.73 + uint16_t delai;
1.74 + uint16_t quality;
1.75 + uint32_t stream_size;
1.76 + uint32_t stream_frames;
1.77 + uint16_t toc_entries;
1.78 + uint16_t toc_scale_factor;
1.79 + uint16_t entry_size;
1.80 + uint16_t entry_frames;
1.81 + int *toc;
1.82 +} vbri_header_t;
1.83 +
1.84 +/* demuxer instance struct */
1.85 typedef struct {
1.86
1.87 demux_plugin_t demux_plugin;
1.88 -
1.89 xine_stream_t *stream;
1.90 -
1.91 fifo_buffer_t *audio_fifo;
1.92 -
1.93 input_plugin_t *input;
1.94 -
1.95 int status;
1.96
1.97 - int stream_length;
1.98 - int br; /* bitrate */
1.99 - int abr; /* average bitrate */
1.100 - int64_t last_pts;
1.101 - int send_newpts;
1.102 - int buf_flag_seek;
1.103 + uint32_t stream_length; /* in seconds */
1.104 + int br; /* bitrate in bits/second */
1.105 uint32_t blocksize;
1.106
1.107 mpg_audio_frame_t cur_frame;
1.108 - double cur_fpts;
1.109 - int is_vbr;
1.110 - int meta_info_flag;
1.111 + double cur_time; /* in milliseconds */
1.112
1.113 - /* Xing header */
1.114 - int check_xing;
1.115 - uint32_t xflags;
1.116 - uint32_t xframes;
1.117 - uint32_t xbytes;
1.118 - uint8_t xtoc[100];
1.119 - uint32_t xvbr_scale;
1.120 + off_t mpg_frame_start; /* offset */
1.121 + off_t mpg_frame_end; /* offset */
1.122 + off_t mpg_size; /* in bytes */
1.123 +
1.124 + int check_vbr_header;
1.125 + xing_header_t *xing_header;
1.126 + vbri_header_t *vbri_header;
1.127 +
1.128 } demux_mpgaudio_t ;
1.129
1.130 +/* demuxer class struct */
1.131 typedef struct {
1.132
1.133 demux_class_t demux_class;
1.134 @@ -139,53 +163,47 @@
1.135
1.136 } demux_mpgaudio_class_t;
1.137
1.138 -/* bitrate table tabsel_123[mpeg version][layer][bitrate index]
1.139 +/* bitrate table[mpeg version][layer][bitrate index]
1.140 * values stored in kbps
1.141 */
1.142 -const int tabsel_123[2][3][16] = {
1.143 - { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,},
1.144 - {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,},
1.145 - {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} },
1.146 -
1.147 - { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,},
1.148 - {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,},
1.149 - {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,} }
1.150 +const int mp3_bitrates[3][3][16] = {
1.151 + { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
1.152 + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
1.153 + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,} },
1.154 + { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
1.155 + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
1.156 + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,} },
1.157 + { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
1.158 + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
1.159 + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,} }
1.160 };
1.161
1.162 -static int frequencies[3][3] = {
1.163 +/* frequency table[mpeg version][frequence index] (in KHz) */
1.164 +static int mp3_freqs[3][3] = {
1.165 { 44100, 48000, 32000 },
1.166 { 22050, 24000, 16000 },
1.167 { 11025, 12000, 8000 }
1.168 };
1.169
1.170 +/* samples per frame table[mpeg version][layer] */
1.171 +static int mp3_samples[3][3] = {
1.172 + { 384, 1152, 1152 },
1.173 + { 384, 1152, 576 },
1.174 + { 384, 1152, 576 }
1.175 +};
1.176
1.177 -static int mpg123_xhead_check(char *buf)
1.178 -{
1.179 - return (BE_32(buf) == XING_TAG);
1.180 -}
1.181 +/* samples per frame table[layer][padding bit] */
1.182 +static int mp3_paddings[3][2] = {
1.183 + { 0, 4 },
1.184 + { 0, 1 },
1.185 + { 0, 1 }
1.186 +};
1.187
1.188 -static void check_newpts (demux_mpgaudio_t *this, int64_t pts) {
1.189 -
1.190 - int64_t diff;
1.191 -
1.192 - diff = pts - this->last_pts;
1.193 -
1.194 - if( pts &&
1.195 - (this->send_newpts || (this->last_pts && abs(diff)>WRAP_THRESHOLD) ) ) {
1.196 - if (this->buf_flag_seek) {
1.197 - _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK);
1.198 - this->buf_flag_seek = 0;
1.199 - } else {
1.200 - _x_demux_control_newpts(this->stream, pts, 0);
1.201 - }
1.202 - this->send_newpts = 0;
1.203 - }
1.204 -
1.205 - if( pts )
1.206 - this->last_pts = pts;
1.207 -}
1.208 -
1.209 -static int mpg123_parse_frame_header(mpg_audio_frame_t *frame, uint8_t *buf) {
1.210 +/*
1.211 + * Parse a mp3 frame
1.212 + * return 1 on success
1.213 + */
1.214 +static int parse_frame_header(mpg_audio_frame_t *frame, uint8_t *buf) {
1.215 uint32_t head;
1.216
1.217 head = BE_32(buf);
1.218 @@ -251,40 +269,47 @@
1.219 }
1.220 #endif
1.221
1.222 - frame->bitrate = tabsel_123[!frame->lsf_bit][frame->layer - 1][frame->bitrate_idx] * 1000;
1.223 - frame->samplerate = frequencies[frame->version_idx][frame->freq_idx];
1.224 - if (frame->layer == 1) {
1.225 - frame->length = (12 * frame->bitrate / frame->samplerate + frame->padding_bit) * 4;
1.226 - frame->duration = 90000.0 * 384.0 / (double)frame->samplerate;
1.227 - } else {
1.228 - int slots_per_frame;
1.229 - slots_per_frame = (frame->layer == 3 && !frame->lsf_bit) ? 72 : 144;
1.230 + frame->bitrate = mp3_bitrates[frame->version_idx][frame->layer - 1][frame->bitrate_idx] * 1000;
1.231 + frame->freq = mp3_freqs[frame->version_idx][frame->freq_idx];
1.232 + frame->samples = mp3_samples[frame->version_idx][frame->layer - 1];
1.233 + frame->padding = mp3_paddings[frame->layer - 1][frame->padding_bit];
1.234 +
1.235 + frame->size = frame->samples * (frame->bitrate / 8);
1.236 + frame->size /= frame->freq;
1.237 + frame->size += frame->padding;
1.238
1.239 - frame->length = slots_per_frame * frame->bitrate / frame->samplerate +
1.240 - frame->padding_bit;
1.241 - frame->duration = 90000.0 * slots_per_frame * 8.0 / (double)frame->samplerate;
1.242 - }
1.243 + frame->duration = 1000.0f * (double)frame->samples / (double)frame->freq;
1.244
1.245 lprintf("mpeg %d, layer %d\n", frame->version_idx + 1, frame->layer);
1.246 - lprintf("bitrate: %d bps, samplerate: %d Hz\n", frame->bitrate, frame->samplerate);
1.247 - lprintf("length: %d bytes, %f pts\n", frame->length, frame->duration);
1.248 + lprintf("bitrate: %d bps, samplerate: %d Hz\n", frame->bitrate, frame->freq);
1.249 + lprintf("length: %d bytes, %f ms\n", frame->size, frame->duration);
1.250 + lprintf("padding: %d bytes\n", frame->padding);
1.251 return 1;
1.252 }
1.253
1.254 -static int mpg123_parse_xing_header(demux_mpgaudio_t *this, uint8_t *buf, int bufsize) {
1.255 +/*
1.256 + * Parse a Xing header
1.257 + * return the Xing header or NULL on error
1.258 + */
1.259 +static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame,
1.260 + uint8_t *buf, int bufsize) {
1.261
1.262 int i;
1.263 uint8_t *ptr = buf;
1.264 - double frame_duration;
1.265 + xing_header_t *xing;
1.266 +
1.267 + xing = xine_xmalloc (sizeof (xing_header_t));
1.268 + if (!xing)
1.269 + return NULL;
1.270
1.271 /* offset of the Xing header */
1.272 - if (this->cur_frame.lsf_bit) {
1.273 - if( this->cur_frame.channel_mode != 3 )
1.274 + if (frame->lsf_bit) {
1.275 + if (frame->channel_mode != 3)
1.276 ptr += (32 + 4);
1.277 else
1.278 ptr += (17 + 4);
1.279 } else {
1.280 - if( this->cur_frame.channel_mode != 3 )
1.281 + if (frame->channel_mode != 3)
1.282 ptr += (17 + 4);
1.283 else
1.284 ptr += (9 + 4);
1.285 @@ -292,75 +317,144 @@
1.286
1.287 if (ptr >= (buf + bufsize - 4)) return 0;
1.288 lprintf("checking %08X\n", *ptr);
1.289 - if (mpg123_xhead_check(ptr)) {
1.290 + if (BE_32(ptr) == XING_TAG) {
1.291 lprintf("Xing header found\n");
1.292 ptr += 4;
1.293
1.294 if (ptr >= (buf + bufsize - 4)) return 0;
1.295 - this->xflags = BE_32(ptr); ptr += 4;
1.296 + xing->flags = BE_32(ptr); ptr += 4;
1.297
1.298 - if (this->xflags & XING_FRAMES_FLAG) {
1.299 - if (ptr >= (buf + bufsize - 4)) return 0;
1.300 - this->xframes = BE_32(ptr); ptr += 4;
1.301 - lprintf("xframes: %d\n", this->xframes);
1.302 + if (xing->flags & XING_FRAMES_FLAG) {
1.303 + if (ptr >= (buf + bufsize - 4)) return 0;
1.304 + xing->stream_frames = BE_32(ptr); ptr += 4;
1.305 + lprintf("stream frames: %d\n", xing->stream_frames);
1.306 }
1.307 - if (this->xflags & XING_BYTES_FLAG) {
1.308 + if (xing->flags & XING_BYTES_FLAG) {
1.309 if (ptr >= (buf + bufsize - 4)) return 0;
1.310 - this->xbytes = BE_32(ptr); ptr += 4;
1.311 - lprintf("xbytes: %d\n", this->xbytes);
1.312 + xing->stream_size = BE_32(ptr); ptr += 4;
1.313 + lprintf("stream size: %d\n", xing->stream_size);
1.314 }
1.315 - if (this->xflags & XING_TOC_FLAG) {
1.316 + if (xing->flags & XING_TOC_FLAG) {
1.317 lprintf("toc found\n");
1.318 if (ptr >= (buf + bufsize - XING_TOC_LENGTH)) return 0;
1.319
1.320 for (i = 0; i < XING_TOC_LENGTH; i++) {
1.321 - this->xtoc[i] = *(ptr + i);
1.322 + xing->toc[i] = *(ptr + i);
1.323 #ifdef LOG
1.324 - printf("%d ", this->xtoc[i]);
1.325 + printf("%d ", xing->toc[i]);
1.326 #endif
1.327 }
1.328 #ifdef LOG
1.329 printf("\n");
1.330 #endif
1.331 - ptr += XING_TOC_LENGTH;
1.332 + ptr += XING_TOC_LENGTH;
1.333 }
1.334 - this->xvbr_scale = -1;
1.335 - if (this->xflags & XING_VBR_SCALE_FLAG) {
1.336 + xing->vbr_scale = -1;
1.337 + if (xing->flags & XING_VBR_SCALE_FLAG) {
1.338 if (ptr >= (buf + bufsize - 4)) return 0;
1.339 - this->xvbr_scale = BE_32(ptr);
1.340 - lprintf("xvbr_scale: %d\n", this->xvbr_scale);
1.341 + xing->vbr_scale = BE_32(ptr);
1.342 + lprintf("vbr_scale: %d\n", xing->vbr_scale);
1.343 }
1.344
1.345 - /* 1 kbit = 1000 bits ! (and not 1024 bits) */
1.346 - if (this->xflags & (XING_FRAMES_FLAG | XING_BYTES_FLAG)) {
1.347 - if (this->cur_frame.layer == 1) {
1.348 - frame_duration = 384.0 / (double)this->cur_frame.samplerate;
1.349 - } else {
1.350 - int slots_per_frame;
1.351 - slots_per_frame = (this->cur_frame.layer == 3 &&
1.352 - !this->cur_frame.lsf_bit) ? 72 : 144;
1.353 - frame_duration = slots_per_frame * 8.0 / (double)this->cur_frame.samplerate;
1.354 - }
1.355 - this->abr = ((double)this->xbytes * 8.0) / ((double)this->xframes * frame_duration);
1.356 - this->stream_length = (double)this->xframes * frame_duration;
1.357 - this->is_vbr = 1;
1.358 - lprintf("abr: %d bps\n", this->abr);
1.359 - lprintf("stream_length: %d s, %d min %d s\n", this->stream_length,
1.360 - this->stream_length / 60, this->stream_length % 60);
1.361 - } else {
1.362 - /* it's a stupid Xing header */
1.363 - this->is_vbr = 0;
1.364 - }
1.365 - return 1;
1.366 + return xing;
1.367 } else {
1.368 lprintf("Xing header not found\n");
1.369 - return 0;
1.370 + free(xing);
1.371 + return NULL;
1.372 }
1.373 }
1.374
1.375 -static int mpg123_parse_frame_payload(demux_mpgaudio_t *this,
1.376 - uint8_t *frame_header,
1.377 - int decoder_flags) {
1.378 +/*
1.379 + * Parse a Vbri header
1.380 + * return the Vbri header or NULL on error
1.381 + */
1.382 +static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame,
1.383 + uint8_t *buf, int bufsize) {
1.384 +
1.385 + int i;
1.386 + uint8_t *ptr = buf;
1.387 + vbri_header_t *vbri;
1.388 +
1.389 + vbri = xine_xmalloc (sizeof (vbri_header_t));
1.390 + if (!vbri)
1.391 + return NULL;
1.392 +
1.393 + ptr += (32 + 4);
1.394 +
1.395 + if ((ptr + 4) >= (buf + bufsize)) return 0;
1.396 + lprintf("Checking %08X\n", *ptr);
1.397 + if (BE_32(ptr) == VBRI_TAG) {
1.398 + lprintf("Vbri header found\n");
1.399 + ptr += 4;
1.400 +
1.401 + if ((ptr + 22) >= (buf + bufsize)) return 0;
1.402 + vbri->version = BE_16(ptr); ptr += 2;
1.403 + vbri->delai = BE_16(ptr); ptr += 2;
1.404 + vbri->quality = BE_16(ptr); ptr += 2;
1.405 + vbri->stream_size = BE_32(ptr); ptr += 4;
1.406 + vbri->stream_frames = BE_32(ptr); ptr += 4;
1.407 + vbri->toc_entries = BE_16(ptr); ptr += 2;
1.408 + vbri->toc_scale_factor = BE_16(ptr); ptr += 2;
1.409 + vbri->entry_size = BE_16(ptr); ptr += 2;
1.410 + vbri->entry_frames = BE_16(ptr); ptr += 2;
1.411 + lprintf("version: %d\n", vbri->version);
1.412 + lprintf("delai: %d\n", vbri->delai);
1.413 + lprintf("quality: %d\n", vbri->quality);
1.414 + lprintf("stream_size: %d\n", vbri->stream_size);
1.415 + lprintf("stream_frames: %d\n", vbri->stream_frames);
1.416 + lprintf("toc_entries: %d\n", vbri->toc_entries);
1.417 + lprintf("toc_scale_factor: %d\n", vbri->toc_scale_factor);
1.418 + lprintf("entry_size: %d\n", vbri->entry_size);
1.419 + lprintf("entry_frames: %d\n", vbri->entry_frames);
1.420 +
1.421 + if ((ptr + (vbri->toc_entries + 1) * vbri->entry_size) >= (buf + bufsize)) return 0;
1.422 + vbri->toc = xine_xmalloc (sizeof(int) * (vbri->toc_entries + 1));
1.423 + if (!vbri->toc) {
1.424 + free (vbri);
1.425 + return NULL;
1.426 + }
1.427 +
1.428 + lprintf("toc entries: %d\n", vbri->toc_entries);
1.429 + for (i = 0; i <= vbri->toc_entries; i++) {
1.430 + int j;
1.431 + uint32_t value = 0;
1.432 +
1.433 + for (j = 0; j < vbri->entry_size; j++) {
1.434 + value = (value << 8) | *(ptr + i * vbri->entry_size + j);
1.435 + }
1.436 + vbri->toc[i] = value;
1.437 +#ifdef LOG
1.438 + printf("%d ", vbri->toc[i]);
1.439 +#endif
1.440 + }
1.441 +#ifdef LOG
1.442 + printf("\n");
1.443 +#endif
1.444 + {
1.445 + int64_t toc_stream_size = 0;
1.446 +
1.447 + /* Compute the stream size using the toc */
1.448 + for (i = 0; i <= vbri->toc_entries; i++) {
1.449 + toc_stream_size += vbri->toc[i];
1.450 + }
1.451 + lprintf("stream size from toc: %lld\n", toc_stream_size);
1.452 + }
1.453 +
1.454 + return vbri;
1.455 + } else {
1.456 + lprintf("Vbri header not found\n");
1.457 + free (vbri);
1.458 + return NULL;
1.459 + }
1.460 +}
1.461 +
1.462 +/*
1.463 + * Parse a mp3 frame paylod
1.464 + * return 1 on success, 0 on error
1.465 + */
1.466 +static int parse_frame_payload(demux_mpgaudio_t *this,
1.467 + uint8_t *frame_header,
1.468 + int decoder_flags) {
1.469 buf_element_t *buf;
1.470 off_t frame_pos, len;
1.471 uint64_t pts = 0;
1.472 @@ -370,7 +464,7 @@
1.473
1.474 buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
1.475
1.476 - if (this->cur_frame.length > buf->max_size) {
1.477 + if (this->cur_frame.size > buf->max_size) {
1.478 xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1.479 "demux_mpgaudio: frame size is greater than fifo buffer size\n");
1.480 buf->free_buffer(buf);
1.481 @@ -380,54 +474,34 @@
1.482 /* the decoder needs the frame header */
1.483 memcpy(buf->mem, frame_header, 4);
1.484
1.485 - len = this->input->read(this->input, buf->mem + 4, this->cur_frame.length - 4);
1.486 - if (len != (this->cur_frame.length - 4)) {
1.487 + len = this->input->read(this->input, buf->mem + 4, this->cur_frame.size - 4);
1.488 + if (len != (this->cur_frame.size - 4)) {
1.489 buf->free_buffer(buf);
1.490 return 0;
1.491 }
1.492
1.493 - /*
1.494 - * compute stream length (in s)
1.495 - * use the Xing header if there is one (VBR) otherwise use CBR formula
1.496 - * set stream_info before sending any buffer to the decoder
1.497 - */
1.498 - if (this->check_xing) {
1.499 - mpg123_parse_xing_header(this, buf->mem, len + 4);
1.500 - if (!this->is_vbr) {
1.501 - this->stream_length = this->input->get_length(this->input) / (this->br / 8);
1.502 - _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->br);
1.503 - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->br);
1.504 - } else {
1.505 - _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->abr);
1.506 - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->abr);
1.507 + if (this->check_vbr_header) {
1.508 + this->check_vbr_header = 0;
1.509 + this->mpg_frame_start = frame_pos;
1.510 + this->xing_header = parse_xing_header(&this->cur_frame, buf->mem, this->cur_frame.size);
1.511 + if (this->xing_header) {
1.512 + buf->free_buffer(buf);
1.513 + return 1;
1.514 }
1.515 - this->check_xing = 0;
1.516 + this->vbri_header = parse_vbri_header(&this->cur_frame, buf->mem, this->cur_frame.size);
1.517 + if (this->vbri_header) {
1.518 + buf->free_buffer(buf);
1.519 + return 1;
1.520 + }
1.521 }
1.522
1.523 - /* set codec infos here
1.524 - * the decoder doesn't know if the stream is VBR
1.525 - */
1.526 - if (!this->meta_info_flag) {
1.527 - char scratch_buf[256];
1.528 - char *mpeg_ver[3] = {"1", "2", "2.5"};
1.529 -
1.530 - snprintf(scratch_buf, 256, "MPEG %s Layer %1d%s",
1.531 - mpeg_ver[this->cur_frame.version_idx], this->cur_frame.layer,
1.532 - (this->is_vbr)? " VBR" : " CBR" );
1.533 - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, scratch_buf);
1.534 -
1.535 - this->meta_info_flag = 1;
1.536 - }
1.537
1.538 - this->cur_fpts += this->cur_frame.duration;
1.539 + pts = (int64_t)(this->cur_time * 90.0f);
1.540
1.541 - pts = (int64_t)this->cur_fpts;
1.542 - check_newpts(this, pts);
1.543 + if (this->stream_length)
1.544 + buf->extra_info->input_normpos = (this->cur_time * 65535.0f) / this->stream_length;
1.545
1.546 - if( this->input->get_length (this->input) )
1.547 - buf->extra_info->input_normpos = (int)( (double) frame_pos *
1.548 - 65535 / this->input->get_length (this->input) );
1.549 - buf->extra_info->input_time = pts / 90;
1.550 + buf->extra_info->input_time = this->cur_time;
1.551 buf->pts = pts;
1.552 buf->size = len + 4;
1.553 buf->content = buf->mem;
1.554 @@ -436,81 +510,52 @@
1.555 buf->decoder_flags = decoder_flags;
1.556
1.557 this->audio_fifo->put(this->audio_fifo, buf);
1.558 + lprintf("send buffer: pts=%lld\n", pts);
1.559 + this->cur_time += this->cur_frame.duration;
1.560 return 1;
1.561 }
1.562
1.563
1.564 -static unsigned char * demux_mpgaudio_read_buffer_header (input_plugin_t *input)
1.565 -{
1.566 - int count;
1.567 - uint8_t buf[MAX_PREVIEW_SIZE];
1.568 - unsigned char *retval;
1.569 -
1.570 - if(!input)
1.571 - return 0;
1.572 -
1.573 - if((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
1.574 - input->seek(input, 0, SEEK_SET);
1.575 -
1.576 - count = input->read(input, buf, SNIFF_BUFFER_LENGTH);
1.577 - if (count < SNIFF_BUFFER_LENGTH)
1.578 - {
1.579 - return NULL;
1.580 - }
1.581 - } else if ((input->get_capabilities(input) & INPUT_CAP_PREVIEW) != 0) {
1.582 - input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
1.583 - } else {
1.584 - return NULL;
1.585 - }
1.586 -
1.587 - retval = xine_xmalloc (SNIFF_BUFFER_LENGTH);
1.588 - memcpy (retval, buf, SNIFF_BUFFER_LENGTH);
1.589 -
1.590 - return retval;
1.591 -}
1.592 -
1.593 -/* Scan through the first SNIFF_BUFFER_LENGTH bytes of the
1.594 - * buffer to find a potential 32-bit MP3 frame header. */
1.595 -static int sniff_buffer_looks_like_mp3 (input_plugin_t *input)
1.596 +/* Scan through the preview buffer to find a potential
1.597 + * 32-bit MP3 frame header.
1.598 + * return 1 if found, 0 if not found
1.599 + */
1.600 +static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen)
1.601 {
1.602 int offset;
1.603 - unsigned char *buf;
1.604 mpg_audio_frame_t frame;
1.605
1.606 - buf = demux_mpgaudio_read_buffer_header (input);
1.607 if (buf == NULL)
1.608 return 0;
1.609
1.610 - for (offset = 0; offset + 4 < SNIFF_BUFFER_LENGTH; offset++) {
1.611 + for (offset = 0; (offset + 4) < buflen; offset++) {
1.612
1.613 - if (mpg123_parse_frame_header(&frame, buf + offset)) {
1.614 - size_t length = frame.length;
1.615 + if (parse_frame_header(&frame, buf + offset)) {
1.616 + size_t size = frame.size;
1.617
1.618 /* Since one frame is available, is there another frame
1.619 * just to be sure this is more likely to be a real MP3
1.620 * buffer? */
1.621 - offset += length;
1.622 + offset += size;
1.623
1.624 - if (offset + 4 > SNIFF_BUFFER_LENGTH)
1.625 - {
1.626 - free (buf);
1.627 + if (offset + 4 >= buflen) {
1.628 return 0;
1.629 }
1.630
1.631 - if (mpg123_parse_frame_header(&frame, buf + offset)) {
1.632 - free (buf);
1.633 + if (parse_frame_header(&frame, buf + offset)) {
1.634 lprintf("mpeg audio frame detected\n");
1.635 return 1;
1.636 }
1.637 break;
1.638 }
1.639 }
1.640 -
1.641 - free (buf);
1.642 return 0;
1.643 }
1.644
1.645 -static int mpg123_read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int bytes) {
1.646 +/*
1.647 + * Read a mp3 frame header (4 bytes)
1.648 + */
1.649 +static int read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int bytes) {
1.650 off_t len;
1.651 int i;
1.652
1.653 @@ -525,22 +570,20 @@
1.654 return 1;
1.655 }
1.656
1.657 +/*
1.658 + * Parse next mp3 frame
1.659 + */
1.660 static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags) {
1.661 uint8_t header_buf[4];
1.662 int bytes = 4;
1.663
1.664 - if (!this->audio_fifo)
1.665 - return 0;
1.666 -
1.667 for (;;) {
1.668
1.669 - if (mpg123_read_frame_header(this, header_buf, bytes)) {
1.670 + if (read_frame_header(this, header_buf, bytes)) {
1.671
1.672 - if (mpg123_parse_frame_header(&this->cur_frame, header_buf)) {
1.673 - if (!this->br) {
1.674 - this->br = this->cur_frame.bitrate;
1.675 - }
1.676 - return mpg123_parse_frame_payload(this, header_buf, decoder_flags);
1.677 + if (parse_frame_header(&this->cur_frame, header_buf)) {
1.678 +
1.679 + return parse_frame_payload(this, header_buf, decoder_flags);
1.680
1.681 } else if ((BE_32(header_buf)) == ID3V22_TAG) {
1.682 xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
1.683 @@ -606,24 +649,11 @@
1.684 static int demux_mpgaudio_read_head(input_plugin_t *input, uint8_t *buf) {
1.685
1.686 int bs = 0;
1.687 - int i, optional;
1.688
1.689 - memset(buf, 0, 4);
1.690 -
1.691 - if(!input)
1.692 - return 0;
1.693 -
1.694 - if((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
1.695 + if (INPUT_IS_SEEKABLE(input)) {
1.696 input->seek(input, 0, SEEK_SET);
1.697
1.698 - if (input->get_capabilities (input) & INPUT_CAP_BLOCK)
1.699 - bs = input->get_blocksize(input);
1.700 -
1.701 - if(!bs)
1.702 - bs = MAX_PREVIEW_SIZE;
1.703 -
1.704 - if (input->read(input, buf, bs) < 4)
1.705 - return 0;
1.706 + bs = input->read(input, buf, MAX_PREVIEW_SIZE);
1.707
1.708 lprintf("stream is seekable\n");
1.709
1.710 @@ -631,20 +661,67 @@
1.711
1.712 lprintf("input plugin provides preview\n");
1.713
1.714 - optional = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
1.715 - optional = optional > 256 ? 256 : optional;
1.716 + bs = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW);
1.717
1.718 - lprintf("got preview %02x %02x %02x %02x\n",
1.719 - buf[0], buf[1], buf[2], buf[3]);
1.720 -
1.721 - for(i = 0; i < (optional - 4); i++) {
1.722 - if (BE_32(buf + i) == RIFF_TAG)
1.723 - return 1;
1.724 - }
1.725 } else {
1.726 lprintf("not seekable, no preview\n");
1.727 return 0;
1.728 }
1.729 + return bs;
1.730 +}
1.731 +
1.732 +/*
1.733 + * mp3 stream detection
1.734 + * return 1 if detected, 0 otherwise
1.735 + */
1.736 +static int detect_mpgaudio_file(input_plugin_t *input) {
1.737 + mpg_audio_frame_t frame;
1.738 + uint8_t buf[MAX_PREVIEW_SIZE];
1.739 + int preview_len;
1.740 + uint32_t head;
1.741 +
1.742 + preview_len = demux_mpgaudio_read_head(input, buf);
1.743 + if (preview_len < 4)
1.744 + return 0;
1.745 +
1.746 + lprintf("got preview %02x %02x %02x %02x\n",
1.747 + buf[0], buf[1], buf[2], buf[3]);
1.748 +
1.749 + head = BE_32(buf);
1.750 +
1.751 + if ((head == ID3V22_TAG) ||
1.752 + (head == ID3V23_TAG) ||
1.753 + (head == ID3V24_TAG)) {
1.754 + /* check if a mp3 frame follows the tag
1.755 + * id3v2 are not specific to mp3 files,
1.756 + * flac files can contain id3v2 tags
1.757 + */
1.758 + uint8_t *ptr = &buf[6];
1.759 + uint32_t tag_size = ((uint32_t)ptr[0] << 21) +
1.760 + ((uint32_t)ptr[1] << 14) +
1.761 + ((uint32_t)ptr[2] << 7) +
1.762 + (uint32_t)ptr[3];
1.763 + lprintf("try to skip id3v2 tag (%d bytes)\n", tag_size);
1.764 + if ((10 + tag_size) >= preview_len) {
1.765 + lprintf("cannot skip id3v2 tag\n");
1.766 + return 0;
1.767 + }
1.768 + if ((10 + tag_size + 4) >= preview_len) {
1.769 + lprintf("cannot read mp3 frame header\n");
1.770 + return 0;
1.771 + }
1.772 + if (!parse_frame_header(&frame, &buf[10 + tag_size])) {
1.773 + lprintf ("invalid mp3 frame header\n");
1.774 + return 0;
1.775 + } else {
1.776 + lprintf ("a valid mp3 frame follows the id3v2 tag\n");
1.777 + }
1.778 + } else if (head == MPEG_MARKER) {
1.779 + return 0;
1.780 + } else if (!sniff_buffer_looks_like_mp3(buf, preview_len)) {
1.781 + lprintf ("sniff_buffer_looks_like_mp3 failed\n");
1.782 + return 0;
1.783 + }
1.784 return 1;
1.785 }
1.786
1.787 @@ -654,15 +731,15 @@
1.788 int i;
1.789
1.790 this->stream_length = 0;
1.791 - this->last_pts = 0;
1.792 this->status = DEMUX_OK;
1.793 - this->check_xing = 1;
1.794
1.795 _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0);
1.796 _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
1.797
1.798 + _x_demux_control_start (this->stream);
1.799 +
1.800 /* read id3 info only from inputs with seeking and without "live" flag */
1.801 - if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) {
1.802 + if (INPUT_IS_SEEKABLE(this->input)) {
1.803 off_t pos;
1.804
1.805 /* check ID3 v1 at the end of the stream */
1.806 @@ -671,141 +748,206 @@
1.807 if (pos == this->input->seek (this->input, pos, SEEK_SET))
1.808 id3v1_parse_tag (this->input, this->stream);
1.809 }
1.810 - }
1.811
1.812 - /*
1.813 - * send preview buffers
1.814 - */
1.815 - _x_demux_control_start (this->stream);
1.816 -
1.817 - if ((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0)
1.818 + /* seek back to the beginning */
1.819 this->input->seek (this->input, 0, SEEK_SET);
1.820
1.821 - for (i = 0; i < NUM_PREVIEW_BUFFERS; i++) {
1.822 - if (!demux_mpgaudio_next (this, BUF_FLAG_PREVIEW)) {
1.823 - break;
1.824 + /*
1.825 + * send preview buffers
1.826 + */
1.827 + this->check_vbr_header = 1;
1.828 + for (i = 0; i < NUM_PREVIEW_BUFFERS; i++) {
1.829 + if (!demux_mpgaudio_next (this, BUF_FLAG_PREVIEW)) {
1.830 + break;
1.831 + }
1.832 + }
1.833 +
1.834 + if (this->xing_header) {
1.835 + xing_header_t *xing = this->xing_header;
1.836 +
1.837 + this->mpg_size = xing->stream_size;
1.838 + this->mpg_frame_end = this->mpg_frame_start + this->mpg_size;
1.839 + this->stream_length = (double)xing->stream_frames * this->cur_frame.duration;
1.840 + /* compute abr */
1.841 + if (this->stream_length) {
1.842 + this->br = (xing->stream_size * 8 * 1000) / this->stream_length;
1.843 + }
1.844 +
1.845 + } else if (this->vbri_header) {
1.846 + vbri_header_t *vbri = this->vbri_header;
1.847 +
1.848 + this->mpg_size = vbri->stream_size;
1.849 + this->mpg_frame_end = this->mpg_frame_start + this->mpg_size;
1.850 + this->stream_length = (double)vbri->stream_frames * this->cur_frame.duration;
1.851 + /* compute abr */
1.852 + if (this->stream_length) {
1.853 + this->br = (vbri->stream_size * 8 * 1000) / this->stream_length;
1.854 + }
1.855 + }
1.856 +
1.857 + /* Set to default if Vbr header is incomplete or not present */
1.858 + if (!this->br) {
1.859 + /* assume CBR */
1.860 + this->br = this->cur_frame.bitrate;
1.861 + }
1.862 + if (!this->mpg_frame_end) {
1.863 + this->mpg_frame_end = this->input->get_length(this->input);
1.864 + }
1.865 + if (!this->mpg_size) {
1.866 + this->mpg_size = this->mpg_frame_end - this->mpg_frame_start;
1.867 + }
1.868 + if (!this->stream_length && this->br) {
1.869 + this->stream_length = (this->mpg_size * 1000) / (this->br / 8);
1.870 + }
1.871 +
1.872 + _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->br);
1.873 + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->br);
1.874 + lprintf("frame_start: %lld, frame_end: %lld\n",
1.875 + this->mpg_frame_start, this->mpg_frame_end);
1.876 + lprintf("stream size: %lld, mp3 size: %lld\n",
1.877 + this->input->get_length(this->input),
1.878 + this->mpg_size);
1.879 + lprintf("stream_length: %lld min %lld s\n",
1.880 + ((uint64_t)this->stream_length / 1000) / 60,
1.881 + ((uint64_t)this->stream_length / 1000) % 60);
1.882 +
1.883 + /* set codec infos here
1.884 + * the decoder doesn't know if the stream is VBR
1.885 + */
1.886 + {
1.887 + char scratch_buf[256];
1.888 + char *mpeg_ver[3] = {"1", "2", "2.5"};
1.889 +
1.890 + snprintf(scratch_buf, 256, "MPEG %s Layer %1d%s",
1.891 + mpeg_ver[this->cur_frame.version_idx], this->cur_frame.layer,
1.892 + (this->xing_header)? " VBR" : " CBR" );
1.893 + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, scratch_buf);
1.894 }
1.895 }
1.896
1.897 - if (this->cur_frame.samplerate) {
1.898 - if (this->cur_frame.layer == 1)
1.899 - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION,
1.900 - 384000 / this->cur_frame.samplerate);
1.901 - else
1.902 - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION,
1.903 - 1152000 / this->cur_frame.samplerate);
1.904 - }
1.905 -
1.906 this->status = DEMUX_OK;
1.907 }
1.908
1.909 -/* interpolate in Xing TOC to get file seek point in bytes */
1.910 -static off_t xing_get_seek_point(demux_mpgaudio_t *this, int time)
1.911 +/*
1.912 + * interpolate in Xing TOC to get file seek point in bytes
1.913 + * return the stream offset of the seekpoint
1.914 + */
1.915 +static off_t xing_get_seek_point(xing_header_t *xing, int time, int stream_length)
1.916 {
1.917 off_t seekpoint;
1.918 int a;
1.919 float fa, fb, fx;
1.920 float percent;
1.921
1.922 - percent = ((float)time / 10.0f)/ (float)this->stream_length;
1.923 + percent = ((float)time * 100.0f)/ (float)stream_length;
1.924 if (percent < 0.0f) percent = 0.0f;
1.925 if (percent > 100.0f) percent = 100.0f;
1.926
1.927 a = (int)percent;
1.928 if (a > 99) a = 99;
1.929 - fa = this->xtoc[a];
1.930 + fa = xing->toc[a];
1.931 if (a < 99) {
1.932 - fb = this->xtoc[a + 1];
1.933 + fb = xing->toc[a + 1];
1.934 } else {
1.935 fb = 256.0f;
1.936 }
1.937
1.938 fx = fa + (fb - fa) * (percent - a);
1.939 - seekpoint = (off_t)((1.0f / 256.0f) * fx * this->xbytes);
1.940 + seekpoint = (off_t)((1.0f / 256.0f) * fx * xing->stream_size);
1.941
1.942 return seekpoint;
1.943 }
1.944
1.945 -/* interpolate in Xing TOC to get file seek point in ms */
1.946 -static int xing_get_seek_time(demux_mpgaudio_t *this, off_t pos)
1.947 +/*
1.948 + * Interpolate in Vbri TOC to get file seek point in bytes
1.949 + * return the stream offset of the seekpoint
1.950 + */
1.951 +static off_t vbri_get_seek_point(vbri_header_t *vbri, int time, int stream_length)
1.952 {
1.953 - int seektime;
1.954 - int a, b;
1.955 - float fb, fx;
1.956 - float percent;
1.957 + double fa, fb, fx;
1.958 + double toc_entry;
1.959 + int i;
1.960 + int a;
1.961
1.962 - fx = 256.0f * (float)pos / (float)this->xbytes;
1.963 - if (fx < 0.0f) fx = 0.0f;
1.964 - if (fx > 256.0f) fx = 256.0f;
1.965 + toc_entry = ((float)time * (float)(vbri->toc_entries + 1)) /
1.966 + (float)stream_length;
1.967 + lprintf("time: %d, stream length: %d, toc entry: %f\n",
1.968 + time, stream_length, toc_entry);
1.969 + if (toc_entry < 0.0f)
1.970 + toc_entry = 0.0f;
1.971 + if (toc_entry > (float)vbri->toc_entries)
1.972 + toc_entry = (float)vbri->toc_entries;
1.973
1.974 - for (b = 0; b < 100; b++) {
1.975 - fb = this->xtoc[b];
1.976 - if (fb > fx)
1.977 - break;
1.978 + a = (int)toc_entry;
1.979 + if (a > (vbri->toc_entries - 1))
1.980 + a = vbri->toc_entries - 1;
1.981 +
1.982 + /* compute the stream offset of the toc entry */
1.983 + fa = 0.0f;
1.984 + for (i = 0; i < a; i++) {
1.985 + fa += (double)vbri->toc[i];
1.986 }
1.987 -
1.988 - if (b > 0) {
1.989 - a = b - 1;
1.990 - } else {
1.991 - a = 0;
1.992 - }
1.993 + /* compute the stream offset of the next toc entry */
1.994 + fb = fa + (double)vbri->toc[a];
1.995
1.996 - percent = a + (fx - this->xtoc[a]);
1.997 - seektime = 10.0f * percent * this->stream_length;
1.998 + /* interpolate */
1.999 + fx = fa + (fb - fa) * (toc_entry - (double)a);
1.1000
1.1001 - return seektime;
1.1002 + return (off_t)fx;
1.1003 }
1.1004
1.1005 +/*
1.1006 + * Seeking function
1.1007 + * Try to use the Vbr header if present.
1.1008 + * If no Vbr header is present then use a CBR formula
1.1009 + *
1.1010 + * Position seek is relative to the total time of the stream, the position
1.1011 + * is converted to a time at the beginning of the function
1.1012 + */
1.1013 static int demux_mpgaudio_seek (demux_plugin_t *this_gen,
1.1014 off_t start_pos, int start_time, int playing) {
1.1015
1.1016 demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen;
1.1017 - start_pos = (off_t) ( (double) start_pos / 65535 *
1.1018 - this->input->get_length (this->input) );
1.1019 + off_t seek_pos = this->mpg_frame_start;
1.1020
1.1021 if ((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
1.1022 - if (!start_pos && start_time && this->stream_length > 0) {
1.1023 - if (this->is_vbr && (this->xflags & (XING_TOC_FLAG | XING_BYTES_FLAG))) {
1.1024 - /* vbr */
1.1025 - start_pos = xing_get_seek_point(this, start_time);
1.1026 - lprintf("time seek: vbr: time=%d, pos=%lld\n", start_time, start_pos);
1.1027 + /* Convert position seek to time seek */
1.1028 + if (!start_time) {
1.1029 + start_time = (int)((double)start_pos * (double)this->stream_length / 65535.0f);
1.1030 + lprintf("position seek: start_pos=%lld => start_time=%d\n", start_pos, start_time);
1.1031 + }
1.1032 +
1.1033 + if (start_time < 0)
1.1034 + start_time = 0;
1.1035 + if (start_time > this->stream_length)
1.1036 + start_time = this->stream_length;
1.1037 +
1.1038 + if (this->stream_length > 0) {
1.1039 + if (this->xing_header &&
1.1040 + (this->xing_header->flags & (XING_TOC_FLAG | XING_BYTES_FLAG))) {
1.1041 + seek_pos += xing_get_seek_point(this->xing_header, start_time, this->stream_length);
1.1042 + lprintf("time seek: xing: time=%d, pos=%lld\n", start_time, seek_pos);
1.1043 + } else if (this->vbri_header) {
1.1044 + seek_pos += vbri_get_seek_point(this->vbri_header, start_time, this->stream_length);
1.1045 + lprintf("time seek: vbri: time=%d, pos=%lld\n", start_time, seek_pos);
1.1046 } else {
1.1047 - /* cbr */
1.1048 - off_t input_length = this->input->get_length(this->input);
1.1049 -
1.1050 - if ((input_length > 0) && (this->stream_length > 0)) {
1.1051 - start_pos = start_time * input_length / (1000 * this->stream_length);
1.1052 - lprintf("time seek: cbr: time=%d, pos=%lld\n", start_time, start_pos);
1.1053 - }
1.1054 - }
1.1055 - } else {
1.1056 - if (this->is_vbr && (this->xflags & (XING_TOC_FLAG | XING_BYTES_FLAG))) {
1.1057 - /* vbr */
1.1058 - start_time = xing_get_seek_time(this, start_pos);
1.1059 - lprintf("pos seek: vbr: time=%d, pos=%lld\n", start_time, start_pos);
1.1060 - } else {
1.1061 - /* cbr */
1.1062 - off_t input_length = this->input->get_length(this->input);
1.1063 -
1.1064 - if((input_length > 0) && (this->stream_length > 0)) {
1.1065 - start_time = (1000 * start_pos * this->stream_length) / input_length;
1.1066 - lprintf("pos seek: cbr\n");
1.1067 - }
1.1068 + /* cbr */
1.1069 + seek_pos += ((double)start_time / 1000.0) * ((double)this->br / 8.0);
1.1070 + lprintf("time seek: cbr: time=%d, pos=%lld\n", start_time, seek_pos);
1.1071 }
1.1072 }
1.1073 - this->cur_fpts = 90.0 * (double)start_time;
1.1074 - this->input->seek (this->input, start_pos, SEEK_SET);
1.1075 + /* assume seeking is always perfect... */
1.1076 + this->cur_time = start_time;
1.1077 + this->input->seek (this->input, seek_pos, SEEK_SET);
1.1078 +
1.1079 + if (playing) {
1.1080 + _x_demux_flush_engine(this->stream);
1.1081 + }
1.1082 + _x_demux_control_newpts(this->stream,
1.1083 + (int64_t)(this->cur_time * 90.0f),
1.1084 + (playing) ? BUF_FLAG_SEEK : 0);
1.1085 }
1.1086 -
1.1087 this->status = DEMUX_OK;
1.1088 - this->send_newpts = 1;
1.1089 -
1.1090 - if( !playing ) {
1.1091 - this->buf_flag_seek = 0;
1.1092 - } else {
1.1093 - this->buf_flag_seek = 1;
1.1094 - _x_demux_flush_engine(this->stream);
1.1095 - }
1.1096
1.1097 return this->status;
1.1098 }
1.1099 @@ -819,7 +961,7 @@
1.1100 demux_mpgaudio_t *this = (demux_mpgaudio_t *) this_gen;
1.1101
1.1102 if (this->stream_length > 0) {
1.1103 - return this->stream_length * 1000;
1.1104 + return this->stream_length;
1.1105 } else
1.1106 return 0;
1.1107 }
1.1108 @@ -837,105 +979,14 @@
1.1109 input_plugin_t *input) {
1.1110
1.1111 demux_mpgaudio_t *this;
1.1112 - id3v2_header_t tag_header;
1.1113 - mpg_audio_frame_t frame;
1.1114 - uint8_t buf[MAX_PREVIEW_SIZE];
1.1115 - uint8_t *riff_check;
1.1116 - int i;
1.1117 - uint8_t *ptr;
1.1118
1.1119 lprintf("trying to open %s...\n", input->get_mrl(input));
1.1120
1.1121 switch (stream->content_detection_method) {
1.1122
1.1123 case METHOD_BY_CONTENT: {
1.1124 - uint32_t head;
1.1125 -
1.1126 - if (!demux_mpgaudio_read_head(input, buf))
1.1127 + if (!detect_mpgaudio_file(input))
1.1128 return NULL;
1.1129 -
1.1130 - head = BE_32(buf);
1.1131 - lprintf("head is %8X\n", head);
1.1132 -
1.1133 - if (head == RIFF_TAG) {
1.1134 - int ok;
1.1135 -
1.1136 - lprintf("found RIFF tag\n");
1.1137 - /* skip the length */
1.1138 - ptr = buf + 8;
1.1139 -
1.1140 - riff_check = ptr; ptr += 4;
1.1141 - if ((buf + MAX_PREVIEW_SIZE) < ptr)
1.1142 - return NULL;
1.1143 -
1.1144 - /* disqualify the file if it is, in fact, an AVI file or has a CDXA
1.1145 - * marker */
1.1146 - if ((BE_32(riff_check) == AVI_TAG) ||
1.1147 - (BE_32(riff_check) == CDXA_TAG)) {
1.1148 - lprintf("found AVI or CDXA tag\n");
1.1149 - return NULL;
1.1150 - }
1.1151 -
1.1152 - /* skip 4 more bytes */
1.1153 - ptr += 4;
1.1154 -
1.1155 - /* get the length of the next chunk */
1.1156 - riff_check = ptr; ptr += 4;
1.1157 - if ((buf + MAX_PREVIEW_SIZE) < ptr)
1.1158 - return NULL;
1.1159 - /* head gets to be a generic variable in this case */
1.1160 - head = LE_32(riff_check);
1.1161 - /* skip over the chunk and the 'data' tag and length */
1.1162 - ptr += 8;
1.1163 -
1.1164 - /* load the next, I don't know...n bytes, and check for a valid
1.1165 - * MPEG audio header */
1.1166 - riff_check = ptr; ptr += RIFF_CHECK_BYTES;
1.1167 - if ((buf + MAX_PREVIEW_SIZE) < ptr)
1.1168 - return NULL;
1.1169 -
1.1170 - ok = 0;
1.1171 - for (i = 0; i < RIFF_CHECK_BYTES - 4; i++) {
1.1172 - head = BE_32(riff_check + i);
1.1173 -
1.1174 - lprintf("checking %08X\n", head);
1.1175 -
1.1176 - if (sniff_buffer_looks_like_mp3(input))
1.1177 - ok = 1;
1.1178 - }
1.1179 - if (!ok)
1.1180 - return NULL;
1.1181 -
1.1182 - } else if ((head == ID3V22_TAG) ||
1.1183 - (head == ID3V23_TAG) ||
1.1184 - (head == ID3V24_TAG)) {
1.1185 - /* check if a mp3 frame follows the tag
1.1186 - * id3v2 are not specific to mp3 files,
1.1187 - * flac files can contain id3v2 tags
1.1188 - */
1.1189 - ptr = buf + 4;
1.1190 - tag_header.size = (ptr[2] << 21) + (ptr[3] << 14) + (ptr[4] << 7) + ptr[5];
1.1191 - lprintf("id3v2.%d tag detected, size: %d\n", buf[3], tag_header.size);
1.1192 -
1.1193 - ptr += tag_header.size + 6;
1.1194 - if ((ptr + 4) <= (buf + MAX_PREVIEW_SIZE)) {
1.1195 - if (!mpg123_parse_frame_header(&frame, ptr)) {
1.1196 - lprintf ("invalid mp3 frame header\n");
1.1197 - return NULL;
1.1198 - }
1.1199 - lprintf ("a valid mp3 frame follows the id3 tag\n");
1.1200 - } else {
1.1201 - lprintf ("the id3v2 tag is too long\n");
1.1202 - return NULL;
1.1203 - }
1.1204 -
1.1205 - } else if (head == MPEG_MARKER) {
1.1206 - lprintf ("discard mpeg video\n");
1.1207 - return NULL;
1.1208 - } else if (!sniff_buffer_looks_like_mp3 (input)) {
1.1209 - lprintf ("sniff_buffer_looks_like_mp3 failed\n");
1.1210 - return NULL;
1.1211 - }
1.1212 }
1.1213 break;
1.1214