blob: ffd99a8f0e9b0691e8253c75fbcfcc135c491888 [file] [log] [blame]
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#if __APPLE_CC__
#include <QuickTime/QuickTime.h>
#else
#include <ConditionalMacros.h>
#include <Endian.h>
#include <ImageCodec.h>
#endif
#define VPX_CODEC_DISABLE_COMPAT 1
#define HAVE_CONFIG_H "vpx_codecs_config.h"
#include "vpx/vpx_decoder.h"
#include "vpx/vpx_codec_impl_top.h"
#include "vpx/vpx_codec_impl_bottom.h"
#include "vpx/vp8dx.h"
#include "keystone_util.h"
#include "log.h"
#include "VP8CodecVersion.h"
#include "WebMExportVersions.h"
#include "Raw_debug.h"
// Data structures
typedef struct
{
ComponentInstance self;
ComponentInstance delegateComponent;
ComponentInstance target;
long width;
long height;
vpx_codec_ctx_t *ctx;
vpx_image_t *lastImg;
Handle wantedDestinationPixelTypes;
} VP8DecoderGlobalsRecord, *VP8DecoderGlobals;
typedef struct
{
long width;
long height;
size_t dataSize;
int storageIndex; // index in storedFrameArray of where this frame will go, if applicable
Boolean willBeStored; // if true, frame will go in storedFrameArray[storageIndex]; if false, immediateFrame.
Boolean decoded;
char pad[2];
} VP8DecoderRecord;
// Setup required for ComponentDispatchHelper.c
#define IMAGECODEC_BASENAME() VP8_Decoder_
#define IMAGECODEC_GLOBALS() VP8DecoderGlobals storage
#define CALLCOMPONENT_BASENAME() IMAGECODEC_BASENAME()
#define CALLCOMPONENT_GLOBALS() IMAGECODEC_GLOBALS()
#define QT_BASENAME() CALLCOMPONENT_BASENAME()
#define QT_GLOBALS() CALLCOMPONENT_GLOBALS()
#define COMPONENT_UPP_PREFIX() uppImageCodec
#define COMPONENT_DISPATCH_FILE "VP8DecoderDispatch.h"
#define COMPONENT_SELECT_PREFIX() kImageCodec
#define GET_DELEGATE_COMPONENT() (storage->delegateComponent)
#if __APPLE_CC__
#include <CoreServices/Components.k.h>
#include <QuickTime/ImageCodec.k.h>
#include <QuickTime/ImageCompression.k.h>
#include <QuickTime/ComponentDispatchHelper.c>
#else
#include <Components.k.h>
#include <ImageCodec.k.h>
#include <ImageCompression.k.h>
#include <ComponentDispatchHelper.c>
#endif
/* -- This Image Decompressor User the Base Image Decompressor Component --
The base image decompressor is an Apple-supplied component
that makes it easier for developers to create new decompressors.
The base image decompressor does most of the housekeeping and
interface functions required for a QuickTime decompressor component,
including scheduling for asynchronous decompression.
*/
// Component Open Request - Required
pascal ComponentResult VP8_Decoder_Open(VP8DecoderGlobals glob, ComponentInstance self)
{
ComponentResult err;
dbg_printf("[vp8d - %08lx] VP8_Decoder_Open\n", (UInt32) glob);
TouchActivityFile();
// Allocate memory for our globals, set them up and inform the component manager that we've done so
glob = calloc(sizeof(VP8DecoderGlobalsRecord), 1);
if (! glob)
{
err = memFullErr;
goto bail;
}
SetComponentInstanceStorage(self, (Handle)glob);
glob->self = self;
glob->target = self;
glob->ctx = NULL;
glob->lastImg = NULL;
// Open and target an instance of the base decompressor as we delegate
// most of our calls to the base decompressor instance
err = OpenADefaultComponent(decompressorComponentType, kBaseCodecType, &glob->delegateComponent);
if (err)
goto bail;
err = ComponentSetTarget(glob->delegateComponent, self);
bail:
dbg_printf("[vp8d - %08lx] open %x = %d\n", (UInt32) glob, err);
return err;
}
// Component Close Request - Required
pascal ComponentResult VP8_Decoder_Close(VP8DecoderGlobals glob, ComponentInstance self)
{
dbg_printf("[vp8d - %08lx] VP8_Decoder_Close %x \n", (UInt32) glob);
// Make sure to close the base component and dealocate our storage
if (glob)
{
int frameIndex;
dbg_printf("[vp8d - %08lx] VP8_Decoder_Close delegate \n", (UInt32)glob);
if (glob->delegateComponent)
{
CloseComponent(glob->delegateComponent);
}
dbg_printf("[vp8d - %08lx] VP8_Decoder_Close closed delegate\n", (UInt32)glob);
DisposeHandle(glob->wantedDestinationPixelTypes);
glob->wantedDestinationPixelTypes = NULL;
if (glob->ctx != NULL)
{
if (vpx_codec_destroy(glob->ctx))
dbg_printf("[vp8d - %08lx] Failed to destroy codec\n", (UInt32) glob);
free(glob->ctx);
}
free(glob);
}
dbg_printf("[vp8d - %08lx] close component exit\n", (UInt32) glob);
return noErr;
}
// Component Version Request - Required
pascal ComponentResult VP8_Decoder_Version(VP8DecoderGlobals glob)
{
#pragma unused(glob)
return kDecompressorVersion;
}
// Component Target Request
// Allows another component to "target" you i.e., you call another component whenever
// you would call yourself (as a result of your component being used by another component)
pascal ComponentResult VP8_Decoder_Target(VP8DecoderGlobals glob, ComponentInstance target)
{
glob->target = target;
return noErr;
}
#pragma mark-
// ImageCodecInitialize
// The first function call that your image decompressor component receives from the base image
// decompressor is always a call to ImageCodecInitialize. In response to this call, your image decompressor
// component returns an ImageSubCodecDecompressCapabilities structure that specifies its capabilities.
pascal ComponentResult VP8_Decoder_Initialize(VP8DecoderGlobals glob, ImageSubCodecDecompressCapabilities *cap)
{
#pragma unused(glob)
dbg_printf("[vp8d - %08lx] VP8_Decoder_Initialize\n", (UInt32) glob);
// Secifies the size of the ImageSubCodecDecompressRecord structure
// and say we can support asyncronous decompression
// With the help of the base image decompressor, any image decompressor
// that uses only interrupt-safe calls for decompression operations can
// support asynchronous decompression.
cap->decompressRecordSize = sizeof(VP8DecoderRecord);
cap->canAsync = true;
// These fields were added in QuickTime 7. Be safe.
if (cap->recordSize > offsetof(ImageSubCodecDecompressCapabilities, baseCodecShouldCallDecodeBandForAllFrames))
{
// Tell the base codec that we are "multi-buffer aware".
// This promises that we always draw using the ImageSubCodecDecompressRecord.baseAddr/rowBytes
// passed to our ImageCodecDrawBand function, and that we always overwrite every pixel in the buffer.
// It is important to set this in order to get optimal performance when playing through CoreVideo.
cap->subCodecIsMultiBufferAware = true;
// Tell the base codec that we support "out-of-order display times".
// This is the same as saying that we support B frames, or frame reordering.
// It is important to set this or the ICM will assume we do not support B frames,
// and attempts to schedule frames in a display order that's different from their
// decode order will fail.
cap->subCodecSupportsOutOfOrderDisplayTimes = true;
// Ask the base codec to call our ImageCodecDecodeBand function for every frame.
// If you do not set this, then your ImageCodecDrawBand function must
// manually ensure that the frame is decoded before drawing it.
cap->baseCodecShouldCallDecodeBandForAllFrames = true;
}
return noErr;
}
// ImageCodecPreflight
// The base image decompressor gets additional information about the capabilities of your image
// decompressor component by calling ImageCodecPreflight. The base image decompressor uses this
// information when responding to a call to the ImageCodecPredecompress function,
// which the ICM makes before decompressing an image. You are required only to provide values for
// the wantedDestinationPixelSize and wantedDestinationPixelTypes fields and can also modify other
// fields if necessary.
pascal ComponentResult VP8_Decoder_Preflight(VP8DecoderGlobals glob, CodecDecompressParams *decompressParams)
{
dbg_printf("[vp8d - %08lx] VP8_Decoder_Preflight\n", (UInt32) glob);
OSStatus err = noErr;
CodecCapabilities *capabilities = decompressParams->capabilities;
int widthRoundedUp, heightRoundedUp;
int frameIndex;
// Specify the minimum image band height supported by the component
// bandInc specifies a common factor of supported image band heights -
// if your component supports only image bands that are an even
// multiple of some number of pixels high report this common factor in bandInc
capabilities->bandMin = (**decompressParams->imageDescription).height;
capabilities->bandInc = capabilities->bandMin;
dbg_printf("[vp8d - %08lx] preflight bandMin %d bandInc %d\n", (UInt32) glob, capabilities->bandMin, capabilities->bandInc);
// Indicate the pixel depth the component can use with the specified image
capabilities->wantedPixelSize = 0; // set this to zero when using wantedDestinationPixelTypes
if (NULL == glob->wantedDestinationPixelTypes)
{
glob->wantedDestinationPixelTypes = NewHandleClear(2 * sizeof(OSType));
if (NULL == glob->wantedDestinationPixelTypes)
return memFullErr;
}
decompressParams->wantedDestinationPixelTypes = (OSType **)glob->wantedDestinationPixelTypes;
(*decompressParams->wantedDestinationPixelTypes)[0] = k422YpCbCr8PixelFormat; // also known as '2vuy'
(*decompressParams->wantedDestinationPixelTypes)[1] = 0;
// Specify the number of pixels the image must be extended in width and height if
// the component cannot accommodate the image at its given width and height.
// This codec must have output buffers that are rounded up to multiples of 16x16.
glob->width = (**decompressParams->imageDescription).width;
glob->height = (**decompressParams->imageDescription).height;
dbg_printf("[vp8d - %08lx] Preflight Width %d Height %d\n", (UInt32) glob, glob->width, glob->height);
widthRoundedUp = glob->width;
heightRoundedUp = glob->height;
if (0 != (widthRoundedUp & 15))
widthRoundedUp = (widthRoundedUp + 15) & ~15;
if (0 != (heightRoundedUp & 15))
heightRoundedUp = (heightRoundedUp + 15) & ~15;
capabilities->extendWidth = widthRoundedUp - glob->width;
capabilities->extendHeight = heightRoundedUp - glob->height;
dbg_printf("[vp8d - %08lx] Preflight Extend Width %d Extend Height %d\n", (UInt32) glob,
capabilities->extendWidth, capabilities->extendHeight);
// Init Codec
if (glob->ctx == NULL)
glob->ctx = calloc(1, sizeof(vpx_codec_ctx_t));
if (vpx_codec_dec_init(glob->ctx, &vpx_codec_vp8_dx_algo, NULL, 0))
{
dbg_printf("[vp8d - %08lx] vpx_QT_Dx: Failed to initialize decoder: %s\n", (UInt32) glob, vpx_codec_error(glob->ctx));
return paramErr;
}
bail:
return err;
}
// ImageCodecBeginBand
// The ImageCodecBeginBand function allows your image decompressor component to save information about
// a band before decompressing it. This function is never called at interrupt time. The base image decompressor
// preserves any changes your component makes to any of the fields in the ImageSubCodecDecompressRecord
// or CodecDecompressParams structures. If your component supports asynchronous scheduled decompression, it
// may receive more than one ImageCodecBeginBand call before receiving an ImageCodecDrawBand call.
pascal ComponentResult VP8_Decoder_BeginBand(VP8DecoderGlobals glob, CodecDecompressParams *p, ImageSubCodecDecompressRecord *drp, long flags)
{
#pragma unused(glob)
dbg_printf("[vp8d - %08lx] VP8_Decoder_BeginBand\n", (UInt32) glob);
OSStatus err = noErr;
vpx_codec_err_t vpx_err;
vpx_codec_stream_info_t stream_info;
VP8DecoderRecord *myDrp = (VP8DecoderRecord *)drp->userDecompressRecord;
Boolean keyFrame, differenceFrame, droppableFrame, altRefFrame;
int storageIndex;
myDrp->width = (**p->imageDescription).width;
myDrp->height = (**p->imageDescription).height;
dbg_printf("[vp8d - %08lx] VP8_Decoder_BeginBand resolution %dx%d\n", (UInt32) glob, myDrp->width, myDrp->height);
// Unfortunately, the image decompressor API can not quite guarantee to tell the decompressor
// how much data is available, because the deprecated API DecompressSequenceFrame does not take
// a dataSize argument. (That's why you should call DecompressSequenceFrameS instead.)
// Here's the best effort we can make: if there's a data-loading proc, use the dataSize from the
// image description; otherwise, use the bufferSize.
if (drp->dataProcRecord.dataProc)
myDrp->dataSize = (**p->imageDescription).dataSize;
else
myDrp->dataSize = p->bufferSize;
dbg_printf("[vp8d - %08lx] VP8_Decoder_BeginBand: datasize %d\n", (UInt32) glob, myDrp->dataSize);
// In some cases, a frame will be decoded and ready for display, but the display will be cancelled.
// QuickTime's video media handler will remember that the frame has already been decoded,
// and if appropriate, will schedule that frame for display without redecoding by using the
// icmFrameAlreadyDecoded flag.
// In that case, we should simply retrieve the frame from whichever buffer we put it in.
myDrp->decoded = p->frameTime ? (0 != (p->frameTime->flags & icmFrameAlreadyDecoded)) : false;
dbg_printf("[vp8d - %08lx] VP8_Decoder_BeginBand: already decoded = %d\n", (UInt32) glob, myDrp->decoded);
/*err = NaiveDecoder_DecodeFrameHeader( (const UInt8 *)drp->codecData, &keyFrame, &differenceFrame, &droppableFrame, &storageIndex );
if( err )
goto bail;*/
stream_info.sz = sizeof(stream_info);
stream_info.w = glob->width;
stream_info.h = glob->height;
//TODO based on previous comments the data size might not be garenteed
vpx_err = vpx_codec_peek_stream_info(&vpx_codec_vp8_dx_algo, (unsigned char *)drp->codecData, myDrp->dataSize, &stream_info);
if (vpx_err)
{
dbg_printf("[vp8d - %08lx] VP8_Decoder_BeginBand: ignoring error: %s\n", (UInt32) glob, vpx_codec_err_to_string(vpx_err));
}
char packetHeader = ((unsigned char *)drp->codecData)[0];
altRefFrame = (packetHeader & 0x10) == 0;
dbg_printf("[vp8d - %08lx] AltrefFrame = %d packet (%02x)\n", (UInt32) glob,altRefFrame, packetHeader);
keyFrame = stream_info.is_kf;
storageIndex = 0;
droppableFrame = 0;
// Remember which internal buffer we're going to put this frame in when we decode it.
myDrp->storageIndex = storageIndex;
myDrp->willBeStored = ! droppableFrame;
// Classify the frame so that the base codec can do the right thing.
// It is very important to do this so that the base codec will know
// which frames it can drop if we're in danger of falling behind.
if (keyFrame)
{
// Key frames are resynchronization points in the sequence of frames.
// No frames following a key frame can depend on information from frames before a key frame.
// Note that the I frame at the start of an open GOP in MPEG-1/2 frame patterns is *not* a key frame.
drp->frameType = kCodecFrameTypeKey;
}
else if (droppableFrame)
{
// Droppable frames are not stored; no later frames depend on information in them.
// We decode them into the immediateFrame buffer, which is available for reuse
// as soon as the frame is drawn.
drp->frameType = kCodecFrameTypeDroppableDifference;
}
else if (altRefFrame)
{
// Alt Ref frames should not be drawn.
drp->frameType = kCodecFrameTypeUnknown;
}
else
{
// Other frames are difference frames.
drp->frameType = kCodecFrameTypeDifference;
}
dbg_printf("[vp8d - %08lx] VP8_Decoder_BeginBand: frame number %d key frame %d\n", (UInt32) glob, p->frameNumber, keyFrame);
bail:
return err;
}
pascal ComponentResult VP8_Decoder_DecodeBand(VP8DecoderGlobals glob, ImageSubCodecDecompressRecord *drp, unsigned long flags)
{
OSErr err = noErr;
dbg_printf("[vp8d - %08lx] VP8_Decoder_DecodeBand\n", (UInt32) glob);
VP8DecoderRecord *myDrp = (VP8DecoderRecord *)drp->userDecompressRecord;
ICMDataProcRecordPtr dataProc = drp->dataProcRecord.dataProc ? &drp->dataProcRecord : NULL;
struct InternalPixelBuffer *destBuffer;
{
/* Poke the DataProc instance, if one exists. */
ICMDataProcRecordPtr dataProc = drp->dataProcRecord.dataProc ? &drp->dataProcRecord : NULL;
if (dataProc)
{
long bytesNeeded = myDrp->dataSize;
dbg_printf("[vp8d - %08lx] VP8_Decoder_DecodeBand: poking dataProc for %ld bytes\n", (UInt32) glob, bytesNeeded);
dataProc->dataProc((Ptr *)&drp->codecData, bytesNeeded, dataProc->dataRefCon);
}
}
dbg_printf("[vp8d - %08lx] call vpx_codec_decode with %d bytes of data\n", (UInt32) glob, myDrp->dataSize);
//writeRaw("/var/tmp/vp8dump.vp8", myDrp->dataSize, (unsigned char *)drp->codecData);
if (vpx_codec_decode(glob->ctx, (unsigned char *)drp->codecData, myDrp->dataSize, NULL, 0))
{
dbg_printf("[vp8d - %08lx] vpx_QT_Dx: Failed to decode frame: %s\n", (UInt32) glob, vpx_codec_error(glob->ctx));
return paramErr;
}
dbg_printf("[vp8d - %08lx] successfully decoded frame size %d\n", (UInt32) glob, myDrp->dataSize);
myDrp->decoded = true;
bail:
return err;
}
// ImageCodecDrawBand
// The base image decompressor calls your image decompressor component's ImageCodecDrawBand function
// to decompress a band or frame. Your component must implement this function. If the ImageSubCodecDecompressRecord
// structure specifies a progress function or data-loading function, the base image decompressor will never call ImageCodecDrawBand
// at interrupt time. If the ImageSubCodecDecompressRecord structure specifies a progress function, the base image decompressor
// handles codecProgressOpen and codecProgressClose calls, and your image decompressor component must not implement these functions.
// If not, the base image decompressor may call the ImageCodecDrawBand function at interrupt time.
// When the base image decompressor calls your ImageCodecDrawBand function, your component must perform the decompression specified
// by the fields of the ImageSubCodecDecompressRecord structure. The structure includes any changes your component made to it
// when performing the ImageCodecBeginBand function. If your component supports asynchronous scheduled decompression,
// it may receive more than one ImageCodecBeginBand call before receiving an ImageCodecDrawBand call.
pascal ComponentResult VP8_Decoder_DrawBand(VP8DecoderGlobals glob, ImageSubCodecDecompressRecord *drp)
{
OSErr err = noErr;
VP8DecoderRecord *myDrp = (VP8DecoderRecord *)drp->userDecompressRecord;
vpx_codec_iter_t iter = NULL;
vpx_image_t *img;
dbg_printf("[vp8d - %08lx] VP8_Decoder_DrawBand\n", (UInt32) glob);
if (! myDrp->decoded)
{
// If you don't set the baseCodecShouldCallDecodeBandForAllFrames flag, or if you
// need QuickTime 6 compatibility, you should double-check that the frame has been decoded here,
// and decode if necessary:
err = VP8_Decoder_DecodeBand(glob, drp, 0);
if (err) goto bail;
}
//I am keeping an image in the case of altref frames
// when an altref frame shows up, just redraw the previous frame
if (drp->frameType != kCodecFrameTypeUnknown)
{
img = vpx_codec_get_frame(glob->ctx, &iter);
glob->lastImg = img;
}
else
{
img = glob->lastImg;
}
if (img)
{
dbg_printf("[vp8d - %08lx] vpx_QT_Dx_DrawBand: got image %dx%d!\n", (UInt32) glob, myDrp->width, myDrp->height);
CopyPlanarYV12ToChunkyYUV422(myDrp->width, myDrp->height,
img->planes[VPX_PLANE_Y], img->stride[VPX_PLANE_Y],
img->planes[VPX_PLANE_U], img->stride[VPX_PLANE_U],
img->planes[VPX_PLANE_V], img->stride[VPX_PLANE_V],
drp->baseAddr, drp->rowBytes);
}
dbg_printf("[vp8d - %08lx] leaving vp8_decoder_drawband %d\n", (UInt32) glob, err);
bail:
return err;
}
// ImageCodecEndBand
// The ImageCodecEndBand function notifies your image decompressor component that decompression of a band has finished or
// that it was terminated by the Image Compression Manager. Your image decompressor component is not required to implement
// the ImageCodecEndBand function. The base image decompressor may call the ImageCodecEndBand function at interrupt time.
// After your image decompressor component handles an ImageCodecEndBand call, it can perform any tasks that are required
// when decompression is finished, such as disposing of data structures that are no longer needed. Because this function
// can be called at interrupt time, your component cannot use this function to dispose of data structures; this
// must occur after handling the function. The value of the result parameter should be set to noErr if the band or frame was
// drawn successfully. If it is any other value, the band or frame was not drawn.
pascal ComponentResult VP8_Decoder_EndBand(VP8DecoderGlobals glob, ImageSubCodecDecompressRecord *drp, OSErr result, long flags)
{
#pragma unused(glob, drp,result, flags)
return noErr;
}
// ImageCodecQueueStarting
// If your component supports asynchronous scheduled decompression, the base image decompressor calls your image decompressor component's
// ImageCodecQueueStarting function before decompressing the frames in the queue. Your component is not required to implement this function.
// It can implement the function if it needs to perform any tasks at this time, such as locking data structures.
// The base image decompressor never calls the ImageCodecQueueStarting function at interrupt time.
pascal ComponentResult VP8_Decoder_QueueStarting(VP8DecoderGlobals glob)
{
#pragma unused(glob)
return noErr;
}
// ImageCodecQueueStopping
// If your image decompressor component supports asynchronous scheduled decompression, the ImageCodecQueueStopping function notifies
// your component that the frames in the queue have been decompressed. Your component is not required to implement this function.
// After your image decompressor component handles an ImageCodecQueueStopping call, it can perform any tasks that are required when decompression
// of the frames is finished, such as disposing of data structures that are no longer needed.
// The base image decompressor never calls the ImageCodecQueueStopping function at interrupt time.
pascal ComponentResult VP8_Decoder_QueueStopping(VP8DecoderGlobals glob)
{
#pragma unused(glob)
return noErr;
}
// ImageCodecGetCompressedImageSize
// Your component receives the ImageCodecGetCompressedImageSize request whenever an application calls the ICM's GetCompressedImageSize function.
// You can use the ImageCodecGetCompressedImageSize function when you are extracting a single image from a sequence; therefore, you don't have an
// image description structure and don't know the exact size of one frame. In this case, the Image Compression Manager calls the component to determine
// the size of the data. Your component should return a long integer indicating the number of bytes of data in the compressed image. You may want to store
// the image size somewhere in the image description structure, so that you can respond to this request quickly. Only decompressors receive this request.
pascal ComponentResult VP8_Decoder_GetCompressedImageSize(VP8DecoderGlobals glob, ImageDescriptionHandle desc, Ptr data, long dataSize, ICMDataProcRecordPtr dataProc, long *size)
{
#pragma unused(glob,desc,dataSize,dataProc)
if (size == NULL)
return paramErr;
//••
return unimpErr;
}
// ImageCodecGetCodecInfo
// Your component receives the ImageCodecGetCodecInfo request whenever an application calls the Image Compression Manager's GetCodecInfo function.
// Your component should return a formatted compressor information structure defining its capabilities.
// Both compressors and decompressors may receive this request.
pascal ComponentResult VP8_Decoder_GetCodecInfo(VP8DecoderGlobals glob, CodecInfo *info)
{
OSErr err = noErr;
if (info == NULL)
{
err = paramErr;
}
else
{
CodecInfo **tempCodecInfo;
err = GetComponentResource((Component)glob->self, codecInfoResourceType, 255, (Handle *)&tempCodecInfo);
if (err == noErr)
{
*info = **tempCodecInfo;
DisposeHandle((Handle)tempCodecInfo);
}
//TODO see if this line is needed
/*else if(err == resNotFound) {
memcpy(info->typeName, "\3VP8", 4);
info->version=0;
info->revisionLevel=0;
info->vendor='vpx ';
info->decompressFlags=0x10000420;
info->compressFlags=0;
info->formatFlags=codecInfoDepth24;
info->compressionAccuracy = info->decompressionAccuracy = 128;
info->compressionSpeed = info->decompressionSpeed = 200;
info->compressionLevel=128;
info->resvd=0;
info->minimumHeight = info->minimumWidth= 1;
info->decompressPipelineLatency = info->compressPipelineLatency = 0;
info->privateData=0;
err=noErr;
}*/
}
return err;
}
#pragma mark-
// When building the *Application Version Only* make our component available for use by applications (or other clients).
// Once the Component Manager has registered a component, applications can find and open the component using standard
// Component Manager routines.
#if !STAND_ALONE && !TARGET_OS_WIN32
void RegisterVP8Decompressor(void);
void RegisterVP8Decompressor(void)
{
ComponentDescription td;
td.componentType = decompressorComponentType;
td.componentSubType = FOUR_CHAR_CODE('VP80');
td.componentManufacturer = kGoogManufacturer;
td.componentFlags = cmpThreadSafe;
td.componentFlagsMask = 0;
RegisterComponent(&td, (ComponentRoutineUPP)VP8_Decoder_ComponentDispatch, 0, NULL, NULL, NULL);
}
#endif // !STAND_ALONE && TARGET_OS_WIN32