void MediaPictureResamplerTest::testCreation() { RefPointer<MediaPictureResampler> resampler; int32_t oWidth = 200; int32_t oHeight = 100; PixelFormat::Type oFormat = PixelFormat::PIX_FMT_YUV420P; int32_t iWidth = 100; int32_t iHeight = 100; PixelFormat::Type iFormat = PixelFormat::PIX_FMT_ABGR; { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); TS_ASSERT_THROWS(MediaPictureResampler::make(0, oHeight, oFormat, iWidth, iHeight, iFormat, 0),HumbleInvalidArgument); TS_ASSERT_THROWS(MediaPictureResampler::make(oWidth, 0, oFormat, iWidth, iHeight, iFormat, 0),HumbleInvalidArgument); TS_ASSERT_THROWS(MediaPictureResampler::make(oWidth, oHeight, PixelFormat::PIX_FMT_NONE, iWidth, iHeight, iFormat, 0),HumbleInvalidArgument); TS_ASSERT_THROWS(MediaPictureResampler::make(oWidth, oHeight, oFormat, 0, iHeight, iFormat, 0),HumbleInvalidArgument); TS_ASSERT_THROWS(MediaPictureResampler::make(oWidth, oHeight, oFormat, iWidth, 0, iFormat, 0),HumbleInvalidArgument); TS_ASSERT_THROWS(MediaPictureResampler::make(oWidth, oHeight, oFormat, iWidth, iHeight, PixelFormat::PIX_FMT_NONE, 0),HumbleInvalidArgument); } resampler = MediaPictureResampler::make(oWidth, oHeight, oFormat, iWidth, iHeight, iFormat, 0); TS_ASSERT(resampler); }
void AudioResamplerTest :: testGetters() { RefPointer<IAudioResampler> sampler = IAudioResampler::make(1, 2, 22050, 44100, IAudioSamples::FMT_S16, IAudioSamples::FMT_FLT, 16, 1, true, 0.8); VS_TUT_ENSURE("!sampler", sampler); VS_TUT_ENSURE_EQUALS("", sampler->getOutputChannels(), 1); VS_TUT_ENSURE_EQUALS("", sampler->getInputChannels(), 2); VS_TUT_ENSURE_EQUALS("", sampler->getOutputRate(), 22050); VS_TUT_ENSURE_EQUALS("", sampler->getInputRate(), 44100); VS_TUT_ENSURE_EQUALS("", sampler->getOutputFormat(), IAudioSamples::FMT_S16); VS_TUT_ENSURE_EQUALS("", sampler->getInputFormat(), IAudioSamples::FMT_FLT); VS_TUT_ENSURE_EQUALS("", sampler->getFilterLen(), 16); VS_TUT_ENSURE_EQUALS("", sampler->getLog2PhaseCount(), 1); VS_TUT_ENSURE("", sampler->isLinear()); VS_TUT_ENSURE_DISTANCE("", sampler->getCutoffFrequency(), 0.8, 0.001); // Turn down logging for this test as it should be noisy LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); sampler = IAudioResampler::make(3, 2, 22050, 44100); VS_TUT_ENSURE("sampler", !sampler); sampler = IAudioResampler::make(-1, -1, -1, -1); VS_TUT_ENSURE("sampler", !sampler); }
void PropertyTest :: testSetMetaData() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); RefPointer<Configurable> c = Demuxer::make(); RefPointer<KeyValueBag> dict = KeyValueBag::make(); RefPointer<KeyValueBag> unset = KeyValueBag::make(); const char* realKey = "packetsize"; const char* fakeKey = "not-a-valid-key-no-way-all-hail-zod"; const char* realValue = "1000"; const char* fakeValue = "1025"; dict->setValue(realKey, realValue); dict->setValue(fakeKey, fakeValue); TSM_ASSERT("", dict->getNumKeys() == 2); TSM_ASSERT("", unset->getNumKeys() == 0); c->setProperty(dict.value(), unset.value()); TSM_ASSERT("", c->getPropertyAsLong(realKey) == 1000); // make sure the fake isn't there. TS_ASSERT_THROWS(c->getPropertyMetaData(fakeKey), PropertyNotFoundException); // now make sure the returned dictionary only had the fake in it. TSM_ASSERT("", unset->getNumKeys() == 1); TSM_ASSERT("", strcmp(unset->getValue(fakeKey, KeyValueBag::KVB_NONE), fakeValue) == 0); }
void PropertyTest :: testIteration() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_WARN, false); RefPointer<Configurable> c = Demuxer::make(); int32_t numProperties = c->getNumProperties(); TSM_ASSERT("", numProperties > 0); for(int32_t i = 0; i < numProperties; i++) { RefPointer <Property> property = c->getPropertyMetaData(i); const char* name = property->getName(); VS_LOG_DEBUG("Name: %s", name); VS_LOG_DEBUG("Description: %s", property->getHelp()); VS_LOG_DEBUG("Default: %lld", property->getDefault()); if (strcmp(name, "cryptokey")==0) continue; VS_LOG_DEBUG("Current value (boolean) : %d", (int32_t)c->getPropertyAsBoolean(name)); VS_LOG_DEBUG("Current value (double) : %f", c->getPropertyAsDouble(name)); VS_LOG_DEBUG("Current value (long) : %lld", c->getPropertyAsLong(name)); RefPointer<Rational> rational = c->getPropertyAsRational(name); VS_LOG_DEBUG("Current value (rational): %f", rational->getValue()); char* value=c->getPropertyAsString(name); VS_LOG_DEBUG("Current value (string) : %s", value); if (value) free(value); } }
void StreamCoderTest :: testSetCodec() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_WARN, false); h->setupReading(h->SAMPLE_FILE); coder = h->coders[0]; RefPointer<ICodec> codec = h->codecs[0]; // The helper, the coder, and me VS_TUT_ENSURE_EQUALS("wrong codec ref count", codec->getCurrentRefCount(), 3); coder->setCodec(0); // The helper, and me VS_TUT_ENSURE_EQUALS("wrong codec ref count", codec->getCurrentRefCount(), 2); coder->setCodec(ICodec::CODEC_ID_NELLYMOSER); codec = coder->getCodec(); VS_TUT_ENSURE("could not find NELLYMOSER codec", codec); // The coder, and me VS_TUT_ENSURE_EQUALS("codec refcount wrong", codec->getCurrentRefCount(), 2); // Just the helper VS_TUT_ENSURE_EQUALS("codec refcount wrong", h->codecs[0]->getCurrentRefCount(), 1); codec = ICodec::findDecodingCodecByName("aac"); VS_TUT_ENSURE("could not find ac3 decoder", codec); VS_TUT_ENSURE_EQUALS("ac3 codec refcount wrong", codec->getCurrentRefCount(), 1); coder->setCodec(codec.value()); VS_TUT_ENSURE_EQUALS("ac3 codec refcount wrong after setting", codec->getCurrentRefCount(), 2); // This should fail because it's an Encoder, not a Decoder RefPointer<ICodec> encodec = h->codecs[0]; encodec = ICodec::findEncodingCodecByName("libmp3lame"); VS_TUT_ENSURE("could not find libmp3lame encoder", codec); coder->setSampleRate(22050); coder->setCodec(encodec.value()); codec = coder->getCodec(); VS_TUT_ENSURE_EQUALS("should allow wrong direction", codec.value(), encodec.value()); int retval = coder->open(); VS_TUT_ENSURE("should succeed even though wrong direction", retval >= 0); (void) retval; // in release compiles VS_TUT_ENSURE is removed and so -Werror produces errors about unused retvals coder->close(); }
void PropertyTest :: testCreation() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_WARN, false); RefPointer<Configurable> c = Demuxer::make(); RefPointer<Property> property = c->getPropertyMetaData("packetsize"); VS_LOG_DEBUG("Name: %s", property->getName()); VS_LOG_DEBUG("Description: %s", property->getHelp()); TSM_ASSERT("should exist", property); }
void AudioResamplerTest :: testInvalidArguments() { int retval = -1; // Turn down logging for this test as it should be noisy LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); RefPointer<IAudioResampler> sampler; sampler = IAudioResampler::make(3, 2, 22050, 44100); VS_TUT_ENSURE("sampler", !sampler); sampler = IAudioResampler::make(-1, -1, -1, -1); VS_TUT_ENSURE("sampler", !sampler); sampler = IAudioResampler::make(1, 2, 22050, 44100, IAudioSamples::FMT_S16, IAudioSamples::FMT_S16, -1, 0, true, 0.8); VS_TUT_ENSURE("sampler", !sampler); sampler = IAudioResampler::make(1, 2, 22050, 44100, IAudioSamples::FMT_S16, IAudioSamples::FMT_S16, 16, -1, true, 0.8); VS_TUT_ENSURE("sampler", !sampler); sampler = IAudioResampler::make(1, 2, 22050, 44100, IAudioSamples::FMT_S16, IAudioSamples::FMT_S16, 16, 0, true, -1.0); VS_TUT_ENSURE("sampler", !sampler); sampler = IAudioResampler::make(1, 2, 22050, 44100); VS_TUT_ENSURE("! sampler", sampler); retval = sampler->resample(0, 0, 0); VS_TUT_ENSURE("no crash", retval < 0); RefPointer<IAudioSamples> inSamples = IAudioSamples::make(1024, 1); RefPointer<IAudioSamples> outSamples = IAudioSamples::make(1024, 1); // Set to the wrong sample rate. inSamples->setComplete(true, 2, 22050, 2, IAudioSamples::FMT_S16, 0); retval = sampler->resample(outSamples.value(), inSamples.value(), 4); VS_TUT_ENSURE("should fail because of sample rate", retval < 0); inSamples->setComplete(true, 4, 44100, 1, IAudioSamples::FMT_S16, 0); retval = sampler->resample(outSamples.value(), inSamples.value(), 4); VS_TUT_ENSURE("should fail because of channels", retval < 0); }
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 EncoderTest::testRegression36() { Logger::setGlobalIsLogging(Logger::LEVEL_TRACE, false); LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_INFO, false); { const int32_t sampleRate = 44100; const int32_t numSamples = sampleRate; // this is important for the test -- we want to extract 1 second of audio const AudioChannel::Layout channelLayout = AudioChannel::CH_LAYOUT_STEREO; const int32_t channels = AudioChannel::getNumChannelsInLayout(channelLayout); const AudioFormat::Type audioFormat = AudioFormat::SAMPLE_FMT_FLTP; const char* testOutputName = "EncoderTest_testRegression36.mp3"; const Codec::ID codecId = Codec::CODEC_ID_MP3; const int64_t bitRate = 64000; testRegression36Internal (codecId, numSamples, sampleRate, channels, channelLayout, audioFormat, bitRate, testOutputName); } { const int32_t sampleRate = 22050; const int32_t numSamples = sampleRate; // this is important for the test -- we want to extract 1 second of audio const AudioChannel::Layout channelLayout = AudioChannel::CH_LAYOUT_MONO; const int32_t channels = AudioChannel::getNumChannelsInLayout(channelLayout); const AudioFormat::Type audioFormat = AudioFormat::SAMPLE_FMT_FLTP; const char* testOutputName = "EncoderTest_testRegression36.ogg"; const Codec::ID codecId = Codec::CODEC_ID_VORBIS; const int64_t bitRate = 64000; testRegression36Internal (codecId, numSamples, sampleRate, channels, channelLayout, audioFormat, bitRate, testOutputName); } { const int32_t sampleRate = 22050; const int32_t numSamples = sampleRate; // this is important for the test -- we want to extract 1 second of audio const AudioChannel::Layout channelLayout = AudioChannel::CH_LAYOUT_MONO; const int32_t channels = AudioChannel::getNumChannelsInLayout(channelLayout); const AudioFormat::Type audioFormat = AudioFormat::SAMPLE_FMT_FLT; const char* testOutputName = "EncoderTest_testRegression36.flv"; const Codec::ID codecId = Codec::CODEC_ID_NELLYMOSER; const int64_t bitRate = 64000; testRegression36Internal (codecId, numSamples, sampleRate, channels, channelLayout, audioFormat, bitRate, testOutputName); } }
void PropertyTest::testValgrindStrlenIssue() { // This is a bug in FFmpeg which I fixed in our // captive build. The error crops up for BINARY // option types that have no data in them. // This test tries to ensure we have a patched FFmpeg. RefPointer<Configurable> c = Demuxer::make(); { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); char* value = c->getPropertyAsString("cryptokey"); if (value) free(value); } }
void BitStreamFilterTypeTest::testGetBitStreamFilterType() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_INFO, false); // This test makes sure that the getBitStreamFilterType method calls Global::init RefPointer<BitStreamFilterType> t = BitStreamFilterType::getBitStreamFilterType(0); TS_ASSERT(t.value()); int32_t n = BitStreamFilterType::getNumBitStreamFilterTypes(); for(int32_t i = 0; i < n; i++) { RefPointer<BitStreamFilterType> t1 = BitStreamFilterType::getBitStreamFilterType(i); TS_ASSERT(t1->getName() != 0); RefPointer<BitStreamFilterType> t2 = BitStreamFilterType::getBitStreamFilterType(t1->getName()); TS_ASSERT(strcmp(t1->getName(), t2->getName()) == 0); VS_LOG_DEBUG("(%03d) Filter: %s", i, t1->getName()); } }
void CodecTest::testGetSupportedProfiles() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_INFO, false); codec = Codec::findDecodingCodec(Codec::CODEC_ID_MPEG4); TS_ASSERT(codec); int32_t num = codec->getNumSupportedProfiles(); TS_ASSERT(num > 0); for (int i = 0; i < num; i++) { RefPointer<CodecProfile> p = codec->getSupportedProfile(i); TS_ASSERT(p); VS_LOG_DEBUG("Profile: %s", p->getName()); } TS_ASSERT(!codec->getSupportedProfile(-1)); TS_ASSERT(!codec->getSupportedProfile(0x7FFFFFFF)); }
void StreamCoderTest :: testOpenButNoClose() { int retval = 0; // Temporarily turn down logging LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_WARN, false); { Helper lh; lh.setupReading(lh.SAMPLE_FILE); for(int i = 0; i < lh.num_streams; i++) { retval = lh.coders[i]->open(); VS_TUT_ENSURE("could not open coder", retval >= 0); } } }
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 CodecTest :: testGetInstalledCodecs() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_INFO, false); int num = Codec::getNumInstalledCodecs(); TSM_ASSERT("should be > 1", num > 1); for(int i = 0; i < num; i++) { codec = Codec::getInstalledCodec(i); TSM_ASSERT("should be valid", codec); if (codec) { VS_LOG_DEBUG("%s: %s", codec->getName(), codec->getLongName()); } } TSM_ASSERT("could fail quietly", 0 == Codec::getInstalledCodec(-1)); TSM_ASSERT("could fail quietly", 0 == Codec::getInstalledCodec(0x7FFFFFFF)); }
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); }
/** * Test that memory is not leaked/corrupted during error paths. */ void EncoderTest::testEncodeInvalidParameters() { // Sub-test 1 { int32_t width=176; int32_t height=360; // invalid dimensions for H263 codec RefPointer<Codec> codec = Codec::findEncodingCodec(Codec::CODEC_ID_H263); RefPointer<Encoder> encoder = Encoder::make(codec.value()); RefPointer<MediaPicture> picture = MediaPicture::make(width*2,height*2, PixelFormat::PIX_FMT_YUV420P); // set the encoder properties we need encoder->setWidth(picture->getWidth()); encoder->setHeight(picture->getHeight()); encoder->setPixelFormat(picture->getFormat()); encoder->setProperty("b", (int64_t)400000); // bitrate encoder->setProperty("g", (int64_t) 10); // gop RefPointer<Rational> tb = Rational::make(1,25); encoder->setTimeBase(tb.value()); // open the encoder try { // Temporarily turn down logging LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); encoder->open(0, 0); TS_FAIL("should never get here"); } catch (std::exception & e) { // ignore exception } } // Sub-test 2 { int32_t width=176; int32_t height=144; RefPointer<Codec> codec = Codec::findEncodingCodec(Codec::CODEC_ID_H264); RefPointer<Encoder> encoder = Encoder::make(codec.value()); RefPointer<MediaPicture> picture = MediaPicture::make(width*2,height*2, PixelFormat::PIX_FMT_YUV420P); // set the encoder properties we need encoder->setWidth(picture->getWidth()); encoder->setHeight(picture->getHeight()); encoder->setPixelFormat(picture->getFormat()); encoder->setProperty("b", (int64_t)400000); // bitrate encoder->setProperty("g", (int64_t) 10); // gop encoder->setProperty("bf", (int64_t)1); // max b frames RefPointer<Rational> tb = Rational::make(1,25); encoder->setTimeBase(tb.value()); // Do not open the encoder // create an output muxer RefPointer<Muxer> muxer = Muxer::make("EncoderTest_encodeVideo.mov", 0, 0); // add a stream for the encoded packets try { // Temporarily turn down logging LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); RefPointer<MuxerStream> stream = muxer->addNewStream(encoder.value()); TS_FAIL("should never get here"); } catch (std::exception & e) { // success } } }
/** * This test will read ironman (FLV, H263 video and mp3 audio) and transcode * to MP4 (H264 Video and aac audio). */ void EncoderTest::testTranscode() { // enable trace logging Logger::setGlobalIsLogging(Logger::LEVEL_TRACE, false); const bool isMemCheck = getenv("VS_TEST_MEMCHECK") ? true : false; LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_INFO, false); TestData::Fixture* fixture; fixture=mFixtures.getFixture("testfile.flv"); // fixture=mFixtures.getFixture("testfile_h264_mp4a_tmcd.mov"); // fixture=mFixtures.getFixture("bigbuckbunny_h264_aac_5.1.mp4"); TS_ASSERT(fixture); char filepath[2048]; mFixtures.fillPath(fixture, filepath, sizeof(filepath)); RefPointer<Demuxer> source = Demuxer::make(); source->open(filepath, 0, false, true, 0, 0); int32_t numStreams = source->getNumStreams(); TS_ASSERT_EQUALS(fixture->num_streams, numStreams); // Let's create a helper object to help us with decoding typedef struct { MediaDescriptor::Type type; RefPointer<DemuxerStream> stream; RefPointer<Decoder> decoder; RefPointer<MediaSampled> media; } DemuxerStreamHelper; // I know there are only 2 in the input file. DemuxerStreamHelper inputHelpers[10]; for(int32_t i = 0; i < numStreams; i++) { DemuxerStreamHelper* input = &inputHelpers[i]; input->stream = source->getStream(i); input->decoder = input->stream->getDecoder(); if (!input->decoder) // skip break; input->decoder->open(0, 0); input->type = input->decoder->getCodecType(); if (input->type == MediaDescriptor::MEDIA_AUDIO) input->media = MediaAudio::make( input->decoder->getFrameSize(), input->decoder->getSampleRate(), input->decoder->getChannels(), input->decoder->getChannelLayout(), input->decoder->getSampleFormat()); else if (input->type == MediaDescriptor::MEDIA_VIDEO) input->media = MediaPicture::make( input->decoder->getWidth(), input->decoder->getHeight(), input->decoder->getPixelFormat() ); } // now, let's set up our output file. RefPointer<Muxer> muxer = Muxer::make("EncoderTest_testTranscode.mp4", 0, 0); RefPointer<MuxerFormat> format = muxer->getFormat(); // Let's create a helper object to help us with decoding typedef struct { MediaDescriptor::Type type; RefPointer<MuxerStream> stream; RefPointer<MediaResampler> resampler; RefPointer<MediaSampled> media; RefPointer<Encoder> encoder; } MuxerStreamHelper; MuxerStreamHelper outputHelpers[10]; for(int32_t i = 0; i < numStreams; i++) { DemuxerStreamHelper *input = &inputHelpers[i]; MuxerStreamHelper *output = &outputHelpers[i]; if (!input->decoder) // skip break; output->type = input->type; RefPointer<Encoder> encoder; if (output->type == MediaDescriptor::MEDIA_VIDEO) { RefPointer<Codec> codec = Codec::findEncodingCodec(Codec::CODEC_ID_H264); encoder = Encoder::make(codec.value()); // set the encoder properties we need encoder->setWidth(input->decoder->getWidth()); encoder->setHeight(input->decoder->getHeight()); encoder->setPixelFormat(input->decoder->getPixelFormat()); encoder->setProperty("b", (int64_t)400000); // bitrate encoder->setProperty("g", (int64_t) 10); // gop encoder->setProperty("bf", (int64_t)0); // max b frames RefPointer<Rational> tb = Rational::make(1,2997); encoder->setTimeBase(tb.value()); } else if (output->type == MediaDescriptor::MEDIA_AUDIO) { RefPointer<Codec> codec = Codec::findEncodingCodec(Codec::CODEC_ID_AAC); encoder = Encoder::make(codec.value()); // set the encoder properties we need encoder->setSampleRate(input->decoder->getSampleRate()); encoder->setSampleFormat(input->decoder->getSampleFormat()); encoder->setSampleFormat(AudioFormat::SAMPLE_FMT_S16); encoder->setChannelLayout(input->decoder->getChannelLayout()); encoder->setChannels(input->decoder->getChannels()); encoder->setProperty("b", (int64_t)64000); // bitrate RefPointer<Rational> tb = Rational::make(1,encoder->getSampleRate()); encoder->setTimeBase(tb.value()); // //input->decoder->getTimeBase(); // output->encoder->setTimeBase(tb.value()); } output->encoder.reset(encoder.value(), true); if (output->encoder) { if (format->getFlag(MuxerFormat::GLOBAL_HEADER)) output->encoder->setFlag(Encoder::FLAG_GLOBAL_HEADER, true); output->encoder->open(0,0); // sometimes encoders need to change parameters to fit; let's see // if that happened. output->stream = muxer->addNewStream(output->encoder.value()); } output->media = input->media; output->resampler = 0; if (output->type == MediaDescriptor::MEDIA_AUDIO) { // sometimes encoders only accept certain media types and discard // our suggestions. Let's check. if ( output->encoder->getSampleRate() != input->decoder->getSampleRate() || output->encoder->getSampleFormat() != input->decoder->getSampleFormat() || output->encoder->getChannelLayout() != input->decoder->getChannelLayout() || output->encoder->getChannels() != input->decoder->getChannels() ) { // we need a resampler. VS_LOG_DEBUG("Resampling: [%"PRId32", %"PRId32", %"PRId32"] [%"PRId32", %"PRId32", %"PRId32"]", (int32_t)output->encoder->getChannelLayout(), (int32_t)output->encoder->getSampleRate(), (int32_t)output->encoder->getSampleFormat(), (int32_t)input->decoder->getChannelLayout(), (int32_t)input->decoder->getSampleRate(), (int32_t)input->decoder->getSampleFormat() ); RefPointer<MediaAudioResampler> resampler = MediaAudioResampler::make( output->encoder->getChannelLayout(), output->encoder->getSampleRate(), output->encoder->getSampleFormat(), input->decoder->getChannelLayout(), input->decoder->getSampleRate(), input->decoder->getSampleFormat() ); resampler->open(); output->resampler.reset(resampler.value(), true); output->media = MediaAudio::make( output->encoder->getFrameSize(), output->encoder->getSampleRate(), output->encoder->getChannels(), output->encoder->getChannelLayout(), output->encoder->getSampleFormat()); } } } // now we should be ready to open the muxer muxer->open(0, 0); // now, let's start a decoding loop. RefPointer<MediaPacket> packet = MediaPacket::make(); int numPackets = 0; while(source->read(packet.value()) >= 0) { // got a packet; now we try to decode it. if (packet->isComplete()) { int32_t streamNo = packet->getStreamIndex(); DemuxerStreamHelper *input = &inputHelpers[streamNo]; MuxerStreamHelper* output = &outputHelpers[streamNo]; if (input->decoder) decodeAndEncode( packet.value(), input->decoder.value(), input->media.value(), output->resampler.value(), output->media.value(), muxer.value(), output->encoder.value()); ++numPackets; if (isMemCheck && numPackets > 100) { VS_LOG_WARN("Exiting early under valgrind"); break; } } } // now, flush any cached packets for(int i = 0; i < numStreams; i++) { DemuxerStreamHelper *input = &inputHelpers[i]; MuxerStreamHelper* output = &outputHelpers[i]; if (input->decoder) decodeAndEncode( 0, input->decoder.value(), input->media.value(), output->resampler.value(), output->media.value(), muxer.value(), output->encoder.value()); } source->close(); muxer->close(); }
void EncoderTest::testEncodeVideo() { Logger::setGlobalIsLogging(Logger::LEVEL_TRACE, false); LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_INFO, false); const bool isMemCheck = getenv("VS_TEST_MEMCHECK") ? true : false; const int32_t maxPics = isMemCheck ? 10 : 500; int32_t width=176; int32_t height=144; RefPointer<Codec> codec = Codec::findEncodingCodec(Codec::CODEC_ID_H264); RefPointer<Encoder> encoder = Encoder::make(codec.value()); RefPointer<MediaPicture> picture = MediaPicture::make(width*2,height*2, PixelFormat::PIX_FMT_YUV420P); // set the encoder properties we need encoder->setWidth(picture->getWidth()); encoder->setHeight(picture->getHeight()); encoder->setPixelFormat(picture->getFormat()); encoder->setProperty("b", (int64_t)400000); // bitrate encoder->setProperty("g", (int64_t) 10); // gop encoder->setProperty("bf", (int64_t)1); // max b frames RefPointer<Rational> tb = Rational::make(1,25); encoder->setTimeBase(tb.value()); // mandlebrot, that is then negated, horizontally flipped, and edge detected, before // final outputting to a new picture with each version in one of 4 quadrants. char graphCommand[1024]; snprintf(graphCommand,sizeof(graphCommand),"mandelbrot=s=%dx%d[mb];" "[mb]split=4[0][1][2][3];" "[0]pad=iw*2:ih*2[a];" "[1]negate[b];" "[2]hflip[c];" "[3]edgedetect[d];" "[a][b]overlay=w[x];" "[x][c]overlay=0:h[y];" "[y][d]overlay=w:h[out]", width, height); RefPointer<FilterGraph> graph = FilterGraph::make(); RefPointer<FilterPictureSink> fsink = graph->addPictureSink("out", picture->getFormat()); graph->open(graphCommand); // let's set a frame time base of 1/30 RefPointer<Rational> pictureTb = Rational::make(1,30); // create an output muxer RefPointer<Muxer> muxer = Muxer::make("EncoderTest_encodeVideo.mov", 0, 0); RefPointer<MuxerFormat> format = muxer->getFormat(); // if the container will require a global header, then the encoder needs to set this. if (format->getFlag(MuxerFormat::GLOBAL_HEADER)) encoder->setFlag(Encoder::FLAG_GLOBAL_HEADER, true); // open the encoder encoder->open(0, 0); // add a stream for the encoded packets { RefPointer<MuxerStream> stream = muxer->addNewStream(encoder.value()); } // and open the muxer muxer->open(0, 0); // now we're (in theory) ready to start writing data. int32_t numPics = 0; RefPointer<MediaPacket> packet; while(fsink->getPicture(picture.value()) >= 0 && numPics < maxPics) { picture->setTimeBase(pictureTb.value()); picture->setTimeStamp(numPics); // let's encode packet = MediaPacket::make(); encoder->encodeVideo(packet.value(), picture.value()); if (packet->isComplete()) { muxer->write(packet.value(), false); } ++numPics; } // now flush the encoder do { packet = MediaPacket::make(); encoder->encodeVideo(packet.value(), 0); if (packet->isComplete()) { muxer->write(packet.value(), false); } } while (packet->isComplete()); muxer->close(); }
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 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 EncoderTest::testEncodeAudio() { Logger::setGlobalIsLogging(Logger::LEVEL_TRACE, false); LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_INFO, false); const bool isMemCheck = getenv("VS_TEST_MEMCHECK") ? true : false; const int32_t sampleRate = 44100; const int32_t maxSamples = isMemCheck ? sampleRate*0.5 : sampleRate*10; const int32_t numSamples = 1024; const AudioChannel::Layout channelLayout = AudioChannel::CH_LAYOUT_STEREO; const int32_t channels = AudioChannel::getNumChannelsInLayout(channelLayout); const AudioFormat::Type audioFormat = AudioFormat::SAMPLE_FMT_S16; RefPointer<Codec> codec = Codec::findEncodingCodec(Codec::CODEC_ID_AAC); RefPointer<Encoder> encoder = Encoder::make(codec.value()); RefPointer<FilterGraph> graph = FilterGraph::make(); RefPointer<MediaAudio> audio = MediaAudio::make(numSamples, sampleRate, channels, channelLayout, audioFormat); // set the encoder properties we need encoder->setSampleRate(audio->getSampleRate()); encoder->setSampleFormat(audio->getFormat()); encoder->setChannelLayout(audio->getChannelLayout()); encoder->setChannels(audio->getChannels()); encoder->setProperty("b", (int64_t)64000); // bitrate RefPointer<Rational> tb = Rational::make(1,25); encoder->setTimeBase(tb.value()); // create an output muxer RefPointer<Muxer> muxer = Muxer::make("EncoderTest_encodeAudio.mp4", 0, 0); RefPointer<MuxerFormat> format = muxer->getFormat(); if (format->getFlag(MuxerFormat::GLOBAL_HEADER)) encoder->setFlag(Encoder::FLAG_GLOBAL_HEADER, true); // open the encoder encoder->open(0, 0); RefPointer<FilterAudioSink> fsink = graph->addAudioSink("out", audio->getSampleRate(), audio->getChannelLayout(), audio->getFormat()); // Generate a 220 Hz sine wave with a 880 Hz beep each second, for 10 seconds. graph->open("sine=frequency=660:beep_factor=4:duration=11[out]"); // Generate an amplitude modulated signal //graph->open("aevalsrc=sin(10*2*PI*t)*sin(880*2*PI*t)[out]"); // add a stream for the encoded packets { RefPointer<MuxerStream> stream = muxer->addNewStream(encoder.value()); } // and open the muxer muxer->open(0, 0); // now we're (in theory) ready to start writing data. int32_t numFrames = 0; RefPointer<MediaPacket> packet; while(fsink->getAudio(audio.value()) >= 0 && audio->isComplete() && numFrames*audio->getNumSamples() < maxSamples) { audio->setTimeStamp(numFrames*audio->getNumSamples()); // let's encode packet = MediaPacket::make(); encoder->encodeAudio(packet.value(), audio.value()); if (packet->isComplete()) { muxer->write(packet.value(), false); } ++numFrames; } // now flush the encoder do { packet = MediaPacket::make(); encoder->encodeAudio(packet.value(), 0); if (packet->isComplete()) { muxer->write(packet.value(), false); } } while (packet->isComplete()); muxer->close(); }
void StreamCoderTest :: testGetters() { int refcount=0; h->setupReading(h->SAMPLE_FILE); for(int i = 0; i< h->num_streams; i++) { RefPointer<IStream> stream; RefPointer<ICodec> codec; RefPointer<IRational> rational; stream = h->streams[i]; coder = h->coders[i]; VS_TUT_ENSURE_EQUALS("invalid direction", coder->getDirection(), IStreamCoder::DECODING); codec = coder->getCodec(); refcount = codec->getCurrentRefCount(); { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_ERROR, false); coder->setCodec(codec.value()); } // ensure that one release and one acquire happens VS_TUT_ENSURE_EQUALS("invalid releasing or acquiring of codec", codec->getCurrentRefCount(), refcount); VS_TUT_ENSURE_EQUALS("wrong codec type", codec->getType(), h->expected_codec_types[i]); VS_TUT_ENSURE_EQUALS("wrong codec id", codec->getID(), h->expected_codec_ids[i]); if (codec->getType() == ICodec::CODEC_TYPE_AUDIO) { if (h->expected_sample_rate) VS_TUT_ENSURE_EQUALS("unexpected sample rate", coder->getSampleRate(), h->expected_sample_rate ); if (h->expected_channels) VS_TUT_ENSURE_EQUALS("unexpected sample rate", coder->getChannels(), h->expected_channels ); } else if (codec->getType() == ICodec::CODEC_TYPE_VIDEO) { if (h->expected_width) VS_TUT_ENSURE_EQUALS("unexpected width", coder->getWidth(), h->expected_width ); if (h->expected_height) VS_TUT_ENSURE_EQUALS("unexpected height", coder->getHeight(), h->expected_height ); if (h->expected_gops) VS_TUT_ENSURE_EQUALS("unexpected group of pictures", coder->getNumPicturesInGroupOfPictures(), h->expected_gops ); if (h->expected_pixel_format != IPixelFormat::NONE) VS_TUT_ENSURE_EQUALS("unexpected group of pictures", coder->getPixelType(), h->expected_pixel_format ); if (h->expected_time_base) { rational = coder->getTimeBase(); VS_TUT_ENSURE_DISTANCE("unexpected time base", rational->getDouble(), h->expected_time_base, 0.0001 ); rational = stream->getTimeBase(); VS_TUT_ENSURE_DISTANCE("unexpected time base", rational->getDouble(), h->expected_time_base, 0.0001 ); } } else { VS_LOG_ERROR("Unexpected type of codec"); TS_ASSERT(false); } } }
void StreamCoderTest :: testTimestamps() { LoggerStack stack; stack.setGlobalLevel(Logger::LEVEL_WARN, false); Helper hr; hr.setupReading("testfile_h264_mp4a_tmcd.mov"); RefPointer<IStreamCoder> ac; RefPointer<IStreamCoder> vc; if (hr.first_input_audio_stream >= 0) ac = hr.coders[hr.first_input_audio_stream]; if (hr.first_input_video_stream >= 0) vc = hr.coders[hr.first_input_video_stream]; hw->setupWriting("StreamCoderTest_7_output.flv", vc ? "flv" : 0, ac ? "libmp3lame" : 0, "flv", vc ? vc->getPixelType() : IPixelFormat::YUV420P, vc ? vc->getWidth() : 0, vc ? vc->getHeight() : 0, false, ac ? ac->getSampleRate() : 0, ac ? ac->getChannels() : 0, true); RefPointer<IVideoPicture> frame; if (vc) { frame = IVideoPicture::make( vc->getPixelType(), vc->getWidth(), vc->getHeight()); } RefPointer<IAudioSamples> samples; if (ac) { samples = IAudioSamples::make(10000, ac->getChannels()); } int retval = -1; int numReads = 0; int maxReads = 10000; while ((retval = hr.readNextDecodedObject(samples.value(), frame.value())) > 0 && numReads < maxReads) { int result = retval; numReads++; VS_TUT_ENSURE("should only return 1 or 2", retval == 1 || retval == 2); if (retval == 1) { VS_TUT_ENSURE("something should be complete...", samples->isComplete()); retval = hw->writeSamples(samples.value()); VS_TUT_ENSURE("could not write audio", retval >= 0); } if (retval == 2) { VS_TUT_ENSURE("something should be complete...", frame->isComplete()); retval = hw->writeFrame(frame.value()); VS_TUT_ENSURE("could not write video", retval >= 0); } { RefPointer<IRational> timebase = hr.coders[hr.packet->getStreamIndex()]->getTimeBase(); ICodec::Type type = hr.coders[hr.packet->getStreamIndex()]->getCodecType(); (void) type; (void) result; VS_LOG_TRACE("Packet stream: %d.%d; pts: %lld; dts: %lld; spts: %lld; fpts: %lld; tb: %d/%d; ret: %d," "samps: %d", hr.packet->getStreamIndex(), type, hr.packet->getPts(), hr.packet->getDts(), samples ? samples->getPts() : -1, frame ? frame->getPts() : -1, timebase->getNumerator(), timebase->getDenominator(), result, samples ? samples->getNumSamples() : 0); } } VS_TUT_ENSURE("should return some data", numReads > 0); }