Example #1
0
OSStatus MovieWriter::Obj::encodedFrameOutputCallback( void *refCon, 
                   ICMCompressionSessionRef session, 
                   OSStatus err,
                   ICMEncodedFrameRef encodedFrame,
                   void *reserved )
{
	MovieWriter::Obj *obj = reinterpret_cast<MovieWriter::Obj*>( refCon );

	ImageDescriptionHandle imageDescription = NULL;
	err = ICMCompressionSessionGetImageDescription( session, &imageDescription );
	if( ! err ) {
		Fixed gammaLevel = qtime::floatToFixed( obj->mFormat.mGamma );
		err = ICMImageDescriptionSetProperty(imageDescription,
						kQTPropertyClass_ImageDescription,
						kICMImageDescriptionPropertyID_GammaLevel,
						sizeof(gammaLevel), &gammaLevel);
		if( err != 0 )
			throw;
	}
	else
		throw;

	OSStatus result = ::AddMediaSampleFromEncodedFrame( obj->mMedia, encodedFrame, NULL );
	return result;
}
// Prepare to compress frames.
// Compressor should record session and sessionOptions for use in later calls.
// Compressor may modify imageDescription at this point.
// Compressor may create and return pixel buffer options.
ComponentResult
VP8_Encoder_PrepareToCompressFrames(
                                    VP8EncoderGlobals glob,
                                    ICMCompressorSessionRef session,
                                    ICMCompressionSessionOptionsRef sessionOptions,
                                    ImageDescriptionHandle imageDescription,
                                    void *reserved,
                                    CFDictionaryRef *compressorPixelBufferAttributesOut)
{
  dbg_printf("[vp8e] Prepare to Compress Frames\n", (UInt32)glob);
  ComponentResult err = noErr;
  CFMutableDictionaryRef compressorPixelBufferAttributes = NULL;
  //This format later needs to be converted
  OSType pixelFormatList[] = { k422YpCbCr8PixelFormat }; // also known as '2vuy'

  Fixed gammaLevel;
  int frameIndex;
  SInt32 widthRoundedUp, heightRoundedUp;

  // Record the compressor session for later calls to the ICM.
  // Note: this is NOT a CF type and should NOT be CFRetained or CFReleased.
  glob->session = session;

  // Retain the session options for later use.
  ICMCompressionSessionOptionsRelease(glob->sessionOptions);
  glob->sessionOptions = sessionOptions;
  ICMCompressionSessionOptionsRetain(glob->sessionOptions);

  // Modify imageDescription here if needed.
  // We'll set the image description gamma level to say "2.2".
  gammaLevel = kQTCCIR601VideoGammaLevel;
  err = ICMImageDescriptionSetProperty(imageDescription,
                                       kQTPropertyClass_ImageDescription,
                                       kICMImageDescriptionPropertyID_GammaLevel,
                                       sizeof(gammaLevel),
                                       &gammaLevel);

  if (err)
    goto bail;

  // Record the dimensions from the image description.
  glob->width = (*imageDescription)->width;
  glob->height = (*imageDescription)->height;
  dbg_printf("[vp8e - %08lx] Prepare to compress frame width %d height %d\n", (UInt32)glob, glob->width, glob->height);

  if (glob->width < 16 || glob->width % 2 || glob->height < 16 || glob->height % 2)
    dbg_printf("[vp8e - %08lx] Warning :: Invalid resolution: %ldx%ld", (UInt32)glob, glob->width, glob->height);

  if (glob->raw == NULL)
    glob->raw = calloc(1, sizeof(vpx_image_t));

  //Right now I'm only using YV12, this is great for webm, as I control the spit component
  if (!vpx_img_alloc(glob->raw, IMG_FMT_YV12, glob->width, glob->height, 1))
  {
    dbg_printf("[vp8e - %08lx] Error: Failed to allocate image %dx%d", (UInt32)glob, glob->width, glob->height);
    err = paramErr;
    goto bail;
  }

  glob->maxEncodedDataSize = glob->width * glob->height * 2;
  dbg_printf("[vp8e - %08lx] currently allocating %d bytes as my max encoded size\n", (UInt32)glob, glob->maxEncodedDataSize);

  // Create a pixel buffer attributes dictionary.
  err = createPixelBufferAttributesDictionary(glob->width, glob->height,
                                              pixelFormatList, sizeof(pixelFormatList) / sizeof(OSType),
                                              &compressorPixelBufferAttributes);

  if (err)
    goto bail;

  *compressorPixelBufferAttributesOut = compressorPixelBufferAttributes;
  compressorPixelBufferAttributes = NULL;

  /* Populate encoder configuration */
  glob->res = vpx_codec_enc_config_default((&vpx_codec_vp8_cx_algo), &glob->cfg, 0);

  if (glob->res)
  {
    dbg_printf("[vp8e - %08lx] Failed to get config: %s\n", (UInt32)glob, vpx_codec_err_to_string(glob->res));
    err = paramErr; //this may be something different ....
    goto bail;
  }

  glob->cfg.g_w = glob->width;
  glob->cfg.g_h = glob->height;
  dbg_printf("[vp8e - %08lx] resolution %dx%d\n", (UInt32)glob,
             glob->cfg.g_w, glob->cfg.g_h);

bail:

  if (err)
    dbg_printf("[vp8e - %08lx] Error %d\n", (UInt32)glob, err);

  if (compressorPixelBufferAttributes) CFRelease(compressorPixelBufferAttributes);

  return err;
}