void AudioResamplerTest :: testDifferentResampleRates() { int retval = -1; RefPointer<IAudioResampler> sampler; RefPointer<IAudioSamples> inSamples = IAudioSamples::make(4096, 1); RefPointer<IAudioSamples> outSamples = IAudioSamples::make(4096*4, 1); // initialize our starting samples RefPointer<IBuffer> inBuffer = inSamples->getData(); int16_t * inputBuf = (int16_t*)inBuffer->getBytes(0, inSamples->getNumSamples()); VS_TUT_ENSURE("!samples", inputBuf); unsigned int tests[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 32, 64, 128, 256, 512, 1024, 2048, 3072, 4096 }; unsigned int j = 0; // New sample every time sampler = IAudioResampler::make(2, 1, 44100, 22050); VS_TUT_ENSURE("! sampler", sampler); unsigned int totalInput = 0; unsigned int totalOutput = 0; for (j = 0; j < sizeof(tests)/sizeof(unsigned int); j++) { unsigned int i=0; for (i = 0; i < tests[j]; i++) { // This is a hack and doesn't need real randomness; just tesing. bool negative= rand() % 2; inputBuf[i] = (int16_t)(32767.0*((double)rand()/(double)(RAND_MAX))) * (negative ? -1 : 1); } totalInput += tests[j]; inSamples->setComplete(true, i, 22050, 1, IAudioSamples::FMT_S16, 0); retval = sampler->resample(outSamples.value(), inSamples.value(), inSamples->getNumSamples()); VS_TUT_ENSURE("should succeed", retval >= 0); totalOutput += retval; VS_LOG_TRACE("i: %d; o: %d; ti: %d; to: %d", inSamples->getNumSamples(), outSamples->getNumSamples(), totalInput, totalOutput); } // That was all so we could test this. audio_resample hard codes the filter // coefficient in the resample to 16 samples, so we should always hold back // at least 16. VS_TUT_ENSURE_EQUALS("more than I thought", totalOutput, (totalInput)*2-16); }
void MediaAudioTest::testCreationFromBufferPlanar() { const int32_t numSamples = 155; // I choose an odd number because HV will align up to 32 const int32_t sampleRate = 22050; const int32_t channels = 15; // choose a large # of channels to make sure we expand the Frame const AudioChannel::Layout layout = AudioChannel::CH_LAYOUT_UNKNOWN; const AudioFormat::Type format = AudioFormat::SAMPLE_FMT_DBLP; int32_t bufSize = AudioFormat::getBufferSizeNeeded(numSamples, channels, format); // test that there is rounding up int32_t minSize = AudioFormat::getBytesPerSample(format) * numSamples * channels; TS_ASSERT_LESS_THAN(minSize, bufSize); RefPointer<Buffer> src = Buffer::make(0, bufSize); double* srcData = (double*) src->getBytes(0, bufSize); // now, let's go nuts! for (size_t i = 0; i < bufSize / sizeof(double); i++) { srcData[i] = i; } RefPointer<MediaAudio> audio; { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaAudio::make(0, numSamples, sampleRate, channels, layout, format), HumbleInvalidArgument); } audio = MediaAudio::make(src.value(), numSamples, sampleRate, channels, layout, format); TS_ASSERT(audio); TS_ASSERT_EQUALS(channels, audio->getNumDataPlanes()); // sigh; time to test each plane. for (int i = 0; i < channels; i++) { RefPointer<Buffer> dst = audio->getData(i); TS_ASSERT(dst); double* dstData = (double*) dst->getBytes(0, dst->getBufferSize()); // the values should be monotonically increasing given how we set them. double last = dstData[0]; for (size_t j = 1; j < dst->getBufferSize() / sizeof(double); j++) { TS_ASSERT_DELTA(last + 1, dstData[j], 0.001); last = dstData[j]; } } }
void MediaAudioTest::testCreationFromBufferPacked() { const int32_t numSamples = 155; // I choose an odd number because HV will align up to 32 const int32_t sampleRate = 22050; const int32_t channels = 8; const AudioChannel::Layout layout = AudioChannel::CH_LAYOUT_7POINT1; const AudioFormat::Type format = AudioFormat::SAMPLE_FMT_DBL; int32_t bufSize = AudioFormat::getBufferSizeNeeded(numSamples, channels, format); RefPointer<Buffer> src = Buffer::make(0, bufSize); double* srcData = (double*) src->getBytes(0, bufSize); // now, let's go nuts! for (size_t i = 0; i < bufSize / sizeof(double); i++) { srcData[i] = i; } RefPointer<MediaAudio> audio; { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaAudio::make(0, numSamples, sampleRate, channels, layout, format), HumbleInvalidArgument); } audio = MediaAudio::make(src.value(), numSamples, sampleRate, channels, layout, format); TS_ASSERT(audio); TS_ASSERT_EQUALS(1, audio->getNumDataPlanes()); RefPointer<Buffer> dst = audio->getData(0); TS_ASSERT(dst); double* dstData = (double*) dst->getBytes(0, dst->getBufferSize()); // the test in packed data is simple -- the buffers should be equal! TS_ASSERT_EQUALS(src->getBufferSize(), dst->getBufferSize()); TS_ASSERT_EQUALS(srcData, dstData); }
void StreamCoderFaacTest :: testDecodingAndEncodingFaacAudio() { RefPointer<IAudioSamples> samples = 0; RefPointer<IVideoPicture> frame = 0; RefPointer<IRational> num(0); RefPointer<IStreamCoder> ic(0); RefPointer<IStreamCoder> oc(0); RefPointer<ICodec> newcodec; newcodec = ICodec::findEncodingCodecByName("libfaac"); if (!newcodec) { VS_LOG_ERROR("libfaac not supported by this build; ignoring test"); return; } int numSamples = 0; int numPackets = 0; int numFrames = 0; int numKeyFrames = 0; int retval = -1; LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_WARN, false); // use the 20 second file to make memcheck faster h->setupReading("testfile_videoonly_20sec.flv"); RefPointer<IPacket> packet = IPacket::make(); hw->setupWriting("StreamCoderFaacTest_testDecodingAndEncodingFaacAudio.mov", "mpeg4", "libfaac", "mov"); RefPointer<IPacket> opacket = IPacket::make(); VS_TUT_ENSURE("! opacket", opacket); { // Let's set up audio first. ic = h->coders[h->first_input_audio_stream]; oc = hw->coders[hw->first_output_audio_stream]; // Set the output coder correctly. oc->setSampleRate(ic->getSampleRate()); oc->setChannels(ic->getChannels()); oc->setBitRate(ic->getBitRate()); samples = IAudioSamples::make(1024, ic->getChannels()); VS_TUT_ENSURE("got no samples", samples); retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); VS_TUT_ENSURE("Could not open output coder", retval >= 0); } { // now, let's set up video. ic = h->coders[h->first_input_video_stream]; oc = hw->coders[hw->first_output_video_stream]; // We're going to set up high quality video oc->setBitRate(720000); oc->setGlobalQuality(0); oc->setFlags(oc->getFlags() | IStreamCoder::FLAG_QSCALE); oc->setPixelType(ic->getPixelType()); oc->setHeight(ic->getHeight()); oc->setWidth(ic->getWidth()); num = IRational::make(1,15); oc->setFrameRate(num.value()); num = ic->getTimeBase(); oc->setTimeBase(num.value()); oc->setNumPicturesInGroupOfPictures( ic->getNumPicturesInGroupOfPictures() ); // Ask the StreamCoder to guess width and height for us frame = IVideoPicture::make( ic->getPixelType(), -1, -1); VS_TUT_ENSURE("got no frame", frame); VS_TUT_ENSURE("should not have width", frame->getWidth() <= 0); VS_TUT_ENSURE("should not have height", frame->getHeight() <= 0); retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); VS_TUT_ENSURE("Could not open output coder", retval >= 0); } // write header retval = hw->container->writeHeader(); VS_TUT_ENSURE("could not write header", retval >= 0); while (h->container->readNextPacket(packet.value()) == 0) { ic = h->coders[packet->getStreamIndex()]; oc = hw->coders[packet->getStreamIndex()]; if (packet->getStreamIndex() == h->first_input_audio_stream) { int offset = 0; numPackets++; while (offset < packet->getSize()) { retval = ic->decodeAudio( samples.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any audio", retval > 0); offset += retval; VS_TUT_ENSURE("could not write any samples", samples->getNumSamples() > 0); numSamples += samples->getNumSamples(); // now, write out the packets. unsigned int numSamplesConsumed = 0; do { retval = oc->encodeAudio(opacket.value(), samples.value(), numSamplesConsumed); VS_TUT_ENSURE("Could not encode any audio", retval > 0); numSamplesConsumed += retval; if (opacket->isComplete()) { VS_TUT_ENSURE("could not encode audio", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } while (numSamplesConsumed < samples->getNumSamples()); } } else if (packet->getStreamIndex() == h->first_input_video_stream) { int offset = 0; numPackets++; VS_LOG_TRACE("packet: pts: %ld; dts: %ld", packet->getPts(), packet->getDts()); while (offset < packet->getSize()) { retval = ic->decodeVideo( frame.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any video", retval>0); num = ic->getTimeBase(); VS_TUT_ENSURE_DISTANCE("time base changed", num->getDouble(), h->expected_time_base, 0.00001); offset += retval; if (frame->isComplete()) { VS_TUT_ENSURE("should now have a frame width", frame->getWidth() > 0); VS_TUT_ENSURE("should now have a frame height", frame->getHeight() > 0); numFrames++; if (frame->isKeyFrame()) numKeyFrames++; frame->setQuality(0); retval = oc->encodeVideo( opacket.value(), frame.value(), -1); VS_TUT_ENSURE("could not encode video", retval >= 0); VS_TUT_ENSURE("could not encode video", opacket->isComplete()); VS_TUT_ENSURE("could not encode video", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); // now, write the packet to disk. retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } } } // sigh; it turns out that to flush the encoding buffers you need to // ask the encoder to encode a NULL set of samples. So, let's do that. retval = hw->coders[hw->first_output_audio_stream]->encodeAudio(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any audio", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->coders[hw->first_output_video_stream]->encodeVideo(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any video", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->container->writeTrailer(); VS_TUT_ENSURE("! writeTrailer", retval >= 0); retval = h->coders[h->first_input_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = h->coders[h->first_input_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); VS_TUT_ENSURE("could not get any audio packets", numPackets > 0); VS_TUT_ENSURE("could not decode any audio", numSamples > 0); VS_TUT_ENSURE("could not decode any video", numFrames >0); VS_TUT_ENSURE("could not find any key frames", numKeyFrames >0); if (h->expected_packets) VS_TUT_ENSURE_EQUALS("unexpected number of packets", numPackets, 1062); if (h->expected_audio_samples) VS_TUT_ENSURE_EQUALS("unexpected number of audio samples", numSamples, 438912); if (h->expected_video_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video frames", numFrames, 300); if (h->expected_video_key_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video key frames", numKeyFrames, 25); }
void StreamCoderX264Test :: testDecodingAndEncodingH264Video() { // This test doesn't pass memcheck but we're disabling for now const char *memcheck = getenv("VS_TEST_MEMCHECK"); if (memcheck) return; return; RefPointer<IAudioSamples> samples = 0; RefPointer<IVideoPicture> frame = 0; RefPointer<IRational> num(0); RefPointer<IStreamCoder> ic(0); RefPointer<IStreamCoder> oc(0); RefPointer<ICodec> newcodec; newcodec = ICodec::findEncodingCodecByName("libx264"); if (!newcodec) // we're probably in a LGPL build, and so we shouldn't run this test return; int numSamples = 0; int numPackets = 0; int numFrames = 0; int numKeyFrames = 0; int retval = -1; LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_WARN, false); // use the 20 second file to make memcheck faster h->setupReading("testfile_videoonly_20sec.flv"); RefPointer<IPacket> packet = IPacket::make(); hw->setupWriting("StreamCoderX264Test_testDecodingAndEncodingH264Video.mp4", "libx264", "libmp3lame", "mp4"); RefPointer<IPacket> opacket = IPacket::make(); VS_TUT_ENSURE("! opacket", opacket); { // Let's set up audio first. ic = h->coders[h->first_input_audio_stream]; oc = hw->coders[hw->first_output_audio_stream]; // Set the output coder correctly. oc->setSampleRate(ic->getSampleRate()); oc->setChannels(ic->getChannels()); oc->setBitRate(ic->getBitRate()); samples = IAudioSamples::make(1024, ic->getChannels()); VS_TUT_ENSURE("got no samples", samples); retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); VS_TUT_ENSURE("Could not open output coder", retval >= 0); } { // now, let's set up video. ic = h->coders[h->first_input_video_stream]; oc = hw->coders[hw->first_output_video_stream]; // We're going to set up high quality video oc->setBitRate(720000); oc->setGlobalQuality(0); oc->setFlags(oc->getFlags() | IStreamCoder::FLAG_QSCALE); oc->setPixelType(ic->getPixelType()); oc->setHeight(ic->getHeight()); oc->setWidth(ic->getWidth()); num = IRational::make(1,15); oc->setFrameRate(num.value()); num = ic->getTimeBase(); oc->setTimeBase(num.value()); oc->setNumPicturesInGroupOfPictures( ic->getNumPicturesInGroupOfPictures() ); // Ask the StreamCoder to guess width and height for us frame = IVideoPicture::make( ic->getPixelType(), -1, -1); VS_TUT_ENSURE("got no frame", frame); VS_TUT_ENSURE("should not have width", frame->getWidth() <= 0); VS_TUT_ENSURE("should not have height", frame->getHeight() <= 0); oc->setProperty("coder", "0"); oc->setProperty("flags", "+loop"); oc->setProperty("cmp", "+chroma"); oc->setProperty("partitions", "-parti8x8+parti4x4+partp8x8-partp4x4-partb8x8"); oc->setProperty("me_method", "hex"); oc->setProperty("subq", "3"); oc->setProperty("me_range", "16"); oc->setProperty("g", "250"); oc->setProperty("keyint_min", "25"); oc->setProperty("sc_threshold", "40"); oc->setProperty("i_qfactor", "0.71"); oc->setProperty("b_strategy", "1"); oc->setProperty("qcomp", "0.6"); oc->setProperty("qmin", "10"); oc->setProperty("qmax", "51"); oc->setProperty("qdiff", "4"); oc->setProperty("directpred", "1"); oc->setProperty("flags2", "+fastpskip"); oc->setProperty("cqp", "0"); retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); if (retval < 0) // this fails on Mac builds return; VS_TUT_ENSURE("Could not open output coder", retval >= 0); } // write header retval = hw->container->writeHeader(); VS_TUT_ENSURE("could not write header", retval >= 0); while (h->container->readNextPacket(packet.value()) == 0) { ic = h->coders[packet->getStreamIndex()]; oc = hw->coders[packet->getStreamIndex()]; if (packet->getStreamIndex() == h->first_input_audio_stream) { int offset = 0; numPackets++; while (offset < packet->getSize()) { retval = ic->decodeAudio( samples.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any audio", retval > 0); offset += retval; VS_TUT_ENSURE("could not write any samples", samples->getNumSamples() > 0); numSamples += samples->getNumSamples(); // now, write out the packets. unsigned int numSamplesConsumed = 0; do { retval = oc->encodeAudio(opacket.value(), samples.value(), numSamplesConsumed); VS_TUT_ENSURE("Could not encode any audio", retval > 0); numSamplesConsumed += retval; if (opacket->isComplete()) { VS_TUT_ENSURE("could not encode audio", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } while (numSamplesConsumed < samples->getNumSamples()); } } else if (packet->getStreamIndex() == h->first_input_video_stream) { int offset = 0; numPackets++; VS_LOG_TRACE("packet: pts: %ld; dts: %ld", packet->getPts(), packet->getDts()); while (offset < packet->getSize()) { retval = ic->decodeVideo( frame.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any video", retval>0); num = ic->getTimeBase(); VS_TUT_ENSURE_DISTANCE("time base changed", num->getDouble(), h->expected_time_base, 0.00001); offset += retval; if (frame->isComplete()) { VS_TUT_ENSURE("should now have a frame width", frame->getWidth() > 0); VS_TUT_ENSURE("should now have a frame height", frame->getHeight() > 0); numFrames++; if (frame->isKeyFrame()) numKeyFrames++; frame->setQuality(0); retval = oc->encodeVideo( opacket.value(), frame.value(), -1); VS_TUT_ENSURE("could not encode video", retval >= 0); if (opacket->isComplete()) { VS_TUT_ENSURE("could not encode video", opacket->isComplete()); VS_TUT_ENSURE("could not encode video", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); // now, write the packet to disk. retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } } } } // sigh; it turns out that to flush the encoding buffers you need to // ask the encoder to encode a NULL set of samples. So, let's do that. retval = hw->coders[hw->first_output_audio_stream]->encodeAudio(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any audio", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->coders[hw->first_output_video_stream]->encodeVideo(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any video", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->container->writeTrailer(); VS_TUT_ENSURE("! writeTrailer", retval >= 0); retval = h->coders[h->first_input_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = h->coders[h->first_input_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); VS_TUT_ENSURE("could not get any audio packets", numPackets > 0); VS_TUT_ENSURE("could not decode any audio", numSamples > 0); VS_TUT_ENSURE("could not decode any video", numFrames >0); VS_TUT_ENSURE("could not find any key frames", numKeyFrames >0); if (h->expected_packets) VS_TUT_ENSURE_EQUALS("unexpected number of packets", numPackets, 1062); if (h->expected_audio_samples) VS_TUT_ENSURE_EQUALS("unexpected number of audio samples", numSamples, 438912); if (h->expected_video_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video frames", numFrames, 300); if (h->expected_video_key_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video key frames", numKeyFrames, 25); }
void MediaPacketTest::testCopyPacket() { const int32_t size = 512; packet = MediaPacket::make(size); TSM_ASSERT("was able to allocate packet", packet); // everything else should be garbage. int64_t position = packet->getPosition(); TSM_ASSERT("position was not set to -1", position == -1); position = 4; packet->setPosition(position); int64_t dts = 28349762; packet->setDts(dts); int64_t pts = 82729373; packet->setPts(pts); RefPointer<Rational> timeBase = Rational::make(3, 28972); packet->setTimeBase(timeBase.value()); int32_t streamIndex = 8; packet->setStreamIndex(streamIndex); int64_t duration = 28387728; packet->setDuration(duration); int64_t convergenceDuration = 283; packet->setConvergenceDuration(convergenceDuration); // let's get access to the data RefPointer<Buffer> data = packet->getData(); TS_ASSERT_EQUALS(size+16, data->getBufferSize()); TS_ASSERT_EQUALS(size, packet->getSize()); uint8_t* raw = (uint8_t*) data->getBytes(0, size); for (int i = 0; i < size; i++) raw[i] = i % 16; // Now, make a copy bool tests[] = { true, false }; for (size_t i = 0; i < (sizeof(tests) / sizeof(tests[0])); i++) { RefPointer<MediaPacket> newPacket = MediaPacket::make(packet.value(), tests[i]); TSM_ASSERT("should not be empty", newPacket); // let's make sure that when not copying, the data is the same. TSM_ASSERT_EQUALS("should equal", position, newPacket->getPosition()); TSM_ASSERT_EQUALS("should equal", pts, newPacket->getPts()); TSM_ASSERT_EQUALS("should equal", dts, newPacket->getDts()); TSM_ASSERT_EQUALS("should equal", streamIndex, newPacket->getStreamIndex()); TSM_ASSERT_EQUALS("should equal", duration, newPacket->getDuration()); TSM_ASSERT_EQUALS("should equal", convergenceDuration, newPacket->getConvergenceDuration()); RefPointer<Rational> newBase = newPacket->getTimeBase(); TSM_ASSERT("should be equal", newBase->compareTo(timeBase.value()) == 0); RefPointer<Buffer> buf = newPacket->getData(); TS_ASSERT_EQUALS(size, newPacket->getSize()); TS_ASSERT_EQUALS(size+16, buf->getBufferSize()); uint8_t* d = (uint8_t*) buf->getBytes(0, size); if (!tests[i]) { TS_ASSERT_EQUALS(d, raw); } else { TS_ASSERT_DIFFERS(d, raw); } TS_ASSERT(d); for (int j = 0; j < size; j++) { TS_ASSERT_EQUALS(d[j], j % 16); } } }
void MediaAudioTest::testCreation() { const int32_t numSamples = 1024; const int32_t sampleRate = 22050; const int32_t channels = 8; const AudioChannel::Layout layout = AudioChannel::CH_LAYOUT_7POINT1; const AudioFormat::Type format = AudioFormat::SAMPLE_FMT_S16P; // now let's test invalid methods. RefPointer<MediaAudio> audio; { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaAudio::make(-1, sampleRate, channels, layout, format), HumbleInvalidArgument); } { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaAudio::make(numSamples, -1, channels, layout, format), HumbleInvalidArgument); } { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaAudio::make(numSamples, sampleRate, -1, layout, format), HumbleInvalidArgument); } { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaAudio::make(numSamples, sampleRate, channels + 1, layout, format), HumbleInvalidArgument); } { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaAudio::make(numSamples, sampleRate, channels, layout, AudioFormat::SAMPLE_FMT_NONE), HumbleInvalidArgument); } // And this should be valid audio = MediaAudio::make(numSamples, sampleRate, channels + 1, AudioChannel::CH_LAYOUT_UNKNOWN, format); TS_ASSERT(audio); audio = MediaAudio::make(numSamples, sampleRate, channels, layout, format); TS_ASSERT(audio); // now let's try getting the data RefPointer<Buffer> buf; TS_ASSERT_EQUALS(numSamples, audio->getMaxNumSamples()); TS_ASSERT_EQUALS(numSamples, audio->getNumSamples()); TS_ASSERT(!audio->isComplete()); TS_ASSERT_EQUALS(channels, audio->getChannels()); TS_ASSERT_EQUALS(channels, audio->getNumDataPlanes()); TS_ASSERT_EQUALS(layout, audio->getChannelLayout()); TS_ASSERT_EQUALS(sampleRate, audio->getSampleRate()); TS_ASSERT_EQUALS(format, audio->getFormat()); { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS( audio->setNumSamples(audio->getMaxNumSamples()+1), HumbleInvalidArgument); TS_ASSERT_THROWS(audio->setNumSamples(-1), HumbleInvalidArgument); TS_ASSERT_THROWS(audio->setNumSamples(0), HumbleInvalidArgument); } audio->setNumSamples(1); TS_ASSERT_EQUALS(1, audio->getNumSamples()); audio->setComplete(true); TS_ASSERT(audio->isComplete()); for (int i = 0; i < channels; i++) { buf = audio->getData(i); TS_ASSERT(buf); TS_ASSERT_EQUALS(audio->getDataPlaneSize(i), audio->getNumSamples()*AudioFormat::getBytesPerSample(audio->getFormat())*(audio->isPlanar()?1:audio->getChannels())); } // now let's try packed audio audio = MediaAudio::make(numSamples, sampleRate, channels, layout, AudioFormat::getPackedSampleFormat(format)); TS_ASSERT(audio); TS_ASSERT_EQUALS(AudioFormat::getPackedSampleFormat(format), audio->getFormat()); TS_ASSERT_EQUALS(channels, audio->getChannels()); TS_ASSERT_EQUALS(1, audio->getNumDataPlanes()); buf = audio->getData(0); TS_ASSERT(buf); for (int i = 1; i < channels; i++) { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(audio->getData(i), HumbleInvalidArgument); } }
void MediaAudioTest::testCopy() { const int32_t numSamples = 155; // I choose an odd number because HV will align up to 32 const int32_t sampleRate = 22050; const int32_t channels = 15; // choose a large # of channels to make sure we expand the Frame const AudioChannel::Layout layout = AudioChannel::CH_LAYOUT_UNKNOWN; const AudioFormat::Type format = AudioFormat::SAMPLE_FMT_DBLP; int32_t bufSize = AudioFormat::getBufferSizeNeeded(numSamples, channels, format); // test that there is rounding up int32_t minSize = AudioFormat::getBytesPerSample(format) * numSamples * channels; TS_ASSERT_LESS_THAN(minSize, bufSize); RefPointer<Buffer> src = Buffer::make(0, bufSize); double* srcData = (double*) src->getBytes(0, bufSize); // now, let's go nuts! for (size_t i = 0; i < bufSize / sizeof(double); i++) { srcData[i] = i; } RefPointer<MediaAudio> audio; audio = MediaAudio::make(src.value(), numSamples, sampleRate, channels, layout, format); TS_ASSERT(audio); TS_ASSERT_EQUALS(channels, audio->getNumDataPlanes()); bool tests[] = { true, false }; for (size_t i = 0; i < sizeof(tests) / sizeof(*tests); i++) { // now let's make a copy RefPointer<MediaAudio> copy = MediaAudio::make(audio.value(), tests[i]); TS_ASSERT_EQUALS(copy->getMaxNumSamples(), audio->getMaxNumSamples()); TS_ASSERT_EQUALS(copy->getNumSamples(), audio->getNumSamples()); TS_ASSERT_EQUALS(copy->getChannels(), audio->getChannels()); TS_ASSERT_EQUALS(copy->getNumDataPlanes(), audio->getNumDataPlanes()); TS_ASSERT_EQUALS(copy->getChannelLayout(), audio->getChannelLayout()); TS_ASSERT_EQUALS(copy->getSampleRate(), audio->getSampleRate()); TS_ASSERT_EQUALS(copy->getFormat(), audio->getFormat()); for (int32_t j = 0; j < audio->getNumDataPlanes(); j++) { RefPointer<Buffer> srcBuf = audio->getData(j); RefPointer<Buffer> dstBuf = copy->getData(j); int32_t planeSize = srcBuf->getBufferSize(); TS_ASSERT_EQUALS(planeSize, dstBuf->getBufferSize()); uint8_t* srcBytes = (uint8_t*) srcBuf->getBytes(0, planeSize); uint8_t* dstBytes = (uint8_t*) dstBuf->getBytes(0, planeSize); if (tests[i]) { for (int32_t k = 0; k < planeSize; k++) { // should be byte-by-byte the same TS_ASSERT_EQUALS(srcBytes[k], dstBytes[k]); } } else { TS_ASSERT_EQUALS(srcBytes, dstBytes); } } } }
void StreamCoderTest :: testDecodingAndEncodingFullyInterleavedFile() { RefPointer<IAudioSamples> samples = 0; RefPointer<IVideoPicture> frame = 0; RefPointer<IRational> num(0); RefPointer<IStreamCoder> ic(0); RefPointer<IStreamCoder> oc(0); int numSamples = 0; int numPackets = 0; int numFrames = 0; int numKeyFrames = 0; int retval = -1; h->setupReading(h->SAMPLE_FILE); RefPointer<IPacket> packet = IPacket::make(); hw->setupWriting("StreamCoderTest_6_output.mov", "mpeg4", "libmp3lame", "mov"); RefPointer<IPacket> opacket = IPacket::make(); VS_TUT_ENSURE("! opacket", opacket); RefPointer<IMetaData> inputProps = IMetaData::make(); RefPointer<IMetaData> outputProps = IMetaData::make(); { // Let's set up audio first. ic = h->coders[h->first_input_audio_stream]; oc = hw->coders[hw->first_output_audio_stream]; // Set the output coder correctly. oc->setSampleRate(ic->getSampleRate()); oc->setChannels(ic->getChannels()); // Using the MetaData structure char tmpBuf[1024]; snprintf(tmpBuf, sizeof(tmpBuf), "%d", ic->getBitRate()); inputProps->setValue("b", tmpBuf); const char* invalidKey="kd82jclkjdi2oc001,ss2-948"; const char* invalidValue="c9xu1nxL28fJ9"; inputProps->setValue(invalidKey, invalidValue); samples = IAudioSamples::make(1024, ic->getChannels()); VS_TUT_ENSURE("got no samples", samples); retval = ic->open(0,0); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(inputProps.value(), outputProps.value()); VS_TUT_ENSURE("Could not open output coder", retval >= 0); // now let's ensure our fake property was not set. VS_TUT_ENSURE("Should only have one unset setting", outputProps->getNumKeys() == 1) VS_TUT_ENSURE("Should have expected value", strcmp(outputProps->getValue(invalidKey, IMetaData::METADATA_NONE), invalidValue)==0); } { // now, let's set up video. ic = h->coders[h->first_input_video_stream]; oc = hw->coders[hw->first_output_video_stream]; // We're going to set up high quality video oc->setBitRate(720000); oc->setGlobalQuality(0); oc->setFlags(oc->getFlags() | IStreamCoder::FLAG_QSCALE); oc->setPixelType(ic->getPixelType()); oc->setHeight(ic->getHeight()); oc->setWidth(ic->getWidth()); num = IRational::make(1,15); oc->setFrameRate(num.value()); num = ic->getTimeBase(); oc->setTimeBase(num.value()); oc->setNumPicturesInGroupOfPictures( ic->getNumPicturesInGroupOfPictures() ); // Ask the StreamCoder to guess width and height for us frame = IVideoPicture::make( ic->getPixelType(), -1, -1); VS_TUT_ENSURE("got no frame", frame); VS_TUT_ENSURE("should not have width", frame->getWidth() <= 0); VS_TUT_ENSURE("should not have height", frame->getHeight() <= 0); retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); VS_TUT_ENSURE("Could not open output coder", retval >= 0); } // write header retval = hw->container->writeHeader(); VS_TUT_ENSURE("could not write header", retval >= 0); while (h->container->readNextPacket(packet.value()) == 0) { ic = h->coders[packet->getStreamIndex()]; oc = hw->coders[packet->getStreamIndex()]; if (packet->getStreamIndex() == h->first_input_audio_stream) { int offset = 0; numPackets++; while (offset < packet->getSize()) { retval = ic->decodeAudio( samples.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any audio", retval > 0); offset += retval; VS_TUT_ENSURE("could not write any samples", samples->getNumSamples() > 0); numSamples += samples->getNumSamples(); // now, write out the packets. unsigned int numSamplesConsumed = 0; do { retval = oc->encodeAudio(opacket.value(), samples.value(), numSamplesConsumed); VS_TUT_ENSURE("Could not encode any audio", retval > 0); numSamplesConsumed += retval; if (opacket->isComplete()) { VS_TUT_ENSURE("audio duration not set", opacket->getDuration() > 0); VS_TUT_ENSURE("could not encode audio", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } while (numSamplesConsumed < samples->getNumSamples()); } } else if (packet->getStreamIndex() == h->first_input_video_stream) { int offset = 0; numPackets++; VS_LOG_TRACE("packet: pts: %ld; dts: %ld", packet->getPts(), packet->getDts()); while (offset < packet->getSize()) { retval = ic->decodeVideo( frame.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any video", retval>0); num = ic->getTimeBase(); VS_TUT_ENSURE_DISTANCE("time base changed", num->getDouble(), h->expected_time_base, 0.0001); offset += retval; if (frame->isComplete()) { VS_TUT_ENSURE("should now have a frame width", frame->getWidth() > 0); VS_TUT_ENSURE("should now have a frame height", frame->getHeight() > 0); numFrames++; if (frame->isKeyFrame()) numKeyFrames++; frame->setQuality(0); retval = oc->encodeVideo( opacket.value(), frame.value(), -1); VS_TUT_ENSURE("could not encode video", retval >= 0); VS_TUT_ENSURE("could not encode video", opacket->isComplete()); VS_TUT_ENSURE("could not encode video", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); // now, write the packet to disk. retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } } } // sigh; it turns out that to flush the encoding buffers you need to // ask the encoder to encode a NULL set of samples. So, let's do that. retval = hw->coders[hw->first_output_audio_stream]->encodeAudio(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any audio", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->coders[hw->first_output_video_stream]->encodeVideo(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any video", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->container->writeTrailer(); VS_TUT_ENSURE("! writeTrailer", retval >= 0); retval = h->coders[h->first_input_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = h->coders[h->first_input_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); VS_TUT_ENSURE("could not get any audio packets", numPackets > 0); VS_TUT_ENSURE("could not decode any audio", numSamples > 0); VS_TUT_ENSURE("could not decode any video", numFrames >0); VS_TUT_ENSURE("could not find any key frames", numKeyFrames >0); if (h->expected_packets) VS_TUT_ENSURE_EQUALS("unexpected number of packets", numPackets, h->expected_packets); if (h->expected_audio_samples) VS_TUT_ENSURE_EQUALS("unexpected number of audio samples", numSamples, h->expected_audio_samples); if (h->expected_video_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video frames", numFrames, h->expected_video_frames); if (h->expected_video_key_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video key frames", numKeyFrames, h->expected_video_key_frames); }
void AudioResamplerTest :: testTimeStampIsAdjustedWhenResamplerEatsBytesUpsampling() { int retval = -1; int numSamples = 10000; int iSampleRate = numSamples; int oSampleRate = iSampleRate*2; RefPointer<IAudioResampler> sampler; RefPointer<IAudioSamples> inSamples = IAudioSamples::make(numSamples, 1); RefPointer<IAudioSamples> outSamples = IAudioSamples::make(numSamples*oSampleRate/iSampleRate, 2); // initialize our starting samples RefPointer<IBuffer> inBuffer = inSamples->getData(); int16_t * inputBuf = (int16_t*)inBuffer->getBytes(0, inSamples->getNumSamples()); VS_TUT_ENSURE("!samples", inputBuf); sampler = IAudioResampler::make(2, 1, oSampleRate, iSampleRate); VS_TUT_ENSURE("! sampler", sampler); for (int i = 0; i < numSamples; i++) { // This is a hack and doesn't need real randomness; just testing. bool negative= rand() % 2; inputBuf[i] = (int16_t)(32767.0*((double)rand()/(double)(RAND_MAX))) * (negative ? -1 : 1); } // Do it once... inSamples->setComplete(true, numSamples, iSampleRate, 1, IAudioSamples::FMT_S16, 0); retval = sampler->resample(outSamples.value(), inSamples.value(), inSamples->getNumSamples()); VS_TUT_ENSURE("should succeed", retval >= 0); VS_LOG_TRACE("r: %d; i: %d; o: %d; ipts: %lld; opts: %lld", retval, inSamples->getNumSamples(), outSamples->getNumSamples(), inSamples->getPts(), outSamples->getPts()); VS_TUT_ENSURE_EQUALS("should eat exactly 16 samples", outSamples->getNumSamples(), inSamples->getNumSamples()*oSampleRate/iSampleRate - 16); // Do it twice inSamples->setComplete(true, numSamples, iSampleRate, 1, IAudioSamples::FMT_S16, 1*Global::DEFAULT_PTS_PER_SECOND); retval = sampler->resample(outSamples.value(), inSamples.value(), inSamples->getNumSamples()); VS_TUT_ENSURE("should succeed", retval >= 0); VS_LOG_TRACE("r: %d; i: %d; o: %d; ipts: %lld; opts: %lld", retval, inSamples->getNumSamples(), outSamples->getNumSamples(), inSamples->getPts(), outSamples->getPts()); VS_TUT_ENSURE_EQUALS("should eat no samples", outSamples->getNumSamples(), inSamples->getNumSamples()*oSampleRate/iSampleRate); VS_TUT_ENSURE_EQUALS("timestamp should be back 16 samples worth", outSamples->getPts(), inSamples->getPts() - IAudioSamples::samplesToDefaultPts(16, oSampleRate)); // Do it thrice inSamples->setComplete(true, numSamples, iSampleRate, 1, IAudioSamples::FMT_S16, 2*Global::DEFAULT_PTS_PER_SECOND); retval = sampler->resample(outSamples.value(), inSamples.value(), inSamples->getNumSamples()); VS_TUT_ENSURE("should succeed", retval >= 0); VS_LOG_TRACE("r: %d; i: %d; o: %d; ipts: %lld; opts: %lld", retval, inSamples->getNumSamples(), outSamples->getNumSamples(), inSamples->getPts(), outSamples->getPts()); VS_TUT_ENSURE_EQUALS("should eat no samples", outSamples->getNumSamples(), inSamples->getNumSamples()*oSampleRate/iSampleRate); VS_TUT_ENSURE_EQUALS("timestamp should be back 16 samples worth", outSamples->getPts(), inSamples->getPts() - IAudioSamples::samplesToDefaultPts(16, oSampleRate)); // get the trailing bytes retval = sampler->resample(outSamples.value(), 0, 0); VS_TUT_ENSURE("should succeed", retval >= 0); VS_LOG_TRACE("r: %d; i: %d; o: %d; ipts: %lld; opts: %lld", retval, 0, outSamples->getNumSamples(), 0LL, outSamples->getPts()); VS_TUT_ENSURE_EQUALS("timestamp should be back 16 samples worth from end of last samples given", outSamples->getPts(), inSamples->getNextPts() - IAudioSamples::samplesToDefaultPts(16, oSampleRate)); }
void AudioResamplerTest :: testResamplingAudio() { RefPointer<IAudioResampler> resampler = IAudioResampler::make(2, 1, 44100, 22050); RefPointer<IAudioSamples> samples = 0; RefPointer<IAudioSamples> resamples = 0; int numSamples = 0; int numPackets = 0; int retval = -1; samples = IAudioSamples::make(1024, 1); VS_TUT_ENSURE("got no samples", samples); resamples = IAudioSamples::make(1024, 2); VS_TUT_ENSURE("got no samples", samples); h->setupReading(h->SAMPLE_FILE); RefPointer<IPacket> packet = IPacket::make(); hw->setupWriting("AudioResamplerTest_3_output.flv", 0, "libmp3lame", "flv"); int outStream = hw->first_output_audio_stream; VS_TUT_ENSURE("Could not find an audio stream in the output", outStream >= 0); int inStream = h->first_input_audio_stream; VS_TUT_ENSURE("Could not find an audio stream in the input", inStream >= 0); RefPointer<IStreamCoder> ic = h->coders[inStream]; RefPointer<IStreamCoder> oc = hw->coders[outStream]; RefPointer<IPacket> opacket = IPacket::make(); VS_TUT_ENSURE("! opacket", opacket); // Set the output coder correctly. int outChannels = 2; int outRate = 44100; resampler = IAudioResampler::make(outChannels, ic->getChannels(), outRate, ic->getSampleRate()); oc->setSampleRate(outRate); oc->setChannels(outChannels); oc->setBitRate(ic->getBitRate()); int maxSamples = 10 * ic->getSampleRate(); // 10 seconds retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); VS_TUT_ENSURE("Could not open output coder", retval >= 0); // write header retval = hw->container->writeHeader(); VS_TUT_ENSURE("could not write header", retval >= 0); while (h->container->readNextPacket(packet.value()) == 0 && numSamples < maxSamples) { if (packet->getStreamIndex() == inStream) { int offset = 0; numPackets++; while (offset < packet->getSize()) { retval = ic->decodeAudio( samples.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any audio", retval > 0); offset += retval; VS_TUT_ENSURE("could not write any samples", samples->getNumSamples() > 0); numSamples += samples->getNumSamples(); resamples = IAudioSamples::make((samples->getNumSamples()*2),2); // now, resample the audio retval = resampler->resample(resamples.value(), samples.value(), 0); VS_TUT_ENSURE("could not resample", retval > 0); VS_TUT_ENSURE("no resamples", resamples->getNumSamples() > 0); VS_TUT_ENSURE_EQUALS("wrong sample rate", resamples->getSampleRate(), outRate); VS_TUT_ENSURE_EQUALS("wrong channels", resamples->getChannels(), outChannels); // now, write out the packets. unsigned int samplesConsumed = 0; do { retval = oc->encodeAudio(opacket.value(), resamples.value(), samplesConsumed); VS_TUT_ENSURE("Could not encode any audio", retval >= 0); samplesConsumed += (unsigned int)retval; VS_LOG_TRACE("packet: %d; is: %d; os: %d", numPackets, numSamples, samplesConsumed); if (opacket->isComplete()) { VS_TUT_ENSURE("could not encode audio", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } // keep going until we've encoded all samples in this buffer. } while (samplesConsumed < resamples->getNumSamples()); } } } // sigh; it turns out that to flush the encoding buffers you need to // ask the encoder to encode a NULL set of samples. So, let's do that. retval = oc->encodeAudio(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any audio", retval >= 0); if (retval > 0) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->container->writeTrailer(); VS_TUT_ENSURE("! writeTrailer", retval >= 0); retval = ic->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = oc->close(); VS_TUT_ENSURE("! close", retval >= 0); VS_TUT_ENSURE("could not get any audio packets", numPackets > 0); VS_TUT_ENSURE("could not decode any audio", numSamples > 0); }
void StreamCoderSpeexTest :: testEncodingSpeexAudio() { // disable because broken on Windows return; RefPointer<IAudioSamples> samples = 0; RefPointer<IAudioSamples> outSamples = 0; RefPointer<IVideoPicture> frame = 0; RefPointer<IRational> num(0); RefPointer<IStreamCoder> ic(0); RefPointer<IStreamCoder> oc(0); RefPointer<IAudioResampler> resampler; int numSamples = 0; int numPackets = 0; int numFrames = 0; int numKeyFrames = 0; int retval = -1; h->setupReading(h->SAMPLE_FILE); RefPointer<IPacket> packet = IPacket::make(); hw->setupWriting("StreamCoderSpeexTest_output.ogg", "libtheora", "libspeex", "ogg"); RefPointer<IPacket> opacket = IPacket::make(); VS_TUT_ENSURE("! opacket", opacket); { // Let's set up audio first. ic = h->coders[h->first_input_audio_stream]; oc = hw->coders[hw->first_output_audio_stream]; // Set the output coder correctly. oc->setSampleRate(16000); oc->setChannels(1); oc->setBitRate(ic->getBitRate()); samples = IAudioSamples::make(1024, ic->getChannels()); VS_TUT_ENSURE("got no samples", samples); outSamples = IAudioSamples::make(1024, 1); VS_TUT_ENSURE("got no samples", outSamples); resampler = IAudioResampler::make(1, ic->getChannels(), 16000, ic->getSampleRate()); retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); VS_TUT_ENSURE("Could not open output coder", retval >= 0); } { // now, let's set up video. ic = h->coders[h->first_input_video_stream]; oc = hw->coders[hw->first_output_video_stream]; // We're going to set up high quality video oc->setBitRate(720000); oc->setGlobalQuality(0); oc->setFlags(oc->getFlags() | IStreamCoder::FLAG_QSCALE); oc->setPixelType(ic->getPixelType()); oc->setHeight(ic->getHeight()); oc->setWidth(ic->getWidth()); num = IRational::make(1,15); oc->setFrameRate(num.value()); num = ic->getTimeBase(); oc->setTimeBase(num.value()); oc->setNumPicturesInGroupOfPictures( ic->getNumPicturesInGroupOfPictures() ); // Ask the StreamCoder to guess width and height for us frame = IVideoPicture::make( ic->getPixelType(), -1, -1); VS_TUT_ENSURE("got no frame", frame); VS_TUT_ENSURE("should not have width", frame->getWidth() <= 0); VS_TUT_ENSURE("should not have height", frame->getHeight() <= 0); retval = ic->open(); VS_TUT_ENSURE("Could not open input coder", retval >= 0); retval = oc->open(); VS_TUT_ENSURE("Could not open output coder", retval >= 0); } // write header retval = hw->container->writeHeader(); VS_TUT_ENSURE("could not write header", retval >= 0); while (h->container->readNextPacket(packet.value()) == 0) { ic = h->coders[packet->getStreamIndex()]; oc = hw->coders[packet->getStreamIndex()]; if (packet->getStreamIndex() == h->first_input_audio_stream) { int offset = 0; numPackets++; while (offset < packet->getSize()) { retval = ic->decodeAudio( samples.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any audio", retval > 0); offset += retval; VS_TUT_ENSURE("could not write any samples", samples->getNumSamples() > 0); numSamples += samples->getNumSamples(); retval = resampler->resample(outSamples.value(), samples.value(), samples->getNumSamples()); VS_TUT_ENSURE("Could not resample audio", retval > 0); // now, write out the packets. unsigned int numSamplesConsumed = 0; do { retval = oc->encodeAudio(opacket.value(), outSamples.value(), numSamplesConsumed); VS_TUT_ENSURE("Could not encode any audio", retval > 0); numSamplesConsumed += retval; if (opacket->isComplete()) { VS_TUT_ENSURE("could not encode audio", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } while (numSamplesConsumed < outSamples->getNumSamples()); } } else if (packet->getStreamIndex() == h->first_input_video_stream) { int offset = 0; numPackets++; VS_LOG_TRACE("packet: pts: %ld; dts: %ld", packet->getPts(), packet->getDts()); while (offset < packet->getSize()) { retval = ic->decodeVideo( frame.value(), packet.value(), offset); VS_TUT_ENSURE("could not decode any video", retval>0); num = ic->getTimeBase(); VS_TUT_ENSURE_EQUALS("time base changed", num->getDouble(), h->expected_time_base); offset += retval; if (frame->isComplete()) { VS_TUT_ENSURE("should now have a frame width", frame->getWidth() > 0); VS_TUT_ENSURE("should now have a frame height", frame->getHeight() > 0); numFrames++; if (frame->isKeyFrame()) numKeyFrames++; frame->setQuality(0); retval = oc->encodeVideo( opacket.value(), frame.value(), -1); VS_TUT_ENSURE("could not encode video", retval >= 0); VS_TUT_ENSURE("could not encode video", opacket->isComplete()); VS_TUT_ENSURE("could not encode video", opacket->getSize() > 0); RefPointer<IBuffer> encodedBuffer = opacket->getData(); VS_TUT_ENSURE("no encoded data", encodedBuffer); VS_TUT_ENSURE("less data than there should be", encodedBuffer->getBufferSize() >= opacket->getSize()); // now, write the packet to disk. retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } } } } // sigh; it turns out that to flush the encoding buffers you need to // ask the encoder to encode a NULL set of samples. So, let's do that. retval = hw->coders[hw->first_output_audio_stream]->encodeAudio(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any audio", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->coders[hw->first_output_video_stream]->encodeVideo(opacket.value(), 0, 0); VS_TUT_ENSURE("Could not encode any video", retval >= 0); if (opacket->isComplete()) { retval = hw->container->writePacket(opacket.value()); VS_TUT_ENSURE("could not write packet", retval >= 0); } retval = hw->container->writeTrailer(); VS_TUT_ENSURE("! writeTrailer", retval >= 0); retval = h->coders[h->first_input_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = h->coders[h->first_input_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_audio_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); retval = hw->coders[hw->first_output_video_stream]->close(); VS_TUT_ENSURE("! close", retval >= 0); VS_TUT_ENSURE("could not get any audio packets", numPackets > 0); VS_TUT_ENSURE("could not decode any audio", numSamples > 0); VS_TUT_ENSURE("could not decode any video", numFrames >0); VS_TUT_ENSURE("could not find any key frames", numKeyFrames >0); if (h->expected_packets) VS_TUT_ENSURE_EQUALS("unexpected number of packets", numPackets, h->expected_packets); if (h->expected_audio_samples) VS_TUT_ENSURE_EQUALS("unexpected number of audio samples", numSamples, h->expected_audio_samples); if (h->expected_video_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video frames", numFrames, h->expected_video_frames); if (h->expected_video_key_frames) VS_TUT_ENSURE_EQUALS("unexpected number of video key frames", numKeyFrames, h->expected_video_key_frames); }