summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego 'Flameeyes' Pettenò <flameeyes@gmail.com>2006-11-09 15:13:19 +0000
committerDiego 'Flameeyes' Pettenò <flameeyes@gmail.com>2006-11-09 15:13:19 +0000
commit8d0828feb74d91958d151284494cad1aeac62432 (patch)
treed22bcd05dd0db3f7ca880ff1158c3ce68ec3508d /src
parent3c0e458a00a2171f0116fccd50e9736c4cd4cbc3 (diff)
downloadxine-lib-8d0828feb74d91958d151284494cad1aeac62432.tar.gz
xine-lib-8d0828feb74d91958d151284494cad1aeac62432.tar.bz2
Add support for playing OggFlac files (still not 100% complete, but will play). Add a flacutils.h header with functions to parse FLAC data structure, to be shared with demux_flac. Closes bug #1590690.
CVS patchset: 8362 CVS date: 2006/11/09 15:13:19
Diffstat (limited to 'src')
-rw-r--r--src/demuxers/demux_flac.c13
-rw-r--r--src/demuxers/demux_ogg.c79
-rw-r--r--src/demuxers/flacutils.h91
3 files changed, 166 insertions, 17 deletions
diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c
index a0ae6c5ba..94c668555 100644
--- a/src/demuxers/demux_flac.c
+++ b/src/demuxers/demux_flac.c
@@ -23,7 +23,7 @@
* For more information on the FLAC file format, visit:
* http://flac.sourceforge.net/
*
- * $Id: demux_flac.c,v 1.10 2006/06/02 22:33:37 dsalt Exp $
+ * $Id: demux_flac.c,v 1.11 2006/11/09 15:13:19 dgp85 Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -49,16 +49,7 @@
#include "bswap.h"
#include "group_audio.h"
-typedef struct {
- off_t offset;
- int64_t sample_number;
- int64_t pts;
- int size;
-} flac_seekpoint_t;
-
-#define FLAC_SIGNATURE_SIZE 4
-#define FLAC_STREAMINFO_SIZE 34
-#define FLAC_SEEKPOINT_SIZE 18
+#include "flacutils.h"
typedef struct {
demux_plugin_t demux_plugin;
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c
index 92eb6507d..9a44d77cd 100644
--- a/src/demuxers/demux_ogg.c
+++ b/src/demuxers/demux_ogg.c
@@ -19,7 +19,7 @@
*/
/*
- * $Id: demux_ogg.c,v 1.168 2006/09/14 02:04:48 dgp85 Exp $
+ * $Id: demux_ogg.c,v 1.169 2006/11/09 15:13:19 dgp85 Exp $
*
* demultiplexer for ogg streams
*
@@ -55,6 +55,7 @@
#define LOG_MODULE "demux_ogg"
#define LOG_VERBOSE
+
/*
#define LOG
*/
@@ -68,6 +69,7 @@
#include "xineutils.h"
#include "demux.h"
#include "bswap.h"
+#include "flacutils.h"
#define CHUNKSIZE 8500
#define PACKET_TYPE_HEADER 0x01
@@ -592,6 +594,7 @@ static void send_ogg_buf (demux_ogg_t *this,
}
if ((this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_AUDIO_SPEEX ||
+ (this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_AUDIO_FLAC ||
(this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_AUDIO_VORBIS) {
data = op->packet;
size = op->bytes;
@@ -615,10 +618,9 @@ static void send_ogg_buf (demux_ogg_t *this,
pts);
_x_demux_send_data(this->audio_fifo, data, size,
- pts, this->si[stream_num]->buf_types, decoder_flags,
- normpos,
- pts / 90, this->time_length, 0);
-
+ pts, this->si[stream_num]->buf_types, decoder_flags,
+ normpos,
+ pts / 90, this->time_length, 0);
#ifdef HAVE_THEORA
} else if ((this->si[stream_num]->buf_types & 0xFFFF0000) == BUF_VIDEO_THEORA) {
@@ -1179,6 +1181,69 @@ static void decode_theora_header (demux_ogg_t *this, const int stream_num, ogg_p
#endif
}
+static void decode_flac_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) {
+ xine_flac_metadata_header header;
+ xine_flac_streaminfo_block streaminfo;
+ buf_element_t *buf;
+ xine_waveformatex wave;
+
+ /* Packet type */
+ _x_assert(op->packet[0] == 0x7F);
+
+ /* OggFLAC signature */
+ _x_assert(op->packet[1] == 'F'); _x_assert(op->packet[2] == 'L');
+ _x_assert(op->packet[3] == 'A'); _x_assert(op->packet[4] == 'C');
+
+ /* Version: supported only 1.0 */
+ _x_assert(op->packet[5] == 1); _x_assert(op->packet[6] == 0);
+
+ /* Header count */
+ this->si[stream_num]->headers = 0/*BE_16(&op->packet[7]) +1*/;
+
+ /* fLaC signature */
+ _x_assert(op->packet[9] == 'f'); _x_assert(op->packet[10] == 'L');
+ _x_assert(op->packet[11] == 'a'); _x_assert(op->packet[12] == 'C');
+
+ _x_parse_flac_metadata_header(&op->packet[13], &header);
+
+ switch ( header.blocktype ) {
+ case FLAC_BLOCKTYPE_STREAMINFO:
+ _x_assert(header.length == FLAC_STREAMINFO_SIZE);
+ _x_parse_flac_streaminfo_block(&op->packet[17], &streaminfo);
+ break;
+ }
+
+ this->si[stream_num]->buf_types = BUF_AUDIO_FLAC
+ +this->num_audio_streams++;
+
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, streaminfo.samplerate);
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS, streaminfo.channels);
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, streaminfo.bits_per_sample);
+
+ this->si[stream_num]->factor = 90000;
+
+ buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
+
+ buf->type = BUF_AUDIO_FLAC;
+ buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
+
+ buf->decoder_info[0] = 0;
+ buf->decoder_info[1] = streaminfo.samplerate;
+ buf->decoder_info[2] = streaminfo.bits_per_sample;
+ buf->decoder_info[3] = streaminfo.channels;
+ buf->size = sizeof(xine_waveformatex) + FLAC_STREAMINFO_SIZE;
+ memcpy(buf->content+sizeof(xine_waveformatex), &op->packet[17], FLAC_STREAMINFO_SIZE);
+ xine_hexdump(&op->packet[17], FLAC_STREAMINFO_SIZE);
+ wave.cbSize = FLAC_STREAMINFO_SIZE;
+ memcpy(buf->content, &wave, sizeof(xine_waveformatex));
+
+ this->audio_fifo->put(this->audio_fifo, buf);
+
+ /* Skip the Ogg framing info */
+ op->bytes -= 9;
+ op->packet += 9;
+}
+
static void decode_annodex_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) {
lprintf ("Annodex stream detected\n");
this->si[stream_num]->buf_types = BUF_CONTROL_NOP;
@@ -1325,6 +1390,8 @@ static void send_header (demux_ogg_t *this) {
decode_text_header(this, stream_num, &op);
} else if (!strncmp (&op.packet[1], "theora", 6)) {
decode_theora_header(this, stream_num, &op);
+ } else if (!strncmp (&op.packet[1], "FLAC", 4)) {
+ decode_flac_header(this, stream_num, &op);
} else if (!strncmp (&op.packet[0], "Annodex", 7)) {
decode_annodex_header(this, stream_num, &op);
} else if (!strncmp (&op.packet[0], "AnxData", 7)) {
@@ -1439,7 +1506,7 @@ static int demux_ogg_send_chunk (demux_plugin_t *this_gen) {
/* printf("demux_ogg: got a packet\n"); */
if ((*op.packet & PACKET_TYPE_HEADER) &&
- (this->si[stream_num]->buf_types!=BUF_VIDEO_THEORA) && (this->si[stream_num]->buf_types!=BUF_AUDIO_SPEEX)) {
+ (this->si[stream_num]->buf_types!=BUF_VIDEO_THEORA) && (this->si[stream_num]->buf_types!=BUF_AUDIO_SPEEX) && (this->si[stream_num]->buf_types!=BUF_AUDIO_FLAC)) {
if (op.granulepos != -1) {
this->si[stream_num]->header_granulepos = op.granulepos;
lprintf ("header with granulepos, remembering granulepos\n");
diff --git a/src/demuxers/flacutils.h b/src/demuxers/flacutils.h
new file mode 100644
index 000000000..67f5d66c9
--- /dev/null
+++ b/src/demuxers/flacutils.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 the xine project
+ * Based on the FLAC File Demuxer by Mike Melanson
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef __FLACUTILS_H__
+#define __FLACUTILS_H__
+
+typedef struct {
+ off_t offset;
+ int64_t sample_number;
+ int64_t pts;
+ int size;
+} flac_seekpoint_t;
+
+#define FLAC_SIGNATURE_SIZE 4
+#define FLAC_STREAMINFO_SIZE 34
+#define FLAC_SEEKPOINT_SIZE 18
+
+enum {
+ FLAC_BLOCKTYPE_STREAMINFO,
+ FLAC_BLOCKTYPE_PADDING,
+ FLAC_BLOCKTYPE_APPLICATION,
+ FLAC_BLOCKTYPE_SEEKTABLE,
+ FLAC_BLOCKTYPE_VORBIS_COMMENT,
+ FLAC_BLOCKTYPE_CUESHEET,
+ FLAC_BLOCKTYPE_INVALID = 127
+};
+
+/*
+ * WARNING: These structures are *not* using the same format
+ * used by FLAC files, bitwise.
+ *
+ * Using bitfields to read the whole data is unfeasible because
+ * of endianness problems with non-byte-aligned values.
+ */
+
+typedef struct {
+ uint8_t last;
+ uint8_t blocktype;
+ uint32_t length;
+} xine_flac_metadata_header;
+
+typedef struct {
+ uint16_t blocksize_min;
+ uint16_t blocksize_max;
+ uint32_t framesize_min;
+ uint32_t framesize_max;
+ uint32_t samplerate;
+ uint8_t channels;
+ uint8_t bits_per_sample;
+ uint64_t total_samples;
+ uint8_t md5[16];
+} xine_flac_streaminfo_block;
+
+static inline void _x_parse_flac_metadata_header(uint8_t *buffer, xine_flac_metadata_header *parsed) {
+ parsed->last = buffer[0] & 0x80 ? 1 : 0;
+ parsed->blocktype = buffer[0] & 0x7f;
+
+ parsed->length = BE_24(&buffer[1]);
+}
+
+static inline void _x_parse_flac_streaminfo_block(uint8_t *buffer, xine_flac_streaminfo_block *parsed) {
+ parsed->blocksize_min = BE_16(&buffer[0]);
+ parsed->blocksize_max = BE_16(&buffer[2]);
+ parsed->framesize_min = BE_24(&buffer[4]);
+ parsed->framesize_max = BE_24(&buffer[7]);
+ parsed->samplerate = BE_32(&buffer[10]);
+ parsed->channels = ((parsed->samplerate >> 9) & 0x07) + 1;
+ parsed->bits_per_sample = ((parsed->samplerate >> 4) & 0x1F) + 1;
+ parsed->samplerate >>= 12;
+ parsed->total_samples = BE_64(&buffer[10]) & UINT64_C(0x0FFFFFFFFF); /* 36 bits */
+}
+
+#endif