Commit c0a5c212 authored by Gildas Bazin's avatar Gildas Bazin

* include/codecs.h: new header file to store information shared by decoders
   and demuxers, like the BITMAPINFOHEADER structure for instance.
* modules/demux/ogg.c: the ogg demuxer should now work nicely with ogm files
   (including for the video). It has only been tested with a few streams
   produced with dvd::rip and ogmmerge though.
parent ce1815eb
/*****************************************************************************
* codecs.h: codec related structures needed by the demuxers and decoders
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: codecs.h,v 1.1 2002/11/03 23:00:32 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
* This program 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.
*
* This program 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, USA.
*****************************************************************************/
#ifndef _VLC_CODECS_H
#define _VLC_CODECS_H 1
/* Structures exported to the demuxers and decoders */
#ifndef _WAVEFORMATEX_
#define _WAVEFORMATEX_
typedef struct __attribute__((__packed__)) _WAVEFORMATEX {
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t wBitsPerSample;
uint16_t cbSize;
} WAVEFORMATEX, *PWAVEFORMATEX, *NPWAVEFORMATEX, *LPWAVEFORMATEX;
#endif /* _WAVEFORMATEX_ */
#ifndef _BITMAPINFOHEADER_
#define _BITMAPINFOHEADER_
typedef struct __attribute__((__packed__))
{
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER, *LPBITMAPINFOHEADER;
typedef struct {
BITMAPINFOHEADER bmiHeader;
int bmiColors[1];
} BITMAPINFO, *LPBITMAPINFO;
#endif
/* WAVE form wFormatTag IDs */
#define WAVE_FORMAT_UNKNOWN 0x0000 /* Microsoft Corporation */
#define WAVE_FORMAT_PCM 0x0001 /* Microsoft Corporation */
#define WAVE_FORMAT_ADPCM 0x0002 /* Microsoft Corporation */
#define WAVE_FORMAT_IEEE_FLOAT 0x0003 /* Microsoft Corporation */
#define WAVE_FORMAT_ALAW 0x0006 /* Microsoft Corporation */
#define WAVE_FORMAT_MULAW 0x0007 /* Microsoft Corporation */
#define WAVE_FORMAT_DTS 0x0008 /* Microsoft Corporation */
#define WAVE_FORMAT_MPEG 0x0050 /* Microsoft Corporation */
#define WAVE_FORMAT_MPEGLAYER3 0x0055 /* ISO/MPEG Layer3 Format Tag */
#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 /* Sonic Foundry */
/* Need to check these */
#define WAVE_FORMAT_A52 0x2000
#define WAVE_FORMAT_WMA1 0x0160
#define WAVE_FORMAT_WMA2 0x0161
#if !defined(WAVE_FORMAT_EXTENSIBLE)
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE /* Microsoft */
#endif
#endif /* "codecs.h" */
......@@ -2,7 +2,7 @@
* ogg.c : ogg stream input module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: ogg.c,v 1.5 2002/11/03 13:22:44 gbazin Exp $
* $Id: ogg.c,v 1.6 2002/11/03 23:00:32 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -34,6 +34,8 @@
#include <ogg/ogg.h>
#include <codecs.h> /* BITMAPINFOHEADER, WAVEFORMATEX */
#define OGG_BLOCK_SIZE 4096
#define PAGES_READ_ONCE 1
......@@ -63,12 +65,16 @@ typedef struct logical_stream_s
/* program clock reference (in units of 90kHz) derived from the previous
* granulepos */
mtime_t i_pcr;
long l_previous_granulepos;
/* info from logical streams */
int i_rate;
double i_rate;
int i_bitrate;
int b_reinit;
BITMAPINFOHEADER *p_bih;
WAVEFORMATEX *p_wf;
} logical_stream_t;
struct demux_sys_t
......@@ -93,6 +99,50 @@ struct demux_sys_t
int b_seekable;
};
/* OggDS headers for the new header format (used in ogm files) */
typedef struct stream_header_video
{
ogg_int32_t width;
ogg_int32_t height;
} stream_header_video;
typedef struct stream_header_audio
{
ogg_int16_t channels;
ogg_int16_t blockalign;
ogg_int32_t avgbytespersec;
} stream_header_audio;
typedef struct stream_header
{
char streamtype[8];
char subtype[4];
ogg_int32_t size; /* size of the structure */
ogg_int64_t time_unit; /* in reference time */
ogg_int64_t samples_per_unit;
ogg_int32_t default_len; /* in media time */
ogg_int32_t buffersize;
ogg_int16_t bits_per_sample;
union
{
/* Video specific */
stream_header_video video;
/* Audio specific */
stream_header_audio audio;
} sh;
} stream_header;
/* Some defines from OggDS */
#define PACKET_TYPE_HEADER 0x01
#define PACKET_TYPE_BITS 0x07
#define PACKET_LEN_BITS01 0xc0
#define PACKET_LEN_BITS2 0x02
#define PACKET_IS_SYNCPOINT 0x08
/*****************************************************************************
* Local prototypes
*****************************************************************************/
......@@ -258,6 +308,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
pes_packet_t *p_pes;
data_packet_t *p_data;
demux_sys_t *p_ogg = p_input->p_demux_data;
int i_header_len = 0;
if( p_stream->b_force_backup )
{
......@@ -315,19 +366,24 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
return;
}
p_pes->p_first = p_pes->p_last = p_data;
p_pes->i_nb_data = 1;
p_pes->i_pes_size = p_oggpacket->bytes;
p_pes->i_dts = p_oggpacket->granulepos;
/* Convert the pcr into a pts */
p_pes->i_pts = ( p_stream->i_pcr < 0 ) ? 0 :
input_ClockGetTS( p_input, p_input->stream.p_selected_program,
p_stream->i_pcr );
/* Convert the next granule into a pcr */
p_stream->i_pcr = ( p_oggpacket->granulepos < 0 ) ? -1 :
p_oggpacket->granulepos * 90000 / p_stream->i_rate;
if( p_oggpacket->granulepos < 0 )
{
/* FIXME: ffmpeg doesn't like null pts */
if( p_stream->i_cat == VIDEO_ES )
p_stream->i_pcr += (90000 / p_stream->i_rate);
else
p_stream->i_pcr = -1;
}
else
{
p_stream->i_pcr = p_oggpacket->granulepos * 90000 / p_stream->i_rate;
}
/* Update the main pcr */
if( p_stream == p_ogg->p_stream_timeref )
......@@ -343,7 +399,26 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
}
}
memcpy( p_data->p_payload_start, p_oggpacket->packet, p_oggpacket->bytes );
p_pes->i_nb_data = 1;
p_pes->i_dts = p_oggpacket->granulepos;
p_pes->p_first = p_pes->p_last = p_data;
p_pes->i_pes_size = p_oggpacket->bytes;
if( p_stream->i_fourcc != VLC_FOURCC( 'v','o','r','b' ) )
{
/* Remove the header from the packet */
i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
i_header_len++;
p_pes->i_pes_size -= i_header_len;
}
memcpy( p_data->p_payload_start,
p_oggpacket->packet + i_header_len,
p_oggpacket->bytes - i_header_len );
p_data->p_payload_end = p_data->p_payload_start + p_pes->i_pes_size;
input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
}
......@@ -426,9 +501,129 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
oggpack_adv( &opb, 32 );
p_stream->i_bitrate = oggpack_read( &opb, 32 );
}
else if( (*oggpacket.packet & PACKET_TYPE_BITS )
== PACKET_TYPE_HEADER &&
oggpacket.bytes >= (int)sizeof(stream_header)+1 )
{
stream_header *st = (stream_header *)(oggpacket.packet+1);
/* Check for video header (new format) */
if( !strncmp( st->streamtype, "video", 5 ) )
{
p_stream->i_cat = VIDEO_ES;
/* We need to get rid of the header packet */
ogg_stream_packetout( &p_stream->os, &oggpacket );
p_stream->p_bih = (BITMAPINFOHEADER*)
calloc( 1, sizeof(BITMAPINFOHEADER) );
p_stream->p_bih->biSize = sizeof(BITMAPINFOHEADER);
p_stream->p_bih->biCompression=
p_stream->i_fourcc = VLC_FOURCC( st->subtype[0],
st->subtype[1],
st->subtype[2],
st->subtype[3] );
msg_Dbg( p_input, "found video header of type: %.4s",
(char *)&p_stream->i_fourcc );
p_stream->i_rate = 10000000.0 / st->time_unit;
p_stream->p_bih->biBitCount = st->bits_per_sample;
p_stream->p_bih->biWidth = st->sh.video.width;
p_stream->p_bih->biHeight = st->sh.video.height;
p_stream->p_bih->biPlanes= 1 ;
p_stream->p_bih->biSizeImage =
(p_stream->p_bih->biBitCount >> 3) *
p_stream->p_bih->biWidth *
p_stream->p_bih->biHeight;
msg_Dbg( p_input,
"fps: %f, width:%i; height:%i, bitcount:%i",
p_stream->i_rate, p_stream->p_bih->biWidth,
p_stream->p_bih->biHeight,
p_stream->p_bih->biBitCount);
}
/* Check for audio header (new format) */
else if( !strncmp( st->streamtype, "audio", 5 ) )
{
char p_buffer[5];
int i_extra_size = st->size - sizeof(stream_header);
p_stream->i_cat = AUDIO_ES;
/* We need to get rid of the header packet */
ogg_stream_packetout( &p_stream->os, &oggpacket );
memcpy( p_buffer, st->subtype, 4 );
p_buffer[4] = '\0';
p_stream->p_wf = (WAVEFORMATEX *)
calloc( 1, sizeof(WAVEFORMATEX) + i_extra_size );
p_stream->p_wf->wFormatTag = strtol(p_buffer,NULL,16);
p_stream->p_wf->nChannels = st->sh.audio.channels;
p_stream->i_rate = p_stream->p_wf->nSamplesPerSec =
st->samples_per_unit;
p_stream->i_bitrate = p_stream->p_wf->nAvgBytesPerSec =
st->sh.audio.avgbytespersec;
p_stream->i_bitrate *= 8;
p_stream->p_wf->nBlockAlign = st->sh.audio.blockalign;
p_stream->p_wf->wBitsPerSample = st->bits_per_sample;
p_stream->p_wf->cbSize = i_extra_size;
if( i_extra_size )
memcpy( p_stream->p_wf + sizeof(WAVEFORMATEX),
&st[1] , i_extra_size );
switch( p_stream->p_wf->wFormatTag )
{
case WAVE_FORMAT_PCM:
p_stream->i_fourcc =
VLC_FOURCC( 'a', 'r', 'a', 'w' );
break;
case WAVE_FORMAT_MPEG:
case WAVE_FORMAT_MPEGLAYER3:
p_stream->i_fourcc =
VLC_FOURCC( 'm', 'p', 'g', 'a' );
break;
case WAVE_FORMAT_A52:
p_stream->i_fourcc =
VLC_FOURCC( 'a', '5', '2', ' ' );
break;
case WAVE_FORMAT_WMA1:
p_stream->i_fourcc =
VLC_FOURCC( 'w', 'm', 'a', '1' );
break;
case WAVE_FORMAT_WMA2:
p_stream->i_fourcc =
VLC_FOURCC( 'w', 'm', 'a', '2' );
break;
default:
p_stream->i_fourcc = VLC_FOURCC( 'm', 's',
( p_stream->p_wf->wFormatTag >> 8 ) & 0xff,
p_stream->p_wf->wFormatTag & 0xff );
}
msg_Dbg( p_input, "found audio header of type: %.4s",
(char *)&p_stream->i_fourcc );
msg_Dbg( p_input, "audio:0x%4.4x channels:%d %dHz "
"%dbits/sample %dkb/s",
p_stream->p_wf->wFormatTag,
p_stream->p_wf->nChannels,
p_stream->p_wf->nSamplesPerSec,
p_stream->p_wf->wBitsPerSample,
p_stream->p_wf->nAvgBytesPerSec * 8 / 1024 );
}
else
{
msg_Dbg( p_input, "stream %d has a header marker "
"but is of an unknown type", p_ogg->i_streams-1 );
free( p_stream );
p_ogg->i_streams--;
}
}
else
{
msg_Dbg( p_input, "found unknown codec" );
msg_Dbg( p_input, "stream %d is of unknown type",
p_ogg->i_streams-1 );
free( p_stream );
p_ogg->i_streams--;
}
......@@ -538,6 +733,8 @@ static int Activate( vlc_object_t * p_this )
p_stream->p_es->i_stream_id = i_stream;
p_stream->p_es->i_fourcc = p_stream->i_fourcc;
p_stream->p_es->i_cat = p_stream->i_cat;
p_stream->p_es->p_demux_data = p_stream->p_bih ?
(void *)p_stream->p_bih : (void *)p_stream->p_wf;
#undef p_stream
}
......@@ -618,7 +815,14 @@ static void Deactivate( vlc_object_t *p_this )
{
free( p_ogg->pp_stream[i]->p_packets_backup[j].packet );
}
free( p_ogg->pp_stream[i]->p_packets_backup );
if( p_ogg->pp_stream[i]->p_packets_backup)
free( p_ogg->pp_stream[i]->p_packets_backup );
#if 0 /* hmmm, it's already freed in input_DelES() */
if( p_ogg->pp_stream[i]->p_bih )
free( p_ogg->pp_stream[i]->p_bih );
if( p_ogg->pp_stream[i]->p_wf )
free( p_ogg->pp_stream[i]->p_wf );
#endif
free( p_ogg->pp_stream[i] );
}
if( p_ogg->pp_stream ) free( p_ogg->pp_stream );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment