Added a first Vorbis support including the packetizers.

This commit is contained in:
Moritz Bunkus 2003-03-03 18:00:30 +00:00
parent 2de297e537
commit a0f0cfbedc
5 changed files with 496 additions and 94 deletions

View File

@ -14,6 +14,7 @@ mkvmerge_SOURCES = mkvmerge.cpp mkvmerge.h \
p_mp3.cpp p_mp3.h \
p_pcm.cpp p_pcm.h \
p_video.cpp p_video.h \
p_vorbis.cpp p_vorbis.h \
pr_generic.h pr_generic.cpp \
queue.cpp queue.h \
r_ac3.cpp r_ac3.h \

View File

@ -13,7 +13,7 @@
/*!
\file
\version \$Id: error.h,v 1.5 2003/02/27 09:52:37 mosu Exp $
\version \$Id: error.h,v 1.6 2003/03/03 18:00:30 mosu Exp $
\brief class definitions for the error exception class
\author Moritz Bunkus <moritz @ bunkus.org>
*/
@ -30,8 +30,7 @@ class error_c {
private:
char *error;
public:
error_c(char *nerror) { error = strdup(nerror); if (!error) die("strdup"); };
~error_c() { if (error) free(error); };
error_c(char *nerror) { error = nerror; };
char *get_error() { return error; };
};

327
p_vorbis.cpp Normal file
View File

@ -0,0 +1,327 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
p_vorbis.h
Written by Moritz Bunkus <moritz@bunkus.org>
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
*/
/*!
\file
\version \$Id: p_vorbis.cpp,v 1.1 2003/03/03 18:00:30 mosu Exp $
\brief Vorbis packetizer
\author Moritz Bunkus <moritz @ bunkus.org>
*/
#include "config.h"
#ifdef HAVE_OGGVORBIS
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>
#include "common.h"
#include "pr_generic.h"
#include "p_vorbis.h"
// #include "vorbis_header_utils.h"
#include "KaxTracks.h"
#include "KaxTrackAudio.h"
#ifdef DMALLOC
#include <dmalloc.h>
#endif
vorbis_packetizer_c::vorbis_packetizer_c(audio_sync_t *nasync, range_t *nrange,
void *d_header, int l_header,
void *d_comments, int l_comments,
void *d_codecsetup, int l_codecsetup)
throw (error_c) : q_c() {
int i;
packetno = 0;
old_granulepos = 0;
memcpy(&async, nasync, sizeof(audio_sync_t));
memcpy(&range, nrange, sizeof(range_t));
last_granulepos = 0;
last_granulepos_seen = 0;
memset(headers, 0, 3 * sizeof(ogg_packet));
headers[0].packet = (unsigned char *)malloc(l_header);
headers[1].packet = (unsigned char *)malloc(l_comments);
headers[2].packet = (unsigned char *)malloc(l_codecsetup);
if ((headers[0].packet == NULL) || (headers[1].packet == NULL) ||
(headers[2].packet == NULL))
die("malloc");
memcpy(headers[0].packet, d_header, l_header);
memcpy(headers[1].packet, d_comments, l_comments);
memcpy(headers[2].packet, d_codecsetup, l_codecsetup);
headers[0].bytes = l_header;
headers[1].bytes = l_comments;
headers[2].bytes = l_codecsetup;
headers[0].b_o_s = 1;
headers[1].packetno = 1;
headers[2].packetno = 2;
vorbis_info_init(&vi);
vorbis_comment_init(&vc);
for (i = 0; i < 3; i++)
if (vorbis_synthesis_headerin(&vi, &vc, &headers[i]) < 0)
throw error_c("Error: vorbis_packetizer: Could not extract the "
"stream's parameters from the first packets.\n");
set_header();
}
vorbis_packetizer_c::~vorbis_packetizer_c() {
int i;
for (i = 0; i < 3; i++)
if (headers[i].packet != NULL)
free(headers[i].packet);
}
int vorbis_packetizer_c::encode_silence(int fd) {
// vorbis_dsp_state lvds;
// vorbis_block lvb;
// vorbis_info lvi;
// vorbis_comment lvc;
// ogg_stream_state loss;
// ogg_page log;
// ogg_packet lop;
// ogg_packet h_main, h_comments, h_codebook;
// int samples, i, j, k, eos;
// float **buffer;
// samples = vi.rate * async.displacement / 1000;
// vorbis_info_init(&lvi);
// if (vorbis_encode_setup_vbr(&lvi, vi.channels, vi.rate, 1))
// return EOTHER;
// vorbis_encode_setup_init(&lvi);
// vorbis_analysis_init(&lvds, &lvi);
// vorbis_block_init(&lvds, &lvb);
// vorbis_comment_init(&lvc);
// lvc.vendor = strdup(VERSIONINFO);
// lvc.user_comments = (char **)mmalloc(4);
// lvc.comment_lengths = (int *)mmalloc(4);
// lvc.comments = 0;
// ogg_stream_init(&loss, serialno);
// vorbis_analysis_headerout(&lvds, &lvc, &h_main, &h_comments, &h_codebook);
// ogg_stream_packetin(&loss, &h_main);
// ogg_stream_packetin(&loss, &h_comments);
// ogg_stream_packetin(&loss, &h_codebook);
// while (ogg_stream_flush(&loss, &log)) {
// write(fd, log.header, log.header_len);
// write(fd, log.body, log.body_len);
// }
// eos = 0;
// for (i = 0; i <= 1; i++) {
// if (i == 0) {
// buffer = vorbis_analysis_buffer(&lvds, samples);
// for (j = 0; j < samples; j++)
// for (k = 0; k < vi.channels; k++)
// buffer[k][j] = 0.0f;
// vorbis_analysis_wrote(&lvds, samples);
// } else
// vorbis_analysis_wrote(&lvds, 0);
// while (vorbis_analysis_blockout(&lvds, &lvb) == 1) {
// vorbis_analysis(&lvb, NULL);
// vorbis_bitrate_addblock(&lvb);
// while (vorbis_bitrate_flushpacket(&lvds, &lop)) {
// ogg_stream_packetin(&loss, &lop);
// while (!eos) {
// if (!ogg_stream_pageout(&loss, &log))
// break;
// write(fd, log.header, log.header_len);
// write(fd, log.body, log.body_len);
// if (ogg_page_eos(&log))
// eos = 1;
// }
// }
// }
// }
// ogg_stream_clear(&loss);
// vorbis_block_clear(&lvb);
// vorbis_dsp_clear(&lvds);
// vorbis_info_clear(&lvi);
// vorbis_comment_clear(&lvc);
return 0;
}
void vorbis_packetizer_c::setup_displacement() {
// char tmpname[30];
// int fd, old_verbose, status;
// ogm_reader_c *ogm_reader;
// audio_sync_t nosync;
// range_t norange;
// generic_packetizer_c *old_packetizer;
// ogmmerge_page_t *mpage;
// if (async.displacement <= 0)
// return;
// strcpy(tmpname, "/tmp/ogmmerge-XXXXXX");
// if ((fd = mkstemp(tmpname)) == -1) {
// fprintf(stderr, "FATAL: vorbis_packetizer: mkstemp() failed.\n");
// exit(1);
// }
// if (encode_silence(fd) < 0) {
// fprintf(stderr, "FATAL: Could not encode silence.\n");
// exit(1);
// }
// close(fd);
// old_verbose = verbose;
// memset(&norange, 0, sizeof(range_t));
// verbose = 0;
// nosync.displacement = 0;
// nosync.linear = 1.0;
// try {
// ogm_reader = new ogm_reader_c(tmpname, NULL, NULL, NULL, &nosync,
// &norange, NULL, NULL);
// } catch (error_c error) {
// fprintf(stderr, "FATAL: vorbis_packetizer: Could not create an " \
// "ogm_reader for the temporary file.\n%s\n", error.get_error());
// exit(1);
// }
// ogm_reader->overwrite_eos(1);
// memcpy(&nosync, &async, sizeof(audio_sync_t));
// async.displacement = 0;
// async.linear = 1.0;
// status = ogm_reader->read();
// mpage = ogm_reader->get_header_page();
// free(mpage->og->header);
// free(mpage->og->body);
// free(mpage->og);
// free(mpage);
// skip_packets = 2;
// old_packetizer = ogm_reader->set_packetizer(this);
// while (status == EMOREDATA)
// status = ogm_reader->read();
// ogm_reader->set_packetizer(old_packetizer);
// delete ogm_reader;
// verbose = old_verbose;
// unlink(tmpname);
// memcpy(&async, &nosync, sizeof(audio_sync_t));
}
#define AVORBIS "A_VORBIS"
void vorbis_packetizer_c::set_header() {
using namespace LIBMATROSKA_NAMESPACE;
if (kax_last_entry == NULL)
track_entry =
&GetChild<KaxTrackEntry>(static_cast<KaxTracks &>(*kax_tracks));
else
track_entry =
&GetNextChild<KaxTrackEntry>(static_cast<KaxTracks &>(*kax_tracks),
static_cast<KaxTrackEntry &>(*kax_last_entry));
kax_last_entry = track_entry;
if (serialno == -1)
serialno = track_number++;
KaxTrackNumber &tnumber =
GetChild<KaxTrackNumber>(static_cast<KaxTrackEntry &>(*track_entry));
*(static_cast<EbmlUInteger *>(&tnumber)) = serialno;
*(static_cast<EbmlUInteger *>
(&GetChild<KaxTrackType>(static_cast<KaxTrackEntry &>(*track_entry)))) =
track_audio;
KaxCodecID &codec_id =
GetChild<KaxCodecID>(static_cast<KaxTrackEntry &>(*track_entry));
codec_id.CopyBuffer((binary *)AVORBIS, countof(AVORBIS));
KaxTrackAudio &track_audio =
GetChild<KaxTrackAudio>(static_cast<KaxTrackEntry &>(*track_entry));
KaxAudioSamplingFreq &kax_freq = GetChild<KaxAudioSamplingFreq>(track_audio);
*(static_cast<EbmlFloat *>(&kax_freq)) = (float)vi.rate;
KaxAudioChannels &kax_chans = GetChild<KaxAudioChannels>(track_audio);
*(static_cast<EbmlUInteger *>(&kax_chans)) = vi.channels;
}
/*
* Some notes - processing is straight-forward if no AV synchronization
* is needed - the packet is simply handed over to ogg_stream_packetin.
* Unfortunately things are not that easy if AV sync is done. For a
* negative displacement packets are simply discarded if their granulepos
* is set before the displacement. For positive displacements the packetizer
* has to generate silence and insert this silence just after the first
* three stream packets - the Vorbis header, the comment and the
* setup packets.
* The creation of the silence is done by encoding 0 samples with
* libvorbis. This produces an OGG file that is read by a separate
* ogm_reader_c. We set this very packetizer as the reader's packetizer
* so that we get the packets we want from the 'silenced' file. This means
* skipping the very first three packets, hence the 'skip_packets' variable.
*/
int vorbis_packetizer_c::process(char *data, int size, int64_t timecode) {
ogg_packet op;
/*
* We might want to skip a certain amount of packets if this packetizer
* is used by a second ogm_reader_c, one that reads from a 'silence'
* file. skip_packets is then intially set to 3 in order to skip all
* header packets.
*/
// if (skip_packets > 0) {
// skip_packets--;
// return EMOREDATA;
// }
op.packet = (unsigned char *)data;
op.bytes = size;
fprintf(stdout, "packet_bs: %ld\n", vorbis_packet_blocksize(&vi, &op));
// Recalculate the timecode if needed.
if (timecode == -1)
die("timecode = -1");
// Handle the displacement.
timecode += async.displacement;
// Handle the linear sync - simply multiply with the given factor.
timecode = (int64_t)((double)timecode * async.linear);
// // range checking
// if ((timecode >= range.start) &&
// (last_granulepos_seen >= range.start) &&
// ((range.end == 0) || (op->granulepos <= range.end))) {
// // Adjust the granulepos
// op->granulepos = (u_int64_t)(op->granulepos - range.start);
// // If no or a positive displacement is set the packet has to be output.
// if (async.displacement >= 0) {
// ogg_stream_packetin(&os, op);
// packetno++;
// }
// /*
// * Only output the current packet if its granulepos ( = position in
// * samples) is bigger than the displacement.
// */
// else if (op->granulepos > 0) {
// ogg_stream_packetin(&os, op);
// packetno++;
// }
// queue_pages();
// last_granulepos = op->granulepos;
// } else if (op->e_o_s) {
add_packet(data, size, (u_int64_t)timecode);
return EMOREDATA;
}
#endif // HAVE_OGGVORBIS

65
p_vorbis.h Normal file
View File

@ -0,0 +1,65 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
p_vorbis.h
Written by Moritz Bunkus <moritz@bunkus.org>
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
*/
/*!
\file
\version \$Id: p_vorbis.h,v 1.1 2003/03/03 18:00:30 mosu Exp $
\brief class definition for the Vorbis packetizer
\author Moritz Bunkus <moritz @ bunkus.org>
*/
#include "config.h"
#ifdef HAVE_OGGVORBIS
#ifndef __P_VORBIS_H
#define __P_VORBIS_H
#include <ogg/ogg.h>
#include <vorbis/codec.h>
#include "common.h"
#include "pr_generic.h"
#include "queue.h"
class vorbis_packetizer_c: public q_c {
private:
ogg_int64_t old_granulepos;
ogg_int64_t ogran;
ogg_int64_t last_granulepos;
ogg_int64_t last_granulepos_seen;
int packetno;
audio_sync_t async;
range_t range;
vorbis_info vi;
vorbis_comment vc;
ogg_packet headers[3];
public:
vorbis_packetizer_c(audio_sync_t *nasync, range_t *nrange,
void *d_header, int l_header, void *d_comments,
int l_comments, void *d_codecsetup, int l_codecsetup)
throw (error_c);
virtual ~vorbis_packetizer_c();
virtual int process(char *data, int size, int64_t timecode);
virtual void set_header();
private:
virtual void setup_displacement();
virtual int encode_silence(int fd);
};
#endif // __P_VORBIS_H
#endif // HAVE_OGGVORBIS

192
r_ogm.cpp
View File

@ -13,7 +13,7 @@
/*!
\file
\version \$Id: r_ogm.cpp,v 1.4 2003/03/03 14:39:03 mosu Exp $
\version \$Id: r_ogm.cpp,v 1.5 2003/03/03 18:00:30 mosu Exp $
\brief OGG media stream reader
\author Moritz Bunkus <moritz @ bunkus.org>
*/
@ -29,12 +29,16 @@
#include <ogg/ogg.h>
#include <vorbis/codec.h>
extern "C" { // for BITMAPINFOHEADER
#include "avilib.h"
}
#include "common.h"
#include "pr_generic.h"
#include "ogmstreams.h"
#include "queue.h"
#include "r_ogm.h"
//#include "p_vorbis.h"
#include "p_vorbis.h"
#include "p_video.h"
#include "p_pcm.h"
//#include "p_textsubs.h"
@ -195,7 +199,7 @@ void ogm_reader_c::free_demuxer(int idx) {
int i;
ogm_demuxer_t *dmx;
if (idx < num_sdemuxers)
if (idx >= num_sdemuxers)
return;
dmx = sdemuxers[idx];
for (i = 0; i < 3; i++)
@ -255,11 +259,13 @@ void ogm_reader_c::add_new_demuxer(ogm_demuxer_t *dmx) {
}
void ogm_reader_c::create_packetizers() {
BITMAPINFOHEADER bih;
char *codec;
stream_header *sth;
int i;
ogm_demuxer_t *dmx;
memset(&bih, 0, sizeof(BITMAPINFOHEADER));
i = 0;
while (i < num_sdemuxers) {
dmx = sdemuxers[i];
@ -271,23 +277,32 @@ void ogm_reader_c::create_packetizers() {
codec = sth->subtype;
else
codec = fourcc;
// AVI compatibility mode. Fill in the values we've got and guess
// the others.
bih.bi_size = sizeof(BITMAPINFOHEADER);
bih.bi_width = sth->sh.video.width;
bih.bi_height = sth->sh.video.height;
bih.bi_planes = 1;
bih.bi_bit_count = 24;
memcpy(&bih.bi_compression, codec, 4);
bih.bi_size_image = sth->sh.video.width * sth->sh.video.height * 3;
try {
dmx->packetizer =
new video_packetizer_c(NULL, 0, codec,
new video_packetizer_c(&bih, sizeof(BITMAPINFOHEADER), codec,
(double)10000000 / (double)sth->time_unit,
sth->sh.video.width, sth->sh.video.height,
sth->bits_per_sample, sth->buffersize, NULL,
&range, 1);
} catch (error_c error) {
fprintf(stderr, "Fatal: ogm_reader: could not initialize video " \
"packetizer for stream id %d. Will try to continue and " \
} catch (error_c &error) {
fprintf(stderr, "Fatal: ogm_reader: could not initialize video "
"packetizer for stream id %d. Will try to continue and "
"ignore this stream.\n", numstreams);
free(dmx);
continue;
}
if (verbose)
fprintf(stdout, "OGG/OGM demultiplexer (%s): using video output " \
fprintf(stdout, "OGG/OGM demultiplexer (%s): using video output "
"module for stream %d.\n", filename, numstreams);
break;
@ -298,16 +313,16 @@ void ogm_reader_c::create_packetizers() {
new pcm_packetizer_c(NULL, 0, sth->samples_per_unit,
sth->sh.audio.channels,
sth->bits_per_sample, &async, &range);
} catch (error_c error) {
fprintf(stderr, "Fatal: ogm_reader: could not initialize PCM " \
"packetizer for stream id %d. Will try to continue and " \
} catch (error_c &error) {
fprintf(stderr, "Fatal: ogm_reader: could not initialize PCM "
"packetizer for stream id %d. Will try to continue and "
"ignore this stream.\n", numstreams);
free_demuxer(i);
continue;
}
if (verbose)
fprintf(stdout, "OGG/OGM demultiplexer (%s): using PCM output " \
fprintf(stdout, "OGG/OGM demultiplexer (%s): using PCM output "
"module for stream %d.\n", filename, numstreams);
break;
@ -318,16 +333,16 @@ void ogm_reader_c::create_packetizers() {
sth->sh.audio.channels,
sth->sh.audio.avgbytespersec * 8 / 1000,
&async, &range);
} catch (error_c error) {
fprintf(stderr, "Fatal: ogm_reader: could not initialize MP3 " \
"packetizer for stream id %d. Will try to continue and " \
} catch (error_c &error) {
fprintf(stderr, "Fatal: ogm_reader: could not initialize MP3 "
"packetizer for stream id %d. Will try to continue and "
"ignore this stream.\n", numstreams);
free_demuxer(i);
continue;
}
if (verbose)
fprintf(stdout, "OGG/OGM demultiplexer (%s): using MP3 output " \
fprintf(stdout, "OGG/OGM demultiplexer (%s): using MP3 output "
"module for stream %d.\n", filename, numstreams);
break;
@ -338,21 +353,39 @@ void ogm_reader_c::create_packetizers() {
sth->sh.audio.channels,
sth->sh.audio.avgbytespersec * 8 / 1000,
&async, &range);
} catch (error_c error) {
fprintf(stderr, "FATAL: ogm_reader: could not initialize AC3 " \
"packetizer for stream id %d. Will try to continue and " \
} catch (error_c &error) {
fprintf(stderr, "FATAL: ogm_reader: could not initialize AC3 "
"packetizer for stream id %d. Will try to continue and "
"ignore this stream.\n", numstreams);
free_demuxer(i);
continue;
}
if (verbose)
fprintf(stdout, "OGG/OGM demultiplexer (%s): using AC3 output " \
fprintf(stdout, "OGG/OGM demultiplexer (%s): using AC3 output "
"module for stream %d.\n", filename, numstreams);
break;
case OGM_STREAM_TYPE_VORBIS:
try {
dmx->packetizer =
new vorbis_packetizer_c(&async, &range,
dmx->packet_data[0], dmx->packet_sizes[0],
dmx->packet_data[1], dmx->packet_sizes[1],
dmx->packet_data[2], dmx->packet_sizes[2]);
} catch (error_c &error) {
fprintf(stderr, "FATAL: ogm_reader: could not initialize Vorbis "
"packetizer for stream id %d. Will try to continue and "
"ignore this stream.\n", numstreams);
free_demuxer(i);
continue;
}
if (verbose)
fprintf(stdout, "OGG/OGM demultiplexer (%s): using Vorbis output "
"module for stream %d.\n", filename, numstreams);
break;
}
i++;
@ -390,7 +423,7 @@ void ogm_reader_c::handle_new_stream(ogg_page *og) {
u_int32_t codec_id;
if (ogg_stream_init(&new_oss, ogg_page_serialno(og))) {
fprintf(stderr, "Fatal: ogm_reader: ogg_stream_init for stream number " \
fprintf(stderr, "Fatal: ogm_reader: ogg_stream_init for stream number "
"%d failed. Will try to continue and ignore this stream.",
numstreams + 1);
return;
@ -422,36 +455,22 @@ void ogm_reader_c::handle_new_stream(ogg_page *og) {
ogg_stream_clear(&new_oss);
return;
}
fprintf(stderr, "Warning: ogm_reader: No Vorbis support at the moment. "
"Ignoring stream id %d.\n", numstreams);
// try {
// dmx->packetizer = new vorbis_packetizer_c(&async, &range, comments);
// } catch (error_c error) {
// fprintf(stderr, "Fatal: ogm_reader: could not initialize Vorbis " \
// "packetizer for stream id %d. Will try to continue and " \
// "ignore this stream.\n", numstreams);
// free(dmx);
// ogg_stream_clear(&new_oss);
// return;
// }
// dmx->stype = OGM_STREAM_TYPE_VORBIS;
// dmx->serial = ogg_page_serialno(og);
// memcpy(&dmx->os, &new_oss, sizeof(ogg_stream_state));
// dmx->sid = nastreams;
// add_new_demuxer(dmx);
// if (verbose)
// fprintf(stdout, "OGG/OGM demultiplexer (%s): using Vorbis audio " \
// "output module for stream %d.\n", filename, numstreams);
// do {
// ((vorbis_packetizer_c *)dmx->packetizer)->
// process(&op, ogg_page_granulepos(og));
// if (op.e_o_s) {
// dmx->packetizer->flush_pages();
// dmx->eos = 1;
// return;
// }
// } while (ogg_stream_packetout(&dmx->os, &op));
nastreams++;
numstreams++;
if (!demuxing_requested(vstreams, nvstreams)) {
ogg_stream_clear(&new_oss);
free(dmx->packet_data[0]);
free(dmx);
return;
}
dmx->stype = OGM_STREAM_TYPE_VORBIS;
dmx->serial = ogg_page_serialno(og);
memcpy(&dmx->os, &new_oss, sizeof(ogg_stream_state));
dmx->sid = nastreams;
add_new_demuxer(dmx);
return;
}
@ -536,8 +555,8 @@ void ogm_reader_c::handle_new_stream(ogg_page *og) {
// dmx->packetizer =
// new textsubs_packetizer_c(&async, &range, comments);
// } catch (error_c error) {
// fprintf(stderr, "FATAL: ogm_reader: could not initialize text " \
// "subtitle packetizer for stream id %d. Will try to " \
// fprintf(stderr, "FATAL: ogm_reader: could not initialize text "
// "subtitle packetizer for stream id %d. Will try to "
// "continue and ignore this stream.\n", numstreams);
// free(dmx);
// ogg_stream_clear(&new_oss);
@ -550,7 +569,7 @@ void ogm_reader_c::handle_new_stream(ogg_page *og) {
// dmx->sid = ntstreams;
// add_new_demuxer(dmx);
// if (verbose)
// fprintf(stdout, "OGG/OGM demultiplexer (%s): using text subtitle " \
// fprintf(stdout, "OGG/OGM demultiplexer (%s): using text subtitle "
// "output module for stream %d.\n", filename, numstreams);
return;
@ -602,66 +621,57 @@ void ogm_reader_c::process_page(ogg_page *og) {
if (o_eos)
op.e_o_s = 0;
switch (dmx->stype) {
// case OGM_STREAM_TYPE_VORBIS:
// ((vorbis_packetizer_c *)dmx->packetizer)->
// process(&op, ogg_page_granulepos(og));
// break;
if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
switch (dmx->stype) {
case OGM_STREAM_TYPE_VORBIS:
((vorbis_packetizer_c *)dmx->packetizer)->
process((char *)op.packet, op.bytes, ogg_page_granulepos(og));
break;
case OGM_STREAM_TYPE_VIDEO:
if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
case OGM_STREAM_TYPE_VIDEO:
((video_packetizer_c *)dmx->packetizer)->
process((char *)&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen,
hdrlen > 0 ? lenbytes : 1,
*op.packet & PACKET_IS_SYNCPOINT, op.e_o_s);
dmx->units_processed += (hdrlen > 0 ? lenbytes : 1);
}
break;
break;
case OGM_STREAM_TYPE_PCM:
if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
case OGM_STREAM_TYPE_PCM:
((pcm_packetizer_c *)dmx->packetizer)->
process((char *)&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen,
op.e_o_s);
dmx->units_processed += op.bytes - 1;
}
break;
break;
case OGM_STREAM_TYPE_MP3: // MP3
if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
case OGM_STREAM_TYPE_MP3: // MP3
((mp3_packetizer_c *)dmx->packetizer)->
process((char *)&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen,
op.e_o_s);
dmx->units_processed += op.bytes - 1;
}
break;
break;
case OGM_STREAM_TYPE_AC3: // AC3
if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
case OGM_STREAM_TYPE_AC3: // AC3
((ac3_packetizer_c *)dmx->packetizer)->
process((char *)&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen,
op.e_o_s);
dmx->units_processed += op.bytes - 1;
}
break;
break;
// case OGM_STREAM_TYPE_TEXT: // text subtitles
// if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
// ((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
// char *subs = (char *)&op.packet[1 + hdrlen];
// if ((*subs != 0) && (*subs != '\n') && (*subs != '\r') &&
// strcmp(subs, " ")) {
// ((textsubs_packetizer_c *)dmx->packetizer)->
// process(op.granulepos, op.granulepos + lenbytes, subs,
// op.e_o_s);
// dmx->units_processed++;
// case OGM_STREAM_TYPE_TEXT: // text subtitles
// if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
// ((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
// char *subs = (char *)&op.packet[1 + hdrlen];
// if ((*subs != 0) && (*subs != '\n') && (*subs != '\r') &&
// strcmp(subs, " ")) {
// ((textsubs_packetizer_c *)dmx->packetizer)->
// process(op.granulepos, op.granulepos + lenbytes, subs,
// op.e_o_s);
// dmx->units_processed++;
// }
// }
// }
// break;
// break;
}
}
if (eos) {