int DVDGraph::check_spdif_passthrough(Speakers _spk) const { // SPDIF-1 check (passthrough) if (!use_spdif) return SPDIF_MODE_DISABLED; // check format if ((spdif_pt & FORMAT_MASK(_spk.format)) == 0) return SPDIF_ERR_FORMAT; // check sample rate if (spdif_check_sr && _spk.sample_rate) if ((!spdif_allow_48 || _spk.sample_rate != 48000) && (!spdif_allow_44 || _spk.sample_rate != 44100) && (!spdif_allow_32 || _spk.sample_rate != 32000)) return SPDIF_ERR_SAMPLE_RATE; // check sink if (sink && query_sink && !spdif_as_pcm) if (!sink->query_input(Speakers(FORMAT_SPDIF, _spk.mask, _spk.sample_rate))) return SPDIF_ERR_SINK; return SPDIF_MODE_PASSTHROUGH; }
void speed_noise() { ///////////////////////////////////////////////////////// // Noise speed test Chunk in, out; NoiseGen noise(Speakers(FORMAT_SPDIF, 0, 0), seed, noise_size, noise_size); noise.get_chunk(in); CPUMeter cpu; cpu.reset(); cpu.start(); int runs = 0; int data_chunks = 0; int empty_chunks = 0; while (cpu.get_thread_time() < time_per_test) { runs++; despdifer.reset(); while (despdifer.process(in, out)) /*do nothing*/; } cpu.stop(); log->msg("Despdifer speed on noise: %iMB/s", int(double(noise_size) * runs / cpu.get_thread_time() / 1000000)); }
void speed_file(const char *file_name) { ///////////////////////////////////////////////////////// // File speed test Chunk in, out; RAWSource f(Speakers(FORMAT_RAWDATA, 0, 0), file_name); if (!f.is_open()) { log->err("Cannot open file %s", file_name); return; } CPUMeter cpu; cpu.reset(); cpu.start(); int runs = 0; int data_chunks = 0; int empty_chunks = 0; while (cpu.get_thread_time() < time_per_test) { runs++; f.reset(); despdifer.reset(); while (f.get_chunk(in)) while (despdifer.process(in, out)) /*do nothing*/; } cpu.stop(); log->msg("Despdifer speed on file %s: %iMB/s", file_name, int(double(f.size()) * runs / cpu.get_thread_time() / 1000000)); }
bool Spdif2PCM::get_chunk(Chunk *_chunk) { send_chunk_inplace(_chunk, size); if (_chunk->spk.format == FORMAT_SPDIF) _chunk->spk = Speakers(FORMAT_PCM16, MODE_STEREO, spk.sample_rate); return true; }
Speakers Spdif2PCM::get_output() const { if (spk.format == FORMAT_SPDIF) return Speakers(FORMAT_PCM16, MODE_STEREO, spk.sample_rate); else return spk; }
void transform() { ///////////////////////////////////////////////////////// // Transform test // spdif stream -> raw stream compare_file(log, Speakers(FORMAT_SPDIF, 0, 0), "a.mp2.005.spdif", &despdifer, "a.mp2.005.mp2"); compare_file(log, Speakers(FORMAT_SPDIF, 0, 0), "a.mp2.002.spdif", &despdifer, "a.mp2.002.mp2"); compare_file(log, Speakers(FORMAT_SPDIF, 0, 0), "a.ac3.03f.spdif", &despdifer, "a.ac3.03f.ac3"); compare_file(log, Speakers(FORMAT_SPDIF, 0, 0), "a.ac3.005.spdif", &despdifer, "a.ac3.005.ac3"); compare_file(log, Speakers(FORMAT_SPDIF, 0, 0), "a.dts.03f.spdif", &despdifer, "a.dts.03f.dts"); compare_file(log, Speakers(FORMAT_RAWDATA, 0, 0), "a.mad.mix.spdif", &despdifer, "a.mad.mix.mad"); }
int DVDGraph::check_spdif_encode(Speakers _spk) const { // SPDIF-2 check (encode) if (!use_spdif) return SPDIF_MODE_DISABLED; if (!spdif_encode) return SPDIF_ERR_ENCODER_DISABLED; // determine encoder's input format Speakers enc_spk = proc.user2output(_spk, user_spk); if (enc_spk.is_unknown()) return SPDIF_ERR_PROC; enc_spk.format = FORMAT_LINEAR; enc_spk.level = 1.0; // do not encode stereo PCM if (spdif_stereo_pt && (enc_spk.mask == MODE_STEREO || enc_spk.mask == MODE_MONO)) return SPDIF_ERR_STEREO_PCM; // check sample rate if (spdif_check_sr && enc_spk.sample_rate) if ((!spdif_allow_48 || enc_spk.sample_rate != 48000) && (!spdif_allow_44 || enc_spk.sample_rate != 44100) && (!spdif_allow_32 || enc_spk.sample_rate != 32000)) return SPDIF_ERR_SAMPLE_RATE; // check encoder if (!enc.query_input(enc_spk)) return SPDIF_ERR_ENCODER; // check sink if (sink && query_sink && !spdif_as_pcm) if (!sink->query_input(Speakers(FORMAT_SPDIF, enc_spk.mask, enc_spk.sample_rate))) return SPDIF_ERR_SINK; return SPDIF_MODE_ENCODE; }
DVDGraph::DVDGraph(int _nsamples, const Sink *_sink) :FilterGraph(-1), proc(_nsamples) { user_spk = Speakers(FORMAT_PCM16, 0, 0); use_spdif = false; use_detector = false; spdif_pt = FORMAT_MASK_AC3; spdif_as_pcm = false; spdif_encode = true; spdif_stereo_pt = true; spdif_bitrate = 640000; spdif_check_sr = false; spdif_allow_48 = true; spdif_allow_44 = false; spdif_allow_32 = false; spdif_status = SPDIF_MODE_NONE; spdif_err = SPDIF_MODE_NONE; sink = _sink; query_sink = true; };
{ 0x77, 0x0b, 0x00, 0x00, 0x41, 0x85, 0x00, 0xa0 }, // 10 00 0101 0100 0 001 101 0 0000 { 0x77, 0x0b, 0x00, 0x00, 0x4a, 0x08, 0x00, 0xc0 }, // 00 00 1000 0100 1 010 110 0 0000 { 0x77, 0x0b, 0x00, 0x00, 0x53, 0x49, 0x00, 0xe0 }, // 01 00 1001 0101 0 011 111 0 0000 { 0x77, 0x0b, 0x00, 0x00, 0x58, 0x90, 0x00, 0x10 }, // 10 01 0000 0101 1 000 000 1 0000 { 0x77, 0x0b, 0x00, 0x00, 0x41, 0x11, 0x00, 0x30 }, // 00 01 0001 0100 0 001 001 1 0000 { 0x77, 0x0b, 0x00, 0x00, 0x42, 0x60, 0x00, 0x44 }, // 01 10 0000 0100 0 010 010 0 0100 { 0x77, 0x0b, 0x00, 0x00, 0x4b, 0xa1, 0x00, 0x64 }, // 10 10 0001 0100 1 011 011 0 0100 { 0x77, 0x0b, 0x00, 0x00, 0x50, 0x22, 0x00, 0x84 }, // 00 10 0010 0101 0 000 100 0 0100 { 0x77, 0x0b, 0x00, 0x00, 0x59, 0x63, 0x00, 0xa1 }, // 01 10 0011 0101 1 001 101 0 0001 { 0x77, 0x0b, 0x00, 0x00, 0x42, 0xa4, 0x00, 0xc4 }, // 10 10 0100 0100 0 010 110 0 0100 { 0x77, 0x0b, 0x00, 0x00, 0x43, 0x25, 0x00, 0xe1 }, // 00 10 0101 0100 0 011 111 0 0001 }; static const Speakers good_spk[] = { Speakers(FORMAT_AC3, MODE_2_0, 48000), Speakers(FORMAT_AC3, MODE_1_0, 22050), Speakers(FORMAT_AC3, MODE_2_0, 8000), Speakers(FORMAT_AC3, MODE_3_0, 6000), Speakers(FORMAT_AC3, MODE_2_1, 44100), Speakers(FORMAT_AC3, MODE_3_1, 32000), Speakers(FORMAT_AC3, MODE_2_2, 24000), Speakers(FORMAT_AC3, MODE_3_2, 11025), Speakers(FORMAT_AC3, MODE_2_0 | CH_MASK_LFE, 4000), Speakers(FORMAT_AC3, MODE_1_0 | CH_MASK_LFE, 48000), Speakers(FORMAT_AC3, MODE_2_0 | CH_MASK_LFE, 44100), Speakers(FORMAT_AC3, MODE_3_0 | CH_MASK_LFE, 16000), Speakers(FORMAT_AC3, MODE_2_1 | CH_MASK_LFE, 12000), Speakers(FORMAT_AC3, MODE_3_1 | CH_MASK_LFE, 5512), Speakers(FORMAT_AC3, MODE_2_2 | CH_MASK_LFE, 32000), Speakers(FORMAT_AC3, MODE_3_2 | CH_MASK_LFE, 48000),
bool mt2spk(CMediaType mt, Speakers &spk) { const GUID type = *mt.Type(); const GUID subtype = *mt.Subtype(); const GUID formattype = *mt.FormatType(); WAVEFORMAT *wf = 0; size_t wf_size = 0; int sample_rate = 0; if ((formattype == FORMAT_WaveFormatEx) && (mt.FormatLength() > sizeof(WAVEFORMAT))) { wf = (WAVEFORMAT *)mt.Format(); wf_size = mt.FormatLength(); sample_rate = wf->nSamplesPerSec; } ///////////////////////////////////////////////////////// // HD LPCM if (type == MEDIATYPE_Audio && subtype == MEDIASUBTYPE_HDMV_LPCM_AUDIO && wf && wf->wFormatTag == 1) { spk = wf2spk(wf, wf_size); switch (spk.format) { case FORMAT_PCM16: spk.format = FORMAT_PCM16_BE; return true; case FORMAT_PCM24: spk.format = FORMAT_PCM24_BE; return true; case FORMAT_PCM32: spk.format = FORMAT_PCM32_BE; return true; default: return false; } } ///////////////////////////////////////////////////////// // Compressed formats if (type == MEDIATYPE_MPEG2_PES || type == MEDIATYPE_MPEG2_PACK || type == MEDIATYPE_DVD_ENCRYPTED_PACK) if (subtype == MEDIASUBTYPE_DOLBY_AC3 || subtype == MEDIASUBTYPE_DTS || subtype == MEDIASUBTYPE_MPEG1AudioPayload || subtype == MEDIASUBTYPE_MPEG2_AUDIO || subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO) { spk = Speakers(FORMAT_PES, 0, sample_rate); return true; } if (subtype == MEDIASUBTYPE_DOLBY_AC3 || subtype == MEDIASUBTYPE_AVI_AC3) { // It may be AC3 or EAC3 spk = Speakers(FORMAT_DOLBY, 0, sample_rate); return true; } if (subtype == MEDIASUBTYPE_DOLBY_DDPLUS) { spk = Speakers(FORMAT_EAC3, 0, sample_rate); return true; } if (subtype == MEDIASUBTYPE_DOLBY_TRUEHD) { spk = Speakers(FORMAT_TRUEHD, 0, sample_rate); return true; } if (subtype == MEDIASUBTYPE_DTS || subtype == MEDIASUBTYPE_DTS_HD || subtype == MEDIASUBTYPE_AVI_DTS) { spk = Speakers(FORMAT_DTS, 0, sample_rate); return true; } if (subtype == MEDIASUBTYPE_MPEG1AudioPayload || subtype == MEDIASUBTYPE_MPEG2_AUDIO) { spk = Speakers(FORMAT_MPA, 0, sample_rate); return true; } if (subtype == MEDIASUBTYPE_DOLBY_AC3_SPDIF) { spk = Speakers(FORMAT_SPDIF, 0, sample_rate); return true; } /* if (subtype == MEDIASUBTYPE_Vorbis && formattype == FORMAT_Vorbis && mt.FormatLength() > sizeof(VORBISFORMAT)) { VORBISFORMAT *format = (VORBISFORMAT *)mt.Format(); spk = Speakers(FORMAT_VORBIS, 0, format->samplesPerSec); spk.set_format_data(mt.Format(), mt.FormatLength()); } */ if (subtype == MEDIASUBTYPE_Vorbis2 && formattype == FORMAT_Vorbis2 && mt.FormatLength() > sizeof(VORBISFORMAT2)) { VORBISFORMAT2 *format = (VORBISFORMAT2 *)mt.Format(); spk = Speakers(FORMAT_VORBIS, 0, format->samplesPerSec); spk.set_format_data(mt.Format(), mt.FormatLength()); return true; } ///////////////////////////////////////////////////////// // LPCM if (subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO) { PCMWAVEFORMAT *pcmwf = wf_cast<PCMWAVEFORMAT>(wf, wf_size); if (!pcmwf) return false; int format, mode; switch (pcmwf->wBitsPerSample) { case 16: format = FORMAT_PCM16_BE; break; case 20: format = FORMAT_LPCM20; break; case 24: format = FORMAT_LPCM24; break; default: return false; } switch (pcmwf->wf.nChannels) { case 1: mode = MODE_MONO; break; case 2: mode = MODE_STEREO; break; default: return false; } spk = Speakers(format, mode, sample_rate); return true; } ///////////////////////////////////////////////////////// // General WAVEFORMAT conversion spk = Speakers(); if (wf) spk = wf2spk(wf, wf_size); return !spk.is_unknown(); }
bool wfx2spk(WAVEFORMATEX *wfx, Speakers &spk) { int format; int mask; WAVEFORMATEXTENSIBLE *wfex = 0; if ( ! wfx ) return false; if ( wfx->wFormatTag == WAVE_FORMAT_DOLBY_AC3_SPDIF ) { spk = Speakers(FORMAT_SPDIF, 0, wfx->nSamplesPerSec); return true; } if ( wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) { // extensible if ( wfx->cbSize < 22 ) return false; wfex = (WAVEFORMATEXTENSIBLE *)wfx; // determine sample format if ( wfex->SubFormat == GUID_SUBTYPE_IEEE_FLOAT ) { switch (wfx->wBitsPerSample) { case 32: format = FORMAT_PCMFLOAT; break; case 64: format = FORMAT_PCMDOUBLE; break; default: return false; } } else if ( wfex->SubFormat == GUID_SUBTYPE_PCM ) { switch ( wfx->wBitsPerSample ) { case 16: format = FORMAT_PCM16; break; case 24: format = FORMAT_PCM24; break; case 32: format = FORMAT_PCM32; break; default: return false; } } else if ( wfex->SubFormat == GUID_DOLBY_AC3_SPDIF ) format = FORMAT_SPDIF; else return false; // determine audio mode for ( mask = 0; mask < ((int)(sizeof(ds_channels_tbl) / sizeof(ds_channels_tbl[0]))); ++mask ) { if ( ds_channels_tbl[mask] == wfex->dwChannelMask ) break; } if ( mask == sizeof(ds_channels_tbl) / sizeof(ds_channels_tbl[0]) ) return false; } else { // determine sample format switch ( wfx->wFormatTag ) { case WAVE_FORMAT_IEEE_FLOAT: switch ( wfx->wBitsPerSample ) { case 32: format = FORMAT_PCMFLOAT; break; case 64: format = FORMAT_PCMDOUBLE; break; default: return false; } break; case WAVE_FORMAT_PCM: switch ( wfx->wBitsPerSample ) { case 16: format = FORMAT_PCM16; break; case 24: format = FORMAT_PCM24; break; case 32: format = FORMAT_PCM32; break; default: return false; } break; case WAVE_FORMAT_AVI_AC3: format = FORMAT_AC3; break; case WAVE_FORMAT_AVI_DTS: format = FORMAT_DTS; break; case WAVE_FORMAT_MPEG: format = FORMAT_MPA; break; default: return false; } // determine audio mode mask = 0; if ( FORMAT_MASK(format) & FORMAT_CLASS_PCM ) switch ( wfx->nChannels ) { case 1: mask = MODE_MONO; break; case 2: mask = MODE_STEREO; break; case 3: mask = MODE_3_0; break; case 4: mask = MODE_QUADRO; break; case 5: mask = MODE_3_2; break; case 6: mask = MODE_5_1; break; default: return false; } } spk = Speakers(format, mask, wfx->nSamplesPerSec); return true; }
bool DtsHeaderParser::parseHeader(const uint8_t *hdr, HeaderInfo *hinfo) { DtsFrameInfo dtsFi; int bsType; bool isBigEndian(true); if ( dtsFi.init(BitReader(hdr, 16, true)) ) bsType = dtsFi.getIs14Bit() ? BITSTREAM_14BE : BITSTREAM_16BE; else if ( dtsFi.init(BitReader(hdr, 16, false)) ) { bsType = dtsFi.getIs14Bit() ? BITSTREAM_14LE : BITSTREAM_16LE; isBigEndian = false; } else return false; ///////////////////////////////////////////////////////// // Constraints if ( dtsFi.getSampleBlocks() < 6 ) // constraint return false; else if ( dtsFi.getChannelLayout() > 0xc ) // we don't work with more than 6 channels return false; else if ( dtsFi.getSampleRate() == 0 ) // constraint return false; else if ( dtsFi.getLfe() == 3 ) // constraint return false; DtsHdFrameInfo dtsHdFrameInfo(BitReader(hdr+dtsFi.getFrameSize(), 16, isBigEndian)); if ( hinfo ) { const int layout2MaskTable[] = { MODE_MONO, MODE_STEREO, MODE_STEREO, MODE_STEREO, MODE_STEREO, MODE_3_0, MODE_2_1, MODE_3_1, MODE_2_2, MODE_3_2 }; const int layout2RelationTable[] = { NO_RELATION, NO_RELATION, NO_RELATION, RELATION_SUMDIFF, RELATION_DOLBY, NO_RELATION, NO_RELATION, NO_RELATION, NO_RELATION, NO_RELATION, }; int mask(layout2MaskTable[dtsFi.getChannelLayout()]); const int relation(layout2RelationTable[dtsFi.getChannelLayout()]); if ( dtsFi.getLfe() ) { mask |= CH_MASK_LFE; } hinfo->setSpeakers(Speakers(FORMAT_DTS, mask, dtsFi.getSampleRate(), 1.0, relation)); hinfo->setFrameSize(dtsFi.getFrameSize() + dtsHdFrameInfo.getHdSize()); hinfo->setDtsHdSize(dtsHdFrameInfo.getHdSize()); hinfo->setScanSize(16384); // always scan up to maximum DTS frame size hinfo->setSampleCount(dtsFi.getSampleCount()); hinfo->setBsType(bsType); switch ( hinfo->getSampleCount() ) { case 512: hinfo->setSpdifType(11); break; case 1024: hinfo->setSpdifType(12); break; case 2048: hinfo->setSpdifType(13); break; default: hinfo->setSpdifType(0); // cannot do SPDIF passthrough break; } } return true; }
bool WAVSource::open_riff() { ///////////////////////////////////////////////////////// // Initializes spk, data_start and data_size const size_t buf_size = 256; uint8_t buf[buf_size]; size_t buf_data; ChunkHeader *header = (ChunkHeader *)buf; RIFFChunk *riff = (RIFFChunk *)buf; DS64Chunk *ds64 = (DS64Chunk *)buf; ///////////////////////////////////////////////////////// // Check RIFF header f.seek(0); buf_data = f.read(buf, sizeof(RIFFChunk)); if (buf_data < sizeof(RIFFChunk) || (riff->fcc != fcc_riff && riff->fcc != fcc_rf64) || riff->type != fcc_wave) return false; ///////////////////////////////////////////////////////// // Chunk walk bool have_fmt = false; bool have_ds64 = false; uint64_t data_size64 = 0; AutoFile::fsize_t next = f.pos(); while (1) { f.seek(next); buf_data = f.read(buf, sizeof(ChunkHeader)); if (buf_data < sizeof(ChunkHeader)) return false; /////////////////////////////////////////////////////// // Format chunk if (header->fcc == fcc_fmt) { if (!format.allocate(header->size)) return false; format.zero(); size_t data_read = f.read(format, header->size); if (data_read < header->size) return false; // Determine output format spk = wf2spk((WAVEFORMAT *)format.begin(), format.size()); if (spk.is_unknown()) spk = Speakers(FORMAT_RAWDATA, 0, 0); have_fmt = true; } /////////////////////////////////////////////////////// // ds64 chunk if (header->fcc == fcc_ds64) { buf_data += f.read(buf + buf_data, sizeof(DS64Chunk) - buf_data); if (buf_data < sizeof(DS64Chunk)) return false; data_size64 = ds64->data_size; have_ds64 = true; } /////////////////////////////////////////////////////// // Data chunk if (header->fcc == fcc_data) { if (!have_fmt) return false; data_start = next + sizeof(ChunkHeader); data_size = header->size; if (have_ds64 && header->size >= 0xffffff00) data_size = data_size64; f.seek(data_start); data_remains = data_size; return true; } next += header->size + sizeof(ChunkHeader); } // never be here return false; }
#include "../../suite.h" #include "rng.h" #include "filters/cache.h" #include "source/generator.h" static const Speakers spk = Speakers(FORMAT_LINEAR, MODE_STEREO, 48000); const size_t data_size = 65536; const size_t block_size = 4096; const int seed = 349087593; TEST(cache, "Cache filter") RNG rng(seed); Chunk in, out; LineGen gen; CacheFilter f; Samples buf; double block_multipliers[] = { 0.3, 0.5, 1, 2, 3 }; int nmultipliers = array_size(block_multipliers); for (int i = 0; i < nmultipliers; i++) for (int j = 0; j < nmultipliers; j++) { size_t cache_samples = size_t(block_size * block_multipliers[j]); vtime_t cache_time = vtime_t(cache_samples) / spk.sample_rate; size_t chunk_size = size_t(block_size * block_multipliers[i]); gen.init(spk, 0, 1, data_size, chunk_size); buf.allocate(cache_samples); f.set_size(cache_time); while (gen.get_chunk(in))
/* PESFrameParser test */ #include <boost/test/unit_test.hpp> #include "parsers/pes/pes_frame_parser.h" static const uint8_t good[][6] = { { 0x00, 0x00, 0x01, 0xbd, 0x01, 0x00 }, // Private stream 1 { 0x00, 0x00, 0x01, 0xc0, 0x01, 0x00 }, // MPEG audio }; static const Speakers good_spk[] = { Speakers(FORMAT_PES, 0, 0), Speakers(FORMAT_PES, 0, 0), }; static const uint8_t bad[][6] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // null header { 0x00, 0x00, 0x01, 0x80, 0x01, 0x00 }, // Bad stream }; BOOST_AUTO_TEST_SUITE(pes_frame_parser) BOOST_AUTO_TEST_CASE(can_parse) { PESFrameParser parser; BOOST_CHECK(parser.can_parse(FORMAT_PES));