📄 main.c
字号:
imageParamP->width = 0; // Don't care
imageParamP->height = 0; // Don't care
imageParamP->rowByte = 0; // Don't care
imageParamP->endianess = 0; // Don't care
// Create the MPEG4 Decoding session
//err = CodecMgrCreateSession(gMPEG4Info.codecMgrLibRefNum, palmCodecVideoMPEG4, NULL, gMPEG4Info.imageFormat, imageParamP, &gMPEG4Info.session);
err = CodecMgrCreateSessionByID(gMPEG4Info.codecMgrLibRefNum, palmCodecVideoMPEG4, NULL, gMPEG4Info.imageFormat, imageParamP, 'mp4d', 0, &gMPEG4Info.session);
if(err) {
FrmCustomAlert(ErrorAlert, "Unable to create session", NULL, NULL);
goto Done;
}
// Set the planar image
planarImage.width = gMPEG4Info.width;
planarImage.height = gMPEG4Info.height;
planarImage.planeCount = 3;
switch(gMPEG4Info.imageFormat)
{
case palmCodecImageYCbCr420Planar:
planarImage.planeP[0] = Allocate( (3 * planarImage.width * planarImage.height) / 2);
planarImage.planeP[1] = (UInt8*)planarImage.planeP[0] + planarImage.width * planarImage.height;
planarImage.planeP[2] = (UInt8*)planarImage.planeP[1] + (planarImage.width * planarImage.height / 4);
planarImage.planeWidth[0] = planarImage.width;
planarImage.planeWidth[1] = planarImage.width / 2;
planarImage.planeWidth[2] = planarImage.width / 2;
break;
default:
FrmCustomAlert(ErrorAlert, "Bad image format", NULL, NULL);
goto Done;
break;
}
if(!planarImage.planeP[0]) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
// Use a byte-swapped copy for the CPM
swapImageP->width = Swap32(planarImage.width);
swapImageP->height = Swap32(planarImage.height);
swapImageP->planeCount = Swap32(planarImage.planeCount);
swapImageP->planeP[0] = (void*)Swap32(planarImage.planeP[0]);
swapImageP->planeP[1] = (void*)Swap32(planarImage.planeP[1]);
swapImageP->planeP[2] = (void*)Swap32(planarImage.planeP[2]);
swapImageP->planeWidth[0] = Swap32(planarImage.planeWidth[0]);
swapImageP->planeWidth[1] = Swap32(planarImage.planeWidth[1]);
swapImageP->planeWidth[2] = Swap32(planarImage.planeWidth[2]);
// Running from file
if(gMPEG4Info.loadFileInMemory)
{
// Get the file size
err = VFSFileSize(gMPEG4Info.inputFileRef, &inputBufferSize);
if(err || !inputBufferSize)
goto Done;
currentBufferP = inputBufferP = (UInt8*)Allocate(inputBufferSize);
if(!inputBufferP) {
// Try with FtrPtr
err = FtrPtrNew(appFileCreator, 0, inputBufferSize, (void*)&inputBufferP);
if(err) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
currentBufferP = inputBufferP;
useFtr = true;
}
// Load the file
if(!PrvLoadFileInMemory(gMPEG4Info.inputFileRef, inputBufferSize, inputBufferP, useFtr))
goto Done;
}
else
{
// Allocate buffer for VFS
inputBufferP = (UInt8*)Allocate(DATA_BUFFER_SIZE);
// Load first input buffer
currentBufferP = inputBufferP;
err = VFSFileRead(gMPEG4Info.inputFileRef, DATA_BUFFER_SIZE, inputBufferP, &inputBufferSize);
if(err)
goto Done;
}
// Get the bounds for the Go button
FrmGetObjectBounds(FrmGetActiveForm(), FrmGetObjectIndex(FrmGetActiveForm(),MainGoButton), &goButtonBounds);
// LCD Overlay
if( gUseOverlay)
{
LcdOverlayLibSettingType overlaySetting;
RectangleType rect = { { 0, 0 }, { 0, 0 } };
rect.extent.x = planarImage.width / 2;
rect.extent.y = planarImage.height / 2;
overlaySetting.type = kLcdOverlayLibDataFormatYCbCr420Planar;
err = LcdOverlayLibControl(gLCDOverlayRefNum, kLcdOverlayLibCtrlFormatSet, (void*)&overlaySetting);
err |= LcdOverlayLibControl(gLCDOverlayRefNum, kLcdOverlayLibCtrlRectSet, &rect);
err |= LcdOverlayLibControl(gLCDOverlayRefNum, kLcdOverlayLibCtrlStart, NULL);
if(err) {
FrmCustomAlert(ErrorAlert, "LCD Overlay Init failed!!!", NULL, NULL);
goto Done;
}
}
// Get the current time here we we go!
gFrameCount = 0;
gRateControl = sysTicksPerSecond / 15; // Rate control: 15 FPS
gStartTicks = gLastTick = TimGetTicks();
// Decode Frames
while(true)
{
// Set input params
inSize = inputBufferSize;
outSize = sizeof(PalmImagePlanarType);
// Check the event queue
EvtGetEvent(&event, 0);
if(event.eType == penDownEvent && RctPtInRectangle(event.screenX, event.screenY, &goButtonBounds))
goto Done;
// Decode a frame
err = CodecMgrEncodeDecode(gMPEG4Info.codecMgrLibRefNum, gMPEG4Info.session, currentBufferP, &inSize, swapImageP, &outSize);
switch(err)
{
UInt32 read = 0;
case kCodecSyncNotFound:
if(gMPEG4Info.loadFileInMemory) {
if(gMPEG4Info.loop)
{
VFSFileSize(gMPEG4Info.inputFileRef, &inputBufferSize);
currentBufferP = inputBufferP;
err = CodecMgrResetSession(gMPEG4Info.codecMgrLibRefNum, gMPEG4Info.session);
}
else
{
FrmCustomAlert(InfoAlert, "Decoding done!", NULL, NULL);
goto Done;
}
} else {
// Reload the buffer
MemMove(inputBufferP, currentBufferP, inputBufferSize);
err = VFSFileRead(gMPEG4Info.inputFileRef, DATA_BUFFER_SIZE - inputBufferSize, inputBufferP + inputBufferSize, &read);
if(!read) {
if(gMPEG4Info.loop)
{
VFSFileSeek(gMPEG4Info.inputFileRef, vfsOriginBeginning, 0);
currentBufferP = inputBufferP;
VFSFileRead(gMPEG4Info.inputFileRef, DATA_BUFFER_SIZE, inputBufferP, &inputBufferSize);
err = CodecMgrResetSession(gMPEG4Info.codecMgrLibRefNum, gMPEG4Info.session);
}
else
{
if(gUseOverlay)
err = LcdOverlayLibControl(gLCDOverlayRefNum, kLcdOverlayLibCtrlStop, NULL);
FrmCustomAlert(InfoAlert, "Decoding done!", NULL, NULL);
goto Done;
}
}
// Set current buffer
inputBufferSize += read;
currentBufferP = inputBufferP;
}
break;
// Real error
case kCodecMgrLibNotSupported:
case kCodecErrBadParam:
if(gUseOverlay)
err = LcdOverlayLibControl(gLCDOverlayRefNum, kLcdOverlayLibCtrlStop, NULL);
FrmCustomAlert(InfoAlert, "Decoding done!", NULL, NULL);
goto Done;
default:
break;
}
// Update the input buffer size
inputBufferSize -= inSize;
currentBufferP += inSize;
// Update the Frame counter
if(outSize)
{
gFrameCount++;
if(gUseOverlay)
{
err = LcdOverlayLibControl(gLCDOverlayRefNum, kLcdOverlayLibCtrlDraw, planarImage.planeP[0]);
}
if(gMPEG4Info.outputToSD)
{
UInt32 written = 0;
UInt32 YSize = planarImage.width * planarImage.height;
UInt32 CSize = planarImage.width * planarImage.height / 4;
// Write the Y components
err = VFSFileWrite(gMPEG4Info.outputFileRef, YSize, planarImage.planeP[0], &written);
if(err || written != YSize) {
FrmCustomAlert(ErrorAlert, "Error during file write!", NULL, NULL);
goto Done;
}
// Write the Cb components
err = VFSFileWrite(gMPEG4Info.outputFileRef, CSize, planarImage.planeP[1], &written);
if(err || written != CSize) {
FrmCustomAlert(ErrorAlert, "Error during file write!", NULL, NULL);
goto Done;
}
// Write the Cr components
err = VFSFileWrite(gMPEG4Info.outputFileRef, CSize, planarImage.planeP[2], &written);
if(err || written != CSize) {
FrmCustomAlert(ErrorAlert, "Error during file write!", NULL, NULL);
goto Done;
}
}
}
#if USE_RATE_CONTROL == 1
if((TimGetTicks() - gLastTick) < gRateControl)
SysTaskDelay(gRateControl - TimGetTicks() + gLastTick);
#endif
// Update the UI frame count
PrvUpdateUI(gFrameCount);
}
Done:
if(offScreenH)
WinDeleteWindow(offScreenH, false);
if(inputBufferP)
if(useFtr)
FtrPtrFree(appFileCreator, 0);
else
MemPtrFree(inputBufferP);
if(planarImage.planeP[0])
MemPtrFree(planarImage.planeP[0]);
if(imageParamP)
MemPtrFree(imageParamP);
if(swapImageP)
MemPtrFree(swapImageP);
// Close overlay
if( gUseOverlay)
err = LcdOverlayLibControl(gLCDOverlayRefNum, kLcdOverlayLibCtrlStop, NULL);
// Delete the session
if(gMPEG4Info.session)
CodecMgrDeleteSession(gMPEG4Info.codecMgrLibRefNum, &gMPEG4Info.session);
// Close files
if(gMPEG4Info.inputFileRef) {
VFSFileClose(gMPEG4Info.inputFileRef);
gMPEG4Info.inputFileRef = NULL;
}
if(gMPEG4Info.outputFileRef) {
VFSFileClose(gMPEG4Info.outputFileRef);
gMPEG4Info.outputFileRef = NULL;
}
// Quick refresh
if(gUseOverlay)
FrmDrawForm(FrmGetActiveForm());
return err;
}
/**
* Run the MPEG4 Encoder
*
* The loop option is done by simply rewinding the file or stream.
*/
static Err PrvStartEncoder()
{
Err err = errNone;
EventType event;
Boolean useFtr = false;
UInt32 inSize = 0;
UInt32 outSize = 0;
UInt32 inputBufferSize = 0;
UInt32 fileOffset = 0;
UInt8 *inputBufferP = NULL;
UInt8 *outputBufferP = NULL;
UInt8 *savedPlaneP[3] = { NULL, NULL, NULL };
RectangleType goButtonBounds;
PalmImagePlanarType planarImage;
PalmImagePlanarType *swapImageP = NULL;
PalmImageParamType *imageParamP = NULL;
PalmVideoMPEG4EncodeParamType *mpeg4ParamP = NULL;
// Make sure atack data is clean
MemSet(&planarImage, sizeof(PalmImagePlanarType), 0);
// Read parameters and check
err = PrvReadParameters(false);
if(err)
goto Done;
// Open the input and output files
err = PrvFileOpenInput();
if(err)
goto Done;
if(gMPEG4Info.outputToSD) {
err = PrvFileOpenOutput();
if(err)
goto Done;
}
// Allocate image structure
imageParamP = (PalmImageParamType*)MemPtrNew(sizeof(PalmImageParamType));
if(!imageParamP) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
MemSet(imageParamP, sizeof(PalmImageParamType), 0);
// Allocate swap image
swapImageP = (PalmImagePlanarType*)MemPtrNew(sizeof(PalmImagePlanarType));
if(!swapImageP) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
MemSet(swapImageP, sizeof(PalmImagePlanarType), 0);
// Allocate MPEG4 param
mpeg4ParamP = (PalmVideoMPEG4EncodeParamType*)MemPtrNew(sizeof(PalmVideoMPEG4EncodeParamType));
if(!mpeg4ParamP) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
MemSet(mpeg4ParamP, sizeof(PalmVideoMPEG4EncodeParamType), 0);
// Set Image Params
imageParamP->width = Swap32(gMPEG4Info.width);
imageParamP->height = Swap32(gMPEG4Info.height);
imageParamP->rowByte = 0; // Don't care
imageParamP->endianess = 0; // Don't care
// Set MPEG4 Params
mpeg4ParamP->profile = 0; // Don't care for now
mpeg4ParamP->volWidth = Swap32(gMPEG4Info.width);
mpeg4ParamP->volHeight = Swap32(gMPEG4Info.height);
mpeg4ParamP->keyFrame = Swap32(gMPEG4Info.keyFrame);
mpeg4ParamP->frameRate = Swap32(gMPEG4Info.frameRate);
mpeg4ParamP->bitRate = Swap32(gMPEG4Info.bitRate);
mpeg4ParamP->algorithm = Swap32(palmCodecMPEG4MVFAST);
mpeg4ParamP->IVOPQuantization = Swap32(gMPEG4Info.IQuantization);
mpeg4ParamP->VOVOLVersionID = Swap32(2);
// Set the planar image
planarImage.width = gMPEG4Info.width;
planarImage.height = gMPEG4Info.height;
switch(gMPEG4Info.imageFormat)
{
case palmCodecImageYCbCr420Planar:
planarImage.planeP[0] = Allocate(planarImage.width * planarImage.height);
planarImage.planeP[1] = Allocate(planarImage.width * planarImage.height / 4);
planarImage.planeP[2] = Allocate(planarImage.width * planarImage.height / 4);
planarImage.planeWidth[0] = planarImage.width;
planarImage.planeWidth[1] = planarImage.width / 2;
planarImage.planeWidth[2] = planarImage.width / 2;
break;
case palmCodecImageYCbCr422Planar:
planarImage.planeP[0] = Allocate(planarImage.width * planarImage.height);
planarImage.planeP[1] = Allocate(planarImage.width * planarImage.height / 2);
planarImage.planeP[2] = Allocate(planarImage.width * planarImage.height / 2);
planarImage.planeWidth[0] = planarImage.width;
planarImage.planeWidth[1] = planarImage.width / 2;
planarImage.planeWidth[2] = planarImage.width / 2;
break;
default:
FrmCustomAlert(ErrorAlert, "Bad image format", NULL, NULL);
goto Done;
break;
}
// Check for memory
if(!planarImage.planeP[0] || !planarImage.planeP[1] || !planarImage.planeP[2]) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
// Save plane pointers since they can be modified
savedPlaneP[0] = planarImage.planeP[0];
savedPlaneP[1] = planarImage.planeP[1];
savedPlaneP[2] = planarImage.planeP[2];
// Create a copy for the CPM
swapImageP->width = Swap32(planarImage.width);
swapImageP->height = Swap32(planarImage.height);
swapImageP->planeP[0] = (void*)Swap32(planarImage.planeP[0]);
swapImageP->planeP[1] = (void*)Swap32(planarImage.planeP[1]);
swapImageP->planeP[2] = (void*)Swap32(planarImage.planeP[2]);
swapImageP->planeWidth[0] = Swap32(planarImage.planeWidth[0]);
swapImageP->planeWidth[1] = Swap32(planarImage.planeWidth[1]);
swapImageP->planeWidth[2] = Swap32(planarImage.planeWidth[2]);
// Create the MPEG4 Encoding session
err = CodecMgrCreateSession(gMPEG4Info.codecMgrLibRefNum, gMPEG4Info.imageFormat, imageParamP, palmCodecVideoMPEG4, mpeg4ParamP, &gMPEG4Info.session);
if(err) {
FrmCustomAlert(ErrorAlert, "Unable to create session", NULL, NULL);
goto Done;
}
// Allocate output buffer
outputBufferP = (UInt8*)Allocate(planarImage.width * planarImage.height * 2);
if(!outputBufferP) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
MemSet(mpeg4ParamP, sizeof(PalmVideoMPEG4EncodeParamType), 0);
// Running from file
if(gMPEG4Info.loadFileInMemory)
{
// Get the file size
err = VFSFileSize(gMPEG4Info.inputFileRef, &inputBufferSize);
if(err || !inputBufferSize)
goto Done;
// Might work....
inputBufferP = (UInt8*)Allocate(inputBufferSize);
if(!inputBufferP) {
// Try with FtrPtr
err = FtrPtrNew(appFileCreator, 0, inputBufferSize, (void*)&inputBufferP);
if(err) {
err = memErrNotEnoughSpace;
FrmCustomAlert(ErrorAlert, "Not enough memory", NULL, NULL);
goto Done;
}
useFtr = true;
}
// Load the file
if(!PrvLoadFileInMemory(gMPEG4Info.inputFileRef, inputBufferSize, inputBufferP, useFtr))
goto Done;
}
// Get the bounds for the Go button
FrmGetObjectBounds(FrmGetActiveForm(), FrmGetObjectIndex(FrmGetActiveForm(),MainGoButton), &goButtonBounds);
// Get the current time here we we go!
gFrameCount = 0;
gStartTicks = gLastTick = TimGetTicks();
// Decode Frames
while(true)
{
// Load raw data from input file
if(gMPEG4Info.loadFileInMemory)
{
if( gMPEG4Info.loop && fileOffset < inputBufferSize)
fileOffset = 0;
if( fileOffset < inputBufferSize )
{
PrvLoadFrameFromMemory(inputBufferP + fileOffset, &planarImage, gMPEG4Info.imageFormat);
swapImageP->planeP[0] = (void*)Swap32(planarImage.planeP[0]);
swapImageP->planeP[1] = (void*)Swap32(planarImage.planeP[1]);
swapImageP->planeP[2] = (void*)Swap32(planarImage.planeP[2]);
switch(gMPEG4Info.imageFormat)
{
case palmCodecImageYCbCr420Planar:
fileOffset += ( 3 * planarImage.width * planarImage.height ) / 2;
break;
case palmCodecImageYCbCr422Planar:
fileOffset += ( 2 * planarImage.width * planarImage.height );
break;
}
}
else
{
FrmCustomAlert(InfoAlert, "Encoding done!", NULL, NULL);
goto Done;
}
}
else
{
// Load from file
err = PrvLoadFrameFromFile(gMPEG4Info.inputFileRef, &planarImage, gMPEG4Info.imageFormat);
if(err) {
if(gMPEG4Info.loop) {
VFSFileSeek(gMPEG4Info.inputFileRef, vfsOriginBeginning, 0);
err = PrvLoadFrameFromFile(gMPEG4Info.inputFileRef, &planarImage, gMPEG4Info.imageFormat);
} else {
FrmCustomAlert(InfoAlert, "Encoding done!", NULL, NULL);
goto Done;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -