From a0f0cfbedc0c2eb744418ab2503faa8bf74d3e24 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Mon, 3 Mar 2003 18:00:30 +0000 Subject: [PATCH] Added a first Vorbis support including the packetizers. --- Makefile.am | 1 + error.h | 5 +- p_vorbis.cpp | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++ p_vorbis.h | 65 ++++++++++ r_ogm.cpp | 192 ++++++++++++++++-------------- 5 files changed, 496 insertions(+), 94 deletions(-) create mode 100644 p_vorbis.cpp create mode 100644 p_vorbis.h diff --git a/Makefile.am b/Makefile.am index 12162130b..d35e55885 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/error.h b/error.h index 908e2390a..e80141099 100644 --- a/error.h +++ b/error.h @@ -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 */ @@ -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; }; }; diff --git a/p_vorbis.cpp b/p_vorbis.cpp new file mode 100644 index 000000000..91738a308 --- /dev/null +++ b/p_vorbis.cpp @@ -0,0 +1,327 @@ +/* + mkvmerge -- utility for splicing together matroska files + from component media subtypes + + p_vorbis.h + + Written by Moritz Bunkus + + 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 +*/ + +#include "config.h" + +#ifdef HAVE_OGGVORBIS + +#include +#include +#include +#include +#include + +#include +#include + +#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 +#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(static_cast(*kax_tracks)); + else + track_entry = + &GetNextChild(static_cast(*kax_tracks), + static_cast(*kax_last_entry)); + kax_last_entry = track_entry; + + if (serialno == -1) + serialno = track_number++; + KaxTrackNumber &tnumber = + GetChild(static_cast(*track_entry)); + *(static_cast(&tnumber)) = serialno; + + *(static_cast + (&GetChild(static_cast(*track_entry)))) = + track_audio; + + KaxCodecID &codec_id = + GetChild(static_cast(*track_entry)); + codec_id.CopyBuffer((binary *)AVORBIS, countof(AVORBIS)); + + KaxTrackAudio &track_audio = + GetChild(static_cast(*track_entry)); + + KaxAudioSamplingFreq &kax_freq = GetChild(track_audio); + *(static_cast(&kax_freq)) = (float)vi.rate; + + KaxAudioChannels &kax_chans = GetChild(track_audio); + *(static_cast(&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 diff --git a/p_vorbis.h b/p_vorbis.h new file mode 100644 index 000000000..2eb62fae0 --- /dev/null +++ b/p_vorbis.h @@ -0,0 +1,65 @@ +/* + mkvmerge -- utility for splicing together matroska files + from component media subtypes + + p_vorbis.h + + Written by Moritz Bunkus + + 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 +*/ + +#include "config.h" + +#ifdef HAVE_OGGVORBIS + +#ifndef __P_VORBIS_H +#define __P_VORBIS_H + +#include +#include + +#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 diff --git a/r_ogm.cpp b/r_ogm.cpp index 78541ae40..eb755dfac 100644 --- a/r_ogm.cpp +++ b/r_ogm.cpp @@ -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 */ @@ -29,12 +29,16 @@ #include #include +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) {