📄 main.c
字号:
/*
* MiniMPEG4.c
*
* Main file for MPEG4
*
* This wizard-generated code is based on code adapted from the
* stationery files distributed as part of the Palm OS SDK 4.0.
*
* Copyright (c) 1999-2004 PalmOne, Inc. or its subsidiaries.
* All rights reserved.
*/
#include <PalmOS.h>
#include <VFSMgr.h>
#include <MemGlue.h>
#include "Common.h"
#include "MiniMPEG4.h"
#include "MiniMPEG4Rsc.h"
#include "FileBrowserForm.h"
#include "FileBrowserFormRsrc.h"
#include "PalmOneCodecPluginMgr.h"
#include "PalmOneCodecFormat.h"
#include "ColorButtonGadget.h"
#include "PalmLcdOverlay.h"
#include "PalmOneCamera.h"
#define ourMinVersion sysMakeROMVersion(3,0,0,sysROMStageDevelopment,0)
#define kPalmOS20Version sysMakeROMVersion(2,0,0,sysROMStageDevelopment,0)
#define Allocate(n) MemPtrNew(n)
#define DATA_BUFFER_SIZE 16384
#define USE_RATE_CONTROL 1
/** Holds basic encoder/decoder info. */
typedef struct {
Char inputFileName[256];
Char outputFileName[256];
FileRef inputFileRef;
FileRef outputFileRef;
UInt32 width;
UInt32 height;
UInt32 frameRate;
UInt32 bitRate;
UInt32 keyFrame;
UInt32 IQuantization;
UInt32 searchRange;
UInt16 codecMgrLibRefNum;
PalmCodecSession session;
UInt32 imageFormat;
Boolean loadFileInMemory;
Boolean outputToSD;
Boolean encoding;
Boolean loop;
} MPEG4Info;
#if 0
#pragma mark Globals
#endif
/** Internal Globals. */
static MPEG4Info gMPEG4Info;
static UInt32 gFrameCount = 0;
static UInt32 gStartTicks = 0;
static UInt32 gLastTick = 0;
static UInt32 gRateControl= 0;
static Char *gGOButtonLabel[] = { "Go", "Stop" };
static Char gLoadingText[] = "Loading";
static UInt32 gScreenDepth = 16;
static UInt32 gPreviousScreenDepth = 0;
RGBColorType gStartColor = { 0, 255, 255, 255 };
RGBColorType gEndColor = { 0, 0, 0, 255 };
static const RGBColorType gWhite = { 0, 255, 255, 255 };
static const RGBColorType gBlack = { 0, 0, 0, 0 };
// Extra
static UInt16 gLCDOverlayRefNum = sysInvalidRefNum;
static Boolean gUseOverlay = true;
static UInt16 gCameraRefNum = sysInvalidRefNum;
#if 0
#pragma mark -
#endif
/**
* Read and Encode the parameters
*/
static Err PrvReadParameters(Boolean encoding)
{
Err err = errNone;
FieldType *fldP = NULL;
FormType *frmP = FrmGetActiveForm();
// Get the width & height
fldP = FrmGetPtr(frmP, MainWidthField);
if(FldGetTextPtr(fldP))
gMPEG4Info.width = StrAToI(FldGetTextPtr(fldP));
fldP = FrmGetPtr(frmP, MainHeightField);
if(FldGetTextPtr(fldP))
gMPEG4Info.height = StrAToI(FldGetTextPtr(fldP));
// Read the file names
fldP = FrmGetPtr(frmP, MainInputField);
StrCopy(gMPEG4Info.inputFileName, FldGetTextPtr(fldP));
fldP = FrmGetPtr(frmP, MainOutputField);
StrCopy(gMPEG4Info.outputFileName, FldGetTextPtr(fldP));
// Get the SearchRange & BitRate
fldP = FrmGetPtr(frmP, MainSearchRangeField);
if(FldGetTextPtr(fldP))
gMPEG4Info.searchRange = StrAToI(FldGetTextPtr(fldP));
fldP = FrmGetPtr(frmP, MainBitRateField);
if(FldGetTextPtr(fldP))
gMPEG4Info.bitRate = StrAToI(FldGetTextPtr(fldP));
// Get the KeyFrame & IQuantization
fldP = FrmGetPtr(frmP, MainKeyFrameField);
if(FldGetTextPtr(fldP))
gMPEG4Info.keyFrame = StrAToI(FldGetTextPtr(fldP));
fldP = FrmGetPtr(frmP, MainIQuantizationField);
if(FldGetTextPtr(fldP))
gMPEG4Info.IQuantization = StrAToI(FldGetTextPtr(fldP));
Done:
return err;
}
/**
* Open input file
*/
static Err PrvFileOpenInput()
{
Err err = errNone;
UInt32 volumeIterator = 0;
UInt16 firstVolume = 0;
// Get first card
volumeIterator = vfsIteratorStart;
err = VFSVolumeEnumerate(&firstVolume, &volumeIterator);
if( err == expErrEnumerationEmpty ) {
goto Done;
}
// If we have a file path, open the file
if(gMPEG4Info.inputFileName)
{
err = VFSFileOpen(firstVolume, gMPEG4Info.inputFileName, vfsModeRead, &gMPEG4Info.inputFileRef);
if( err ) goto Done;
}
Done:
return err;
}
/**
* Open output file
*/
static Err PrvFileOpenOutput()
{
Err err = errNone;
UInt32 volumeIterator = 0;
UInt16 firstVolume = 0;
// Get first card
volumeIterator = vfsIteratorStart;
err = VFSVolumeEnumerate(&firstVolume, &volumeIterator);
if( err == expErrEnumerationEmpty ) {
goto Done;
}
// If we have a file path, open the file
if(gMPEG4Info.outputFileName)
{
err = VFSFileOpen(firstVolume, gMPEG4Info.outputFileName, vfsModeWrite|vfsModeCreate|vfsModeTruncate, &gMPEG4Info.outputFileRef);
if( err ) goto Done;
}
Done:
return err;
}
/**
* File info callback.
* This function is called by the file browser
*/
static void PrvGetInputFileInfoCallback(UInt16 volume, const Char* path, const Char* file)
{
// Create the full path name
StrCopy(gMPEG4Info.inputFileName, path);
// Internally, we expect full path
StrCat(gMPEG4Info.inputFileName, file);
}
/**
* Load a file in memory.
* Draws a fill rectangle with specified colors.
*
*/
static UInt32 PrvLoadFileInMemory(FileRef srcFile, UInt32 inputBufferSize, UInt8 *fileBufferP, Boolean useFtr)
{
UInt32 read = 0;
UInt32 total = 0;
UInt32 current = 0;
UInt32 xPosition = 80 - FntCharsWidth(gLoadingText, StrLen(gLoadingText)) / 2;
RGBColorType oldColor;
EventType event;
UInt8 *tempBufferP = NULL;
RectangleType goButtonBounds;
WinDrawOperation oldOperation;
UInt32 toRead = inputBufferSize / 100;
RectangleType rect = { { 30, 147 }, { 1, 10 } };
RGBColorType color = { 0, 0, 0, 0 };
Int32 R, G, B;
Int32 sR, sG, sB;
// FtrPtrNew - Allocate temporary buffer
if(useFtr) {
tempBufferP = MemPtrNew(4096);
}
// Save old color
WinSetBackColorRGB(&color, &oldColor);
R = (UInt32)gStartColor.r << 8; G = (UInt32)gStartColor.g << 8; B = (UInt32)gStartColor.b << 8;
// Color steps
sR = (((Int32)gEndColor.r - (Int32)gStartColor.r) << 8) / 101;
sG = (((Int32)gEndColor.g - (Int32)gStartColor.g) << 8) / 101;
sB = (((Int32)gEndColor.b - (Int32)gStartColor.b) << 8) / 101;
// Get the bounds for the Go button
FrmGetObjectBounds(FrmGetActiveForm(), FrmGetObjectIndex(FrmGetActiveForm(),MainGoButton), &goButtonBounds);
while(1)
{
EvtGetEvent(&event, 0);
if(event.eType == penDownEvent && RctPtInRectangle(event.screenX, event.screenY, &goButtonBounds)) {
total = 0;
goto Done;
}
if(useFtr) {
VFSFileRead(srcFile, 4096, tempBufferP, &read);
DmWrite(fileBufferP, total, tempBufferP, read);
} else {
VFSFileRead(srcFile, toRead, fileBufferP, &read);
fileBufferP += read;
}
if(!read)
break;
total += read;
current = (total * 100) / inputBufferSize + 31;
if( current > rect.topLeft.x)
{
R += sR; G += sG; B += sB;
if(R < 0) R = 0; if(R > 65536) R = 65536;
if(G < 0) G = 0; if(G > 65536) G = 65536;
if(B < 0) B = 0; if(B > 65536) B = 65536;
color.r = R >> 8;
color.g = G >> 8;
color.b = B >> 8;
WinSetBackColorRGB(&color, NULL);
WinFillRectangle(&rect, 0);
oldOperation = WinSetDrawMode(winOverlay);
WinPaintChars(gLoadingText, StrLen(gLoadingText), xPosition, 146);
WinSetDrawMode(oldOperation);
rect.topLeft.x = current;
}
}
Done:
if(tempBufferP)
MemPtrFree(tempBufferP);
WinSetBackColorRGB(&oldColor, NULL);
return total;
}
/**
* Update the current UI
* Displays the frmae count, the average FPS and the current FPS
*/
static void PrvUpdateUI()
{
Char text[32];
FieldType *fldP = NULL;
UInt32 curTicks = TimGetTicks();
UInt32 fps = curTicks - gStartTicks;
if(fps)
fps = (sysTicksPerSecond * gFrameCount) / fps;
// Average FPS
StrIToA(text, fps);
fldP = FrmGetPtr(FrmGetActiveForm(), MainAverageFPSField);
SetFieldTextFromStr(fldP, text, true);
// Current FPS
fps = ( curTicks - gLastTick );
if(fps)
fps = sysTicksPerSecond / fps;
StrIToA(text, fps);
fldP = FrmGetPtr(FrmGetActiveForm(), MainCurrentFPSField);
SetFieldTextFromStr(fldP, text, true);
gLastTick = curTicks;
// Current Frame Count
StrPrintF(text, "%04ld", gFrameCount);
fldP = FrmGetPtr(FrmGetActiveForm(), MainFramesField);
SetFieldTextFromStr(fldP, text, true);
}
/**
* DrawLaoding rectangle
*/
static void PrvDrawLoadingRect()
{
RGBColorType oldColor;
RectangleType rect = { { 30, 147 }, { 101, 10 } };
// Draw the progress bar
WinSetForeColorRGB(&gWhite, &oldColor);
WinDrawRectangle(&rect, 0);
WinSetForeColorRGB(&gBlack, NULL);
WinDrawRectangleFrame(rectangleFrame, &rect);
// Restore
WinSetForeColorRGB(&oldColor, NULL);
}
#if 0
#pragma mark -
#endif
/**
* Load a frame from memory.
*/
static void PrvLoadFrameFromMemory(UInt8 *bufferP, PalmImagePlanarType *planarImage, UInt32 imageFormat)
{
switch(imageFormat)
{
case palmCodecImageYCbCr420Planar:
planarImage->planeP[0] = bufferP;
bufferP += planarImage->width * planarImage->height;
planarImage->planeP[1] = bufferP;
bufferP += planarImage->width * planarImage->height / 4;
planarImage->planeP[2] = bufferP;
break;
case palmCodecImageYCbCr422Planar:
planarImage->planeP[0] = bufferP;
bufferP += planarImage->width * planarImage->height;
planarImage->planeP[1] = bufferP;
bufferP += planarImage->width * planarImage->height / 2;
planarImage->planeP[2] = bufferP;
break;
}
}
/**
* Laos a frame from file
*/
static Err PrvLoadFrameFromFile(FileRef fileRef, PalmImagePlanarType *planarImage, UInt32 imageFormat)
{
Err err = errNone;
UInt32 read = 0;
UInt32 width = 0;
UInt32 height = 0;
UInt32 YHeight = 0;
UInt32 YWidth = 0;
UInt32 CHeight = 0;
UInt32 CWidth = 0;
UInt8 *planeP = NULL;
switch(imageFormat)
{
case palmCodecImageYCbCr420Planar:
YWidth = planarImage->width;
YHeight = planarImage->height;
CWidth = planarImage->width / 2;
CHeight = planarImage->height / 2;
break;
case palmCodecImageYCbCr422Planar:
YWidth = planarImage->width;
YHeight = planarImage->height;
CWidth = planarImage->width / 2;
CHeight = planarImage->height;
break;
default:
err = appErrorClass;
goto Done;
}
// Load the Y components
planeP = planarImage->planeP[0];
for(height = 0; height < YHeight; height++)
{
err = VFSFileRead(fileRef, YWidth, planeP, &read);
if(err || read != YWidth) {
err = vfsErrFileEOF;
goto Done;
}
planeP += YWidth;
}
// Load the Cb components
planeP = planarImage->planeP[1];
for(height = 0; height < CHeight; height++)
{
err = VFSFileRead(fileRef,CWidth, planeP, &read);
if(err || read != CWidth) {
err = vfsErrFileEOF;
goto Done;
}
planeP += CWidth;
}
// Load the Cr components
planeP = planarImage->planeP[2];
for(height = 0; height < CHeight; height++)
{
err = VFSFileRead(fileRef, CWidth, planeP, &read);
if(err || read != CWidth) {
err = vfsErrFileEOF;
goto Done;
}
planeP += CWidth;
}
Done:
return err;
}
#if 0
#pragma mark -
#endif
/**
* Run the MPEG4 Decoder
*
* The loop option is done by resetting the decoder since the
* next loop will have to read again the VO & VOL header.
*/
static Err PrvStartDecoder()
{
Err err = errNone;
EventType event;
UInt32 inSize = 0;
UInt32 outSize = 0;
Boolean useFtr = false;
UInt32 inputBufferSize = 0;
UInt8 *inputBufferP = NULL;
UInt8 *currentBufferP = NULL;
UInt8 *offScreenP = NULL;
WinHandle offScreenH = NULL;
RectangleType goButtonBounds;
PalmImagePlanarType planarImage;
PalmImagePlanarType *swapImageP = NULL;
PalmImageParamType *imageParamP = 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);
// Set Image Params
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -