예제 #1
0
void
MediaAudioTest::testCreationFromBufferPlanar() {
  const int32_t numSamples = 155; // I choose an odd number because HV will align up to 32
  const int32_t sampleRate = 22050;
  const int32_t channels = 15; // choose a large # of channels to make sure we expand the Frame
  const AudioChannel::Layout layout = AudioChannel::CH_LAYOUT_UNKNOWN;
  const AudioFormat::Type format = AudioFormat::SAMPLE_FMT_DBLP;

  int32_t bufSize = AudioFormat::getBufferSizeNeeded(numSamples, channels,
      format);
  // test that there is rounding up
  int32_t minSize = AudioFormat::getBytesPerSample(format) * numSamples
      * channels;
  TS_ASSERT_LESS_THAN(minSize, bufSize);

  RefPointer<Buffer> src = Buffer::make(0, bufSize);
  double* srcData = (double*) src->getBytes(0, bufSize);

  // now, let's go nuts!
  for (size_t i = 0; i < bufSize / sizeof(double); i++) {
    srcData[i] = i;
  }

  RefPointer<MediaAudio> audio;

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(MediaAudio::make(0, numSamples, sampleRate, channels, layout,
        format), HumbleInvalidArgument);
  }
  audio = MediaAudio::make(src.value(), numSamples, sampleRate, channels,
      layout, format);
  TS_ASSERT(audio);

  TS_ASSERT_EQUALS(channels, audio->getNumDataPlanes());

  // sigh; time to test each plane.
  for (int i = 0; i < channels; i++) {
    RefPointer<Buffer> dst = audio->getData(i);
    TS_ASSERT(dst);
    double* dstData = (double*) dst->getBytes(0, dst->getBufferSize());

    // the values should be monotonically increasing given how we set them.
    double last = dstData[0];
    for (size_t j = 1; j < dst->getBufferSize() / sizeof(double); j++) {
      TS_ASSERT_DELTA(last + 1, dstData[j], 0.001);
      last = dstData[j];
    }
  }
}
예제 #2
0
void
MediaAudioTest::testCreationFromBufferPacked() {
  const int32_t numSamples = 155; // I choose an odd number because HV will align up to 32
  const int32_t sampleRate = 22050;
  const int32_t channels = 8;
  const AudioChannel::Layout layout = AudioChannel::CH_LAYOUT_7POINT1;
  const AudioFormat::Type format = AudioFormat::SAMPLE_FMT_DBL;

  int32_t bufSize = AudioFormat::getBufferSizeNeeded(numSamples, channels,
      format);
  RefPointer<Buffer> src = Buffer::make(0, bufSize);
  double* srcData = (double*) src->getBytes(0, bufSize);

  // now, let's go nuts!
  for (size_t i = 0; i < bufSize / sizeof(double); i++) {
    srcData[i] = i;
  }

  RefPointer<MediaAudio> audio;

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(MediaAudio::make(0, numSamples, sampleRate, channels, layout,
        format), HumbleInvalidArgument);
  }
  audio = MediaAudio::make(src.value(), numSamples, sampleRate, channels,
      layout, format);
  TS_ASSERT(audio);

  TS_ASSERT_EQUALS(1, audio->getNumDataPlanes());
  RefPointer<Buffer> dst = audio->getData(0);
  TS_ASSERT(dst);
  double* dstData = (double*) dst->getBytes(0, dst->getBufferSize());

  // the test in packed data is simple -- the buffers should be equal!
  TS_ASSERT_EQUALS(src->getBufferSize(), dst->getBufferSize());
  TS_ASSERT_EQUALS(srcData, dstData);

}
예제 #3
0
void
MediaAudioTest::testCreation() {
  const int32_t numSamples = 1024;
  const int32_t sampleRate = 22050;
  const int32_t channels = 8;
  const AudioChannel::Layout layout = AudioChannel::CH_LAYOUT_7POINT1;
  const AudioFormat::Type format = AudioFormat::SAMPLE_FMT_S16P;

  // now let's test invalid methods.
  RefPointer<MediaAudio> audio;

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(MediaAudio::make(-1, sampleRate, channels, layout, format),
        HumbleInvalidArgument);
  }

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(MediaAudio::make(numSamples, -1, channels, layout, format),
        HumbleInvalidArgument);
  }

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(MediaAudio::make(numSamples, sampleRate, -1, layout, format),
        HumbleInvalidArgument);
  }

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(MediaAudio::make(numSamples, sampleRate, channels + 1, layout,
        format), HumbleInvalidArgument);
  }

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(MediaAudio::make(numSamples, sampleRate, channels, layout,
        AudioFormat::SAMPLE_FMT_NONE), HumbleInvalidArgument);
  }

  // And this should be valid
  audio = MediaAudio::make(numSamples, sampleRate, channels + 1,
      AudioChannel::CH_LAYOUT_UNKNOWN, format);
  TS_ASSERT(audio);

  audio = MediaAudio::make(numSamples, sampleRate, channels, layout, format);
  TS_ASSERT(audio);

  // now let's try getting the data
  RefPointer<Buffer> buf;

  TS_ASSERT_EQUALS(numSamples, audio->getMaxNumSamples());
  TS_ASSERT_EQUALS(numSamples, audio->getNumSamples());
  TS_ASSERT(!audio->isComplete());
  TS_ASSERT_EQUALS(channels, audio->getChannels());
  TS_ASSERT_EQUALS(channels, audio->getNumDataPlanes());
  TS_ASSERT_EQUALS(layout, audio->getChannelLayout());
  TS_ASSERT_EQUALS(sampleRate, audio->getSampleRate());
  TS_ASSERT_EQUALS(format, audio->getFormat());

  {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);

    TS_ASSERT_THROWS(
        audio->setNumSamples(audio->getMaxNumSamples()+1),
        HumbleInvalidArgument);
    TS_ASSERT_THROWS(audio->setNumSamples(-1), HumbleInvalidArgument);
    TS_ASSERT_THROWS(audio->setNumSamples(0), HumbleInvalidArgument);
  }

  audio->setNumSamples(1);
  TS_ASSERT_EQUALS(1, audio->getNumSamples());
  audio->setComplete(true);
  TS_ASSERT(audio->isComplete());

  for (int i = 0; i < channels; i++) {
    buf = audio->getData(i);
    TS_ASSERT(buf);
    TS_ASSERT_EQUALS(audio->getDataPlaneSize(i),
        audio->getNumSamples()*AudioFormat::getBytesPerSample(audio->getFormat())*(audio->isPlanar()?1:audio->getChannels()));
  }
  // now let's try packed audio
  audio = MediaAudio::make(numSamples, sampleRate, channels, layout,
      AudioFormat::getPackedSampleFormat(format));
  TS_ASSERT(audio);
  TS_ASSERT_EQUALS(AudioFormat::getPackedSampleFormat(format),
      audio->getFormat());
  TS_ASSERT_EQUALS(channels, audio->getChannels());
  TS_ASSERT_EQUALS(1, audio->getNumDataPlanes());

  buf = audio->getData(0);
  TS_ASSERT(buf);
  for (int i = 1; i < channels; i++) {
    LoggerStack stack;
    stack.setGlobalLevel(Logger::LEVEL_ERROR, false);
    TS_ASSERT_THROWS(audio->getData(i), HumbleInvalidArgument);
  }

}
예제 #4
0
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);
      }
    }
  }

}
예제 #5
0
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();
}