void BitStreamFilterTest::testNoiseFilter() { const char* name = "noise"; RefPointer<BitStreamFilter> f = BitStreamFilter::make(name); // let's generate a buffer to add noise to. const int32_t inSize = 1024; // Annoyingly I have to add FF_INPUT_BUFFER_PADDING_SIZE because the noise // filter incorrectly memcopies an additional 16 bytes, and I want Valgrind to // not worry about that. RefPointer<Buffer> inBuf = Buffer::make(0, inSize+FF_INPUT_BUFFER_PADDING_SIZE); uint8_t* in = static_cast<uint8_t*>(inBuf->getBytes(0, inSize)); int32_t outSize = inSize; RefPointer<Buffer> outBuf = Buffer::make(0, outSize+FF_INPUT_BUFFER_PADDING_SIZE); uint8_t* out = static_cast<uint8_t*>(outBuf->getBytes(0, outSize)); for(int32_t i = 0; i < inSize+FF_INPUT_BUFFER_PADDING_SIZE; i++) { in[i] = static_cast<uint8_t>(i); out[i] = in[i]; } outSize = f->filter(outBuf.value(), 0, inBuf.value(), 0, inSize, 0, 0, false); TS_ASSERT_EQUALS(outSize, inSize); int matches = 0; for(int32_t i = 0; i < inSize; i++) { if (in[i] == out[i]) ++ matches; } // noise should make sure that not all elements match. TS_ASSERT(matches < inSize); }
void BitStreamFilterTest::testChompFilter() { const char* name = "chomp"; RefPointer<BitStreamFilter> f = BitStreamFilter::make(name); // let's generate a buffer to chomp nulls off the end of. const int32_t inSize = 1024; RefPointer<Buffer> inBuf = Buffer::make(0, inSize); uint8_t* in = static_cast<uint8_t*>(inBuf->getBytes(0, inSize)); int32_t outSize = inSize; RefPointer<Buffer> outBuf = Buffer::make(0, outSize); uint8_t* out = static_cast<uint8_t*>(outBuf->getBytes(0, outSize)); // set the entire input buffer to null for now. memset(in, 0, inSize); // then set the first half of the buffer to be non-null. for(int32_t i = 0; i < inSize/2; i++) { in[i] = 0x01; out[i] = in[i]; } // should filter out all the null bytes at the end. outSize = f->filter(outBuf.value(), 0, inBuf.value(), 0, inSize, 0, 0, false); TS_ASSERT_EQUALS(outSize, inSize/2); for(int32_t i = 0; i < inSize/2; i++) { TS_ASSERT_EQUALS(in[i], out[i]); } }
void StreamCoderTest :: testGetSetExtraData() { int retval = 0; h->setupReading("testfile_h264_mp4a_tmcd.mov"); for(int i = 0; i < h->num_streams; i++) { if (h->coders[i]->getCodecType() != ICodec::CODEC_TYPE_VIDEO) continue; retval = h->coders[i]->open(); VS_TUT_ENSURE(0, retval >= 0); int32_t extraDataSize = h->coders[i]->getExtraDataSize(); VS_TUT_ENSURE(0, extraDataSize > 0); uint8_t* bytes; if (extraDataSize > 0) { RefPointer<IBuffer> buffer = IBuffer::make(0, extraDataSize); retval = h->coders[i]->getExtraData(buffer.value(), 0, extraDataSize); VS_TUT_ENSURE_EQUALS(0, retval, extraDataSize); bytes = (uint8_t*)buffer->getBytes(0, extraDataSize); for(int j = 0; j < extraDataSize; j++) { // VS_LOG_DEBUG("Byte %d: %hhd", j, bytes[j]); bytes[j] = 5; } retval = h->coders[i]->setExtraData(buffer.value(), 0, extraDataSize, false); VS_TUT_ENSURE_EQUALS(0, retval, extraDataSize); // reset the buffer buffer = IBuffer::make(0, extraDataSize+1); retval = h->coders[i]->getExtraData(buffer.value(), 0, extraDataSize); VS_TUT_ENSURE_EQUALS(0, retval, extraDataSize); bytes = (uint8_t*)buffer->getBytes(0, extraDataSize); for(int j = 0; j < extraDataSize; j++) { VS_TUT_ENSURE_EQUALS(0, bytes[j], 5); } bytes[extraDataSize] = 5; // test the path where we re-alloc buffers retval = h->coders[i]->setExtraData(buffer.value(), 0, extraDataSize+1, true); VS_TUT_ENSURE_EQUALS(0, retval, extraDataSize+1); // reset the buffer buffer = IBuffer::make(0, extraDataSize+1); retval = h->coders[i]->getExtraData(buffer.value(), 0, extraDataSize+1); VS_TUT_ENSURE_EQUALS(0, retval, extraDataSize+1); bytes = (uint8_t*)buffer->getBytes(0, extraDataSize+1); for(int j = 0; j < extraDataSize+1; j++) { VS_TUT_ENSURE_EQUALS(0, bytes[j], 5); } h->coders[i]->close(); } } }
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 MediaPictureResamplerTest::writePicture(const char* prefix, int32_t* frameNo, MediaPicture* picture, MediaPictureResampler* resampler, MediaPicture* resampled) { char filename[2048]; // resample the image from YUV to RGBA resampler->resample(resampled, picture); // write data as PGM file. snprintf(filename, sizeof(filename), "%s-%06d.png", prefix, *frameNo); // only write every n'th frame to save disk space RefPointer<Buffer> buf = resampled->getData(0); uint8_t* data = (uint8_t*)buf->getBytes(0, buf->getBufferSize()); if (!((*frameNo) % 30)) { lodepng_encode32_file(filename, data, resampled->getWidth(), resampled->getHeight()); } (*frameNo)++; // check the frame metadata RefPointer<KeyValueBag> md = picture->getMetaData(); if (md) { int n = md->getNumKeys(); for(int i = 0; i < n; i++) { const char* key = md->getKey(i); const char* val = md->getValue(key, KeyValueBag::KVB_NONE); fprintf(stderr, "%s : %s", key, val); } } }
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 MediaPacketTest::testWrapBuffer() { const int size = 512; RefPointer<Buffer> buf = Buffer::make(0, size); uint8_t* d = (uint8_t*)buf->getBytes(0, size); for(int i = 0; i < size; i++) d[i] = i % 16; packet = MediaPacket::make(buf.value()); RefPointer<Buffer> data = packet->getData(); TSM_ASSERT_DIFFERS("should be different Buffer objects since once in a packet, AV manages buffer", buf.value(), data.value()); TS_ASSERT_EQUALS(size, data->getBufferSize()); TS_ASSERT_EQUALS(size, packet->getSize()); uint8_t* raw = (uint8_t*) data->getBytes(0, size); for (int j = 0; j < size; j++) TS_ASSERT_EQUALS(raw[j], j % 16); }
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 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::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 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)); }