示例#1
0
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_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);
}
示例#2
0
void
EncoderTest::testRegression36Internal (const Codec::ID codecId,
                                       const int32_t numSamples,
                                       const int32_t sampleRate,
                                       const int32_t channels,
                                       const AudioChannel::Layout channelLayout,
                                       const AudioFormat::Type audioFormat,
                                       const int64_t bitRate,
                                       const char* testOutputName)
{
  VS_LOG_DEBUG("Output filename: %s", testOutputName);
  RefPointer<Codec> codec = Codec::findEncodingCodec (codecId);
  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) (bitRate));
  RefPointer<Rational> tb = Rational::make (1, sampleRate);
  encoder->setTimeBase (tb.value ());
  // create an output muxer
  RefPointer<Muxer> muxer = Muxer::make (testOutputName, 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=220:beep_factor=4:duration=11[out]");
  fsink->setFrameSize (numSamples);
  // 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 numCompletePackets = 0;
  RefPointer<MediaPacket> packet;
  // Get one audio packet that is larger than the frame-size.
  fsink->getAudio (audio.value ());
  TS_ASSERT(audio->isComplete ());
  TS_ASSERT_EQUALS(audio->getNumSamples (), sampleRate);
  audio->setTimeStamp (0);
  // let's encode
  packet = MediaPacket::make ();
  encoder->encodeAudio (packet.value (), audio.value ());
  if (packet->isComplete ())
  {
    muxer->write (packet.value (), false);
  }
  // now flush the encoder
  do
  {
    packet = MediaPacket::make ();
    encoder->encodeAudio (packet.value (), 0);
    if (packet->isComplete ())
    {
      muxer->write (packet.value (), false);
      ++numCompletePackets;
    }
  }
  while (packet->isComplete ());
  muxer->close ();
  if (!(codec->getCapabilities() & Codec::CAP_VARIABLE_FRAME_SIZE)) {
    const int32_t numExpectedPackets = audio->getNumSamples()
        / encoder->getFrameSize();

    VS_LOG_DEBUG("%ld vs %ld; framesize: %ld", numCompletePackets, numExpectedPackets, encoder->getFrameSize());
    TS_ASSERT(numCompletePackets > 10);
  }
}
示例#3
0
void
StreamCoderTest :: disabled_testDecodingAndEncodingNellymoserAudio()
{
  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_8_output.flv", "flv", "nellymoser", "flv");

  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_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);
}
示例#4
0
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();
}
示例#5
0
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);
}