diff --git a/src/p_ac3.cpp b/src/p_ac3.cpp index c31dade9d..db39649b8 100644 --- a/src/p_ac3.cpp +++ b/src/p_ac3.cpp @@ -187,3 +187,68 @@ void ac3_packetizer_c::dump_debug_info() { mxprint(stderr, "DBG> ac3_packetizer_c: queue: %d; buffer size: %d\n", packet_queue.size(), buffer_size); } + +ac3_bs_packetizer_c::ac3_bs_packetizer_c(generic_reader_c *nreader, + unsigned long nsamples_per_sec, + int nchannels, track_info_t *nti) + throw (error_c): ac3_packetizer_c(nreader, nsamples_per_sec, nchannels, + nti) { + bsb_present = false; +} + +static bool warning_printed = false; + +void ac3_bs_packetizer_c::add_to_buffer(unsigned char *buf, int size) { + unsigned char *new_buffer, *dptr, *sendptr, *sptr; + int size_add; + bool new_bsb_present; + + if (((size % 2) == 1) && !warning_printed) { + mxprint(stdout, "WARNING! Untested code. If mkvmerge crashes, " + "or if the resulting file does not contain the complete and " + "correct audio track, then please contact the author, Moritz " + "Bunkus, at moritz@bunkus.org.\n"); + warning_printed = true; + } + + if (bsb_present) { + size_add = 1; + sendptr = buf + size + 1; + } else { + size_add = 0; + sendptr = buf + size; + } + size_add += size; + if ((size_add % 2) == 1) { + size_add--; + sendptr--; + new_bsb_present = true; + } else + new_bsb_present = false; + + new_buffer = (unsigned char *)saferealloc(packet_buffer, buffer_size + + size_add); + dptr = new_buffer + buffer_size; + sptr = buf; + + if (bsb_present) { + dptr[1] = bsb; + dptr[0] = sptr[0]; + sptr++; + dptr += 2; + } + + while (sptr < sendptr) { + dptr[0] = sptr[1]; + dptr[1] = sptr[0]; + dptr += 2; + sptr += 2; + } + + if (new_bsb_present) + bsb = *sptr; + bsb_present = new_bsb_present; + packet_buffer = new_buffer; + buffer_size += size_add; +} + diff --git a/src/p_ac3.h b/src/p_ac3.h index 7453fe365..7d26bd335 100644 --- a/src/p_ac3.h +++ b/src/p_ac3.h @@ -28,7 +28,7 @@ #include "ac3_common.h" class ac3_packetizer_c: public generic_packetizer_c { -private: +protected: int64_t bytes_output, packetno; unsigned long samples_per_sec; int channels, buffer_size; @@ -44,7 +44,7 @@ public: int64_t fref = -1); virtual void set_headers(); -private: +protected: virtual void add_to_buffer(unsigned char *buf, int size); virtual unsigned char *get_ac3_packet(unsigned long *header, ac3_header_t *ac3header); @@ -54,4 +54,18 @@ private: virtual void dump_debug_info(); }; +class ac3_bs_packetizer_c: public ac3_packetizer_c { +protected: + unsigned char bsb; + bool bsb_present; + +public: + ac3_bs_packetizer_c(generic_reader_c *nreader, + unsigned long nsamples_per_sec, + int nchannels, track_info_t *nti) throw (error_c); + +protected: + virtual void add_to_buffer(unsigned char *buf, int size); +}; + #endif // __P_AC3_H diff --git a/src/r_real.cpp b/src/r_real.cpp index 57d61aa0e..0076e9a62 100644 --- a/src/r_real.cpp +++ b/src/r_real.cpp @@ -28,6 +28,7 @@ #include "common.h" #include "error.h" #include "r_real.h" +#include "p_ac3.h" #include "p_passthrough.h" #include "p_video.h" @@ -424,23 +425,33 @@ void real_reader_c::create_packetizers() { char buffer[20]; passthrough_packetizer_c *ptzr; - ptzr = new passthrough_packetizer_c(this, ti); - dmx->packetizer = ptzr; + if (!strncmp(dmx->fourcc, "dnet", 4)) { + dmx->packetizer = + new ac3_bs_packetizer_c(this, dmx->samples_per_second, dmx->channels, + ti); + if (verbose) + mxprint(stdout, "+-> Using AC3 output module for stream " + "%u (FourCC: %s).\n", dmx->id, dmx->fourcc); - sprintf(buffer, "A_REAL/%c%c%c%c", toupper(dmx->fourcc[0]), - toupper(dmx->fourcc[1]), toupper(dmx->fourcc[2]), - toupper(dmx->fourcc[3])); + } else { + ptzr = new passthrough_packetizer_c(this, ti); + dmx->packetizer = ptzr; - ptzr->set_track_type(track_audio); - ptzr->set_codec_id(buffer); - ptzr->set_codec_private(dmx->private_data, dmx->private_size); - ptzr->set_audio_sampling_freq((float)dmx->samples_per_second); - ptzr->set_audio_channels(dmx->channels); - ptzr->set_audio_bit_depth(dmx->bits_per_sample); + sprintf(buffer, "A_REAL/%c%c%c%c", toupper(dmx->fourcc[0]), + toupper(dmx->fourcc[1]), toupper(dmx->fourcc[2]), + toupper(dmx->fourcc[3])); - if (verbose) - mxprint(stdout, "+-> Using generic audio output module for stream %u " - "(FourCC: %s).\n", dmx->id, dmx->fourcc); + ptzr->set_track_type(track_audio); + ptzr->set_codec_id(buffer); + ptzr->set_codec_private(dmx->private_data, dmx->private_size); + ptzr->set_audio_sampling_freq((float)dmx->samples_per_second); + ptzr->set_audio_channels(dmx->channels); + ptzr->set_audio_bit_depth(dmx->bits_per_sample); + + if (verbose) + mxprint(stdout, "+-> Using generic audio output module for stream " + "%u (FourCC: %s).\n", dmx->id, dmx->fourcc); + } } dmx->packetizer->duplicate_data_on_add(false);