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();
}
Пример #2
0
/**
 * 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();
}