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 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 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 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); }
void MediaPictureResamplerTest::testRescale() { TestData::Fixture* fixture=mFixtures.getFixture("testfile_h264_mp4a_tmcd.mov"); 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); int32_t streamToDecode = 0; RefPointer<DemuxerStream> stream = source->getStream(streamToDecode); TS_ASSERT(stream); RefPointer<Decoder> decoder = stream->getDecoder(); TS_ASSERT(decoder); RefPointer<Codec> codec = decoder->getCodec(); TS_ASSERT(codec); TS_ASSERT_EQUALS(Codec::CODEC_ID_H264, codec->getID()); decoder->open(0, 0); TS_ASSERT_EQUALS(PixelFormat::PIX_FMT_YUV420P, decoder->getPixelFormat()); // now, let's start a decoding loop. RefPointer<MediaPacket> packet = MediaPacket::make(); RefPointer<MediaPicture> picture = MediaPicture::make( decoder->getWidth(), decoder->getHeight(), decoder->getPixelFormat()); int32_t rescaleW = decoder->getWidth()/4; int32_t rescaleH = (int32_t)(decoder->getHeight()*5.22); PixelFormat::Type rescaleFmt = PixelFormat::PIX_FMT_RGBA; RefPointer<MediaPicture> rescaled = MediaPicture::make( rescaleW, rescaleH, rescaleFmt); RefPointer<MediaPictureResampler> resampler = MediaPictureResampler::make(rescaled->getWidth(), rescaled->getHeight(), rescaled->getFormat(), picture->getWidth(), picture->getHeight(), picture->getFormat(), 0); resampler->open(); int32_t frameNo = 0; while(source->read(packet.value()) >= 0) { // got a packet; now we try to decode it. if (packet->getStreamIndex() == streamToDecode && packet->isComplete()) { int32_t bytesRead = 0; int32_t byteOffset=0; do { bytesRead = decoder->decodeVideo(picture.value(), packet.value(), byteOffset); if (picture->isComplete()) { writePicture("MediaPictureResamplerTest_testRescaleVideo", &frameNo, picture.value(), resampler.value(), rescaled.value()); } byteOffset += bytesRead; } while(byteOffset < packet->getSize()); // now, handle the case where bytesRead is 0; we need to flush any // cached packets do { decoder->decodeVideo(picture.value(), 0, 0); if (picture->isComplete()) { writePicture("MediaPictureResamplerTest_testRescaleVideo", &frameNo, picture.value(), resampler.value(), rescaled.value()); } } while (picture->isComplete()); } if ((int32_t)(frameNo/30) > 10) // 20 pictures should be enough to see if it's working. break; } source->close(); }
MediaPictureImpl* MediaPictureImpl::make(Buffer* buffer, int32_t width, int32_t height, PixelFormat::Type format) { if (width <= 0) { VS_THROW(HumbleInvalidArgument("width must be > 0")); } if (height <= 0) { VS_THROW(HumbleInvalidArgument("height must be > 0")); } if (format == PixelFormat::PIX_FMT_NONE) { VS_THROW(HumbleInvalidArgument("pixel format must be specifie")); } if (!buffer) { VS_THROW(HumbleInvalidArgument("must pass non null buffer")); } // let's figure out how big of a buffer we need int32_t bufSize = PixelFormat::getBufferSizeNeeded(width, height, format); if (bufSize < buffer->getBufferSize()) { VS_THROW( HumbleInvalidArgument( "passed in buffer too small to fit requested image parameters")); } RefPointer<MediaPictureImpl> retval = make(); AVFrame* frame = retval->mFrame; frame->width = width; frame->height = height; frame->format = format; // buffer is large enough; let's fill the data pointers uint8_t* data = (uint8_t*) buffer->getBytes(0, bufSize); int32_t imgSize = av_image_fill_arrays(frame->data, frame->linesize, data, (enum AVPixelFormat) frame->format, frame->width, frame->height, 1); if (imgSize != bufSize) { VS_ASSERT(imgSize == bufSize, "these should always be equal"); VS_THROW(HumbleRuntimeError("could not fill image with data")); } // now, set up the reference buffers frame->extended_data = frame->data; for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) { if (frame->data[i]) frame->buf[i] = AVBufferSupport::wrapBuffer(buffer, frame->data[i], frame->linesize[0]*frame->height+16); } // now fill in the AVBufferRefs where we pass of to FFmpeg care // of our buffer. Be kind FFmpeg. Be kind. RefPointer<PixelFormatDescriptor> desc = PixelFormat::getDescriptor((PixelFormat::Type)frame->format); if (!desc) { VS_THROW(HumbleRuntimeError("could not get format descriptor")); } if (desc->getFlag(PixelFormatDescriptor::PIX_FMT_FLAG_PAL) || desc->getFlag(PixelFormatDescriptor::PIX_FMT_FLAG_PSEUDOPAL)) { av_buffer_unref(&frame->buf[1]); frame->buf[1] = AVBufferSupport::wrapBuffer(Buffer::make(retval.value(), 1024)); if (!frame->buf[1]) { VS_THROW(HumbleRuntimeError("memory failure")); } frame->data[1] = frame->buf[1]->data; } int32_t n = retval->getNumDataPlanes(); (void) n; VS_LOG_TRACE("Created MediaPicture: %d x %d (%d). [%d, %d, %d, %d]", retval->getWidth(), retval->getHeight(), retval->getFormat(), n < 1 ? 0 : retval->getDataPlaneSize(0), n < 2 ? 0 : retval->getDataPlaneSize(1), n < 3 ? 0 : retval->getDataPlaneSize(2), n < 4 ? 0 : retval->getDataPlaneSize(3) ); // and we're done. return retval.get(); }
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); }
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(); }
/** * 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 } } }