This dissertation has been submitted by a student. This is not an example of the work written by our professional dissertation writers.

ENCODEDECODE DEMO

--------------------

/*

* encodedecode.h

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

#ifndef _ENCODEDECODE_H

#define _ENCODEDECODE_H

/* Standard Linux headers */

#include <stdio.h>

#include <pthread.h>

/* Enables or disables debug output */

#ifdef __DEBUG

#define DBG(fmt, args...) fprintf(stderr, "Encodedecode Debug: " fmt, ## args)

#else

#define DBG(fmt, args...)

#endif

#define ERR(fmt, args...) fprintf(stderr, "Encodedecode Error: " fmt, ## args)

/* Function error codes */

#define SUCCESS 0

#define FAILURE -1

/* Thread error codes */

#define THREAD_SUCCESS (void *) 0

#define THREAD_FAILURE (void *) -1

/* The codec engine to use in this application */

#define ENGINE_NAME "encodedecode"

/* Device parameters */

#define V4L2_DEVICE "/dev/video0"

#define OSD_DEVICE "/dev/fb/0"

#define ATTR_DEVICE "/dev/fb/2"

#define FBVID_DEVICE "/dev/fb/3"

/* True of false enumeration */

#define TRUE 1

#define FALSE 0

/* Scaling factors for the video standards */

#define NOSTD 0

#define PALSTD 12

#define NTSCSTD 10

/* Number of microseconds to pause if the demo is 'paused' */

#define PAUSE 100

/* Screen dimensions */

#define SCREEN_BPP 16

#define D1_WIDTH 720

#define D1_HEIGHT yScale(480)

#define D1_LINE_WIDTH D1_WIDTH * SCREEN_BPP / 8

#define D1_FRAME_SIZE D1_LINE_WIDTH * D1_HEIGHT

/* Global data structure */

typedef struct GlobalData {

int quit; /* Global quit flag */

int play; /* Whether to play or pause */

int frames; /* Video frame counter */

int videoBytesEncoded; /* Video bytes encoded counter */

int yFactor; /* Vertical scaling (PAL vs. NTSC) */

pthread_mutex_t mutex; /* Mutex to protect the global data */

} GlobalData;

/* Global data */

extern GlobalData gbl;

/* Functions to protect the global data */

static inline int gblGetQuit(void)

{

int quit;

pthread_mutex_lock(&gbl.mutex);

quit = gbl.quit;

pthread_mutex_unlock(&gbl.mutex);

return quit;

}

static inline void gblSetQuit(void)

{

pthread_mutex_lock(&gbl.mutex);

gbl.quit = TRUE;

pthread_mutex_unlock(&gbl.mutex);

}

static inline int gblGetPlay(void)

{

int play;

pthread_mutex_lock(&gbl.mutex);

play = gbl.play;

pthread_mutex_unlock(&gbl.mutex);

return play;

}

static inline void gblSetPlay(int play)

{

pthread_mutex_lock(&gbl.mutex);

gbl.play = play;

pthread_mutex_unlock(&gbl.mutex);

}

static inline int gblGetAndResetFrames(void)

{

int frames;

pthread_mutex_lock(&gbl.mutex);

frames = gbl.frames;

gbl.frames = 0;

pthread_mutex_unlock(&gbl.mutex);

return frames;

}

static inline void gblIncFrames(void)

{

pthread_mutex_lock(&gbl.mutex);

gbl.frames++;

pthread_mutex_unlock(&gbl.mutex);

}

static inline int gblGetAndResetVideoBytesEncoded(void)

{

int videoBytesEncoded;

pthread_mutex_lock(&gbl.mutex);

videoBytesEncoded = gbl.videoBytesEncoded;

gbl.videoBytesEncoded = 0;

pthread_mutex_unlock(&gbl.mutex);

return videoBytesEncoded;

}

static inline void gblIncVideoBytesEncoded(int videoBytesEncoded)

{

pthread_mutex_lock(&gbl.mutex);

gbl.videoBytesEncoded += videoBytesEncoded;

pthread_mutex_unlock(&gbl.mutex);

}

static inline int gblGetYFactor(void)

{

int yFactor;

pthread_mutex_lock(&gbl.mutex);

yFactor = gbl.yFactor;

pthread_mutex_unlock(&gbl.mutex);

return yFactor;

}

static inline void gblSetYFactor(int yFactor)

{

pthread_mutex_lock(&gbl.mutex);

gbl.yFactor = yFactor;

pthread_mutex_unlock(&gbl.mutex);

}

/* Scale vertically depending on video standard */

#define yScale(x) (((x) * gblGetYFactor()) / 10)

/* Cleans up cleanly after a failure */

#define cleanup(x) \

status = (x); \

gblSetQuit(); \

goto cleanup

/* Breaks a processing loop for a clean exit */

#define breakLoop(x) \

status = (x); \

gblSetQuit(); \

break

#endif /* _ENCODEDECODE_H */

/*

* main.c

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

/* Standard Linux headers */

#include <stdio.h>

#include <errno.h>

#include <fcntl.h>

#include <stdlib.h>

#include <getopt.h>

#include <unistd.h>

#include <string.h>

#include <pthread.h>

#include <sys/ioctl.h>

#include <sys/resource.h>

/* Davinci specific kernel headers */

#include <video/davincifb.h>

/* Codec Engine headers */

#include <xdc/std.h>

#include <ti/sdo/ce/Engine.h>

#include <ti/sdo/ce/trace/gt.h>

#include <ti/sdo/ce/CERuntime.h>

#include <ti/sdo/ce/utils/trace/TraceUtil.h>

/* Demo headers */

#include <rendezvous.h>

#include "encodedecode.h"

#include "video.h"

#include "ctrl.h"

/* The levels of initialization */

#define LOGSINITIALIZED 0x1

#define RENDEZVOUSOPENED 0x2

#define VIDEOTHREADCREATED 0x4

typedef struct Args {

int imageWidth;

int imageHeight;

int videoBitRate;

int passThrough;

int svideoInput;

int keyboard;

int time;

int interface;

} Args;

/* Global variable declarations for this application */

GlobalData gbl = { 0, 1, 0, 0, NOSTD };

/******************************************************************************

* usage

******************************************************************************/

static void usage(void)

{

printf("Usage: encodedecode [options]\n\n"

"Options:\n"

"-r | --resolution Video resolution ('width'x'height') [720x480]\n"

"-b | --bitrate Bit rate to encode video at [variable]\n"

"-p | --passthrough Pass video through without encoding [off]\n"

"-x | --svideo Use s-video instead of composite video input\n"

"-k | --keyboard Enable keyboard interface\n"

"-t | --time Number of seconds to run the demo [infinite]\n"

"-i | --interface Launch the demo interface when exiting [off]\n"

"-h | --help Print this message\n\n");

}

/******************************************************************************

* parseArgs

******************************************************************************/

static void parseArgs(int argc, char *argv[], Args *argsp)

{

const char shortOptions[] = "r:b:pxkt:ih";

const struct option longOptions[] = {

{"resolution", required_argument, NULL, 'r'},

{"bitrate", required_argument, NULL, 'b'},

{"passthrough", no_argument, NULL, 'p'},

{"svideo", no_argument, NULL, 'x'},

{"keyboard", no_argument, NULL, 'k'},

{"time", required_argument, NULL, 't'},

{"interface", no_argument, NULL, 'i'},

{"help", no_argument, NULL, 'h'},

{0, 0, 0, 0}

};

int index;

int c;

int imageWidth;

int imageHeight;

for (;;) {

c = getopt_long(argc, argv, shortOptions, longOptions, &index);

if (c == -1) {

break;

}

switch (c) {

case 0:

break;

case 'r':

if (sscanf(optarg, "%dx%d", &imageWidth,

&imageHeight) != 2) {

fprintf(stderr, "Invalid resolution supplied (%s)\n",

optarg);

usage();

exit(EXIT_FAILURE);

}

/* Sanity check resolution */

if (imageWidth <= 0 || imageHeight <= 0 ||

imageWidth > D1_WIDTH || imageHeight > D1_HEIGHT) {

fprintf(stderr, "Video resolution must be maximum %dx%d\n",

D1_WIDTH, D1_HEIGHT);

exit(EXIT_FAILURE);

}

/* Only use multiples of 16 */

argsp->imageWidth = imageWidth & ~0xf;

argsp->imageHeight = imageHeight & ~0xf;

break;

case 'b':

argsp->videoBitRate = atoi(optarg);

break;

case 'x':

argsp->svideoInput = TRUE;

break;

case 'p':

argsp->passThrough = TRUE;

break;

case 'k':

argsp->keyboard = TRUE;

break;

case 't':

argsp->time = atoi(optarg);

break;

case 'i':

argsp->interface = TRUE;

break;

case 'h':

usage();

exit(EXIT_SUCCESS);

default:

usage();

exit(EXIT_FAILURE);

}

}

}

/******************************************************************************

* detectVideoStandard

******************************************************************************/

static int detectVideoStandard(void)

{

int fd;

int std;

/* Open video display device */

fd = open(FBVID_DEVICE, O_RDWR);

if (fd == -1) {

ERR("Failed to open fb device %s (%s)\n", FBVID_DEVICE,

strerror(errno));

return FAILURE;

}

/* Query the display device driver for video standard chosen */

if (ioctl(fd, FBIO_GETSTD, &std) == -1) {

ERR("Failed to get video standard from display device driver\n");

return FAILURE;

}

if ((std >> 16) == 0x1) {

DBG("NTSC selected\n");

gblSetYFactor(NTSCSTD);

}

else {

DBG("PAL selected\n");

gblSetYFactor(PALSTD);

}

close(fd);

return SUCCESS;

}

/******************************************************************************

* main

******************************************************************************/

int main(int argc, char *argv[])

{

unsigned int initMask = 0;

int status = EXIT_SUCCESS;

int numThreads;

struct sched_param schedParam;

Rendezvous_Obj rendezvous;

pthread_t videoThread;

pthread_attr_t attr;

VideoEnv videoEnv;

CtrlEnv ctrlEnv;

void *ret;

Args args = {

720,

480,

-1,

FALSE,

FALSE,

FALSE,

FOREVER,

FALSE

};

/* Detect PAL or NTSC */

if (detectVideoStandard() == FAILURE) {

cleanup(EXIT_FAILURE);

}

/* Parse the arguments given to the app and set the app environment */

parseArgs(argc, argv, &args);

printf("Encodedecode demo started.\n");

/* Initialize the mutex which protects the global data */

pthread_mutex_init(&gbl.mutex, NULL);

/* Set the priority of this whole process to max (requires root) */

setpriority(PRIO_PROCESS, 0, -20);

/* Initialize Codec Engine runtime */

CERuntime_init();

DBG("Codec Engine initialized\n");

/* Initialize the logs. Must be done after CERuntime_init() */

TraceUtil_start(ENGINE_NAME);

initMask |= LOGSINITIALIZED;

DBG("Logging initialized\n");

/* Open the object which synchronizes the thread initialization */

numThreads = 3;

Rendezvous_open(&rendezvous, numThreads);

initMask |= RENDEZVOUSOPENED;

DBG("Rendezvous opened for %d threads\n", numThreads);

/* Initialize the thread attributes */

if (pthread_attr_init(&attr)) {

ERR("Failed to initialize thread attrs\n");

cleanup(EXIT_FAILURE);

}

/* Force the thread to use custom scheduling attributes */

if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) {

ERR("Failed to set schedule inheritance attribute\n");

cleanup(EXIT_FAILURE);

}

/* Set the thread to be fifo real time scheduled */

if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {

ERR("Failed to set FIFO scheduling policy\n");

cleanup(EXIT_FAILURE);

}

/* Set the thread priority */

schedParam.sched_priority = sched_get_priority_max(SCHED_FIFO);

if (pthread_attr_setschedparam(&attr, &schedParam)) {

ERR("Failed to set scheduler parameters\n");

cleanup(EXIT_FAILURE);

}

/* Create the thread */

videoEnv.hRendezvous = &rendezvous;

videoEnv.videoBitRate = args.videoBitRate;

videoEnv.passThrough = args.passThrough;

videoEnv.svideoInput = args.svideoInput;

videoEnv.imageWidth = args.imageWidth;

videoEnv.imageHeight = args.imageHeight;

if (pthread_create(&videoThread, &attr, videoThrFxn, (void *) &videoEnv)) {

ERR("Failed to create video thread\n");

cleanup(EXIT_FAILURE);

}

initMask |= VIDEOTHREADCREATED;

/* Main thread becomes the control thread */

ctrlEnv.hRendezvous = &rendezvous;

ctrlEnv.keyboard = args.keyboard;

ctrlEnv.time = args.time;

ctrlEnv.imageWidth = args.imageWidth;

ctrlEnv.imageHeight = args.imageHeight;

ctrlEnv.passThrough = args.passThrough;

ret = ctrlThrFxn(&ctrlEnv);

if (ret == THREAD_FAILURE) {

status = EXIT_FAILURE;

}

cleanup:

/* Make sure the other threads aren't waiting for init to complete */

Rendezvous_force(&rendezvous);

/* Wait until the other threads terminate */

if (initMask & VIDEOTHREADCREATED) {

if (pthread_join(videoThread, &ret) == 0) {

if (ret == THREAD_FAILURE) {

status = EXIT_FAILURE;

}

}

}

if (initMask & RENDEZVOUSOPENED) {

Rendezvous_close(&rendezvous);

}

if (initMask & LOGSINITIALIZED) {

TraceUtil_stop();

}

/* Destroy the global mutex */

pthread_mutex_destroy(&gbl.mutex);

if (status == EXIT_SUCCESS && args.interface) {

if (execl("./interface", "interface", "-l 2", NULL) == -1) {

status = EXIT_FAILURE;

}

}

exit(status);

}

/*

* ctrl.h

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

#ifndef _CTRL_H

#define _CTRL_H

#include <rendezvous.h>

#include "encodedecode.h"

/* Defining infinite time */

#define FOREVER -1

typedef struct CtrlEnv {

Rendezvous_Handle hRendezvous;

int keyboard;

int time;

int imageWidth;

int imageHeight;

int passThrough;

} CtrlEnv;

extern void *ctrlThrFxn(void *arg);

#endif /* _CTRL_H */

/*

* ctrl.c

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

/* Standard Linux headers */

#include <stdio.h>

#include <errno.h>

#include <fcntl.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <pthread.h>

#include <linux/fb.h>

#include <sys/mman.h>

#include <sys/time.h>

#include <sys/ioctl.h>

/* Davinci specific kernel headers */

#include <video/davincifb.h>

/* Codec Engine headers */

#include <xdc/std.h>

#include <ti/sdo/ce/Engine.h>

/* Demo headers */

#include <rendezvous.h>

#include <msp430lib.h>

#include "encodedecode.h"

#include "ctrl.h"

#include "ui.h"

/* Keyboard command prompt */

#define COMMAND_PROMPT "Command [ 'help' for usage ] > "

/* The 0-7 transparency value to use for the OSD */

#define OSD_TRANSPARENCY 0x55

#define MAX_TRANSPARENCY 0x77

#define MIN_TRANSPARENCY 0x11

#define INC_TRANSPARENCY 0x11

#define NO_TRANSPARENCY 0x0

/* The levels of initialization */

#define OSDINITIALIZED 0x1

#define ENGINEOPENED 0x2

#define MSP430LIBINITIALIZED 0x4

#define UICREATED 0x8

/* Local function prototypes */

static int setOsdBuffer(int osdFd, int idx);

static int osdInit(char *displays[]);

static int osdExit(int osdFd);

static int setOsdTransparency(unsigned char trans);

static int waitForVsync(int fd);

static int getArmCpuLoad(int *procLoad, int *cpuLoad);

static int keyAction(enum msp430lib_keycode key, int displayIdx,

int *osdTransPtr);

static void drawDynamicData(Engine_Handle hEngine, int osdFd, int *time,

int *displayIdx, int *workingIdx);

/******************************************************************************

* setOsdBuffer

******************************************************************************/

static int setOsdBuffer(int osdFd, int idx)

{

struct fb_var_screeninfo vInfo;

if (ioctl(osdFd, FBIOGET_VSCREENINFO, &vInfo) == -1) {

ERR("Failed FBIOGET_VSCREENINFO (%s)\n", strerror(errno));

return FAILURE;

}

vInfo.yoffset = vInfo.yres * idx;

if (ioctl(osdFd, FBIOPAN_DISPLAY, &vInfo) == -1) {

ERR("Failed FBIOPAN_DISPLAY (%s)\n", strerror(errno));

return FAILURE;

}

return SUCCESS;

}

/******************************************************************************

* osdInit

******************************************************************************/

static int osdInit(char *displays[])

{

struct fb_var_screeninfo varInfo;

int fd;

int size;

/* Open the OSD device */

fd = open(OSD_DEVICE, O_RDWR);

if (fd == -1) {

ERR("Failed to open fb device %s\n", OSD_DEVICE);

return FAILURE;

}

if (ioctl(fd, FBIOGET_VSCREENINFO, &varInfo) == -1) {

ERR("Failed ioctl FBIOGET_VSCREENINFO on %s\n", OSD_DEVICE);

return FAILURE;

}

/* Try the requested size */

varInfo.xres = D1_WIDTH;

varInfo.yres = D1_HEIGHT;

varInfo.bits_per_pixel = SCREEN_BPP;

if (ioctl(fd, FBIOPUT_VSCREENINFO, &varInfo) == -1) {

ERR("Failed ioctl FBIOPUT_VSCREENINFO on %s\n", OSD_DEVICE);

return FAILURE;

}

if (varInfo.xres != D1_WIDTH ||

varInfo.yres != D1_HEIGHT ||

varInfo.bits_per_pixel != SCREEN_BPP) {

ERR("Failed to get the requested screen size: %dx%d at %d bpp\n",

D1_WIDTH, D1_HEIGHT, SCREEN_BPP);

return FAILURE;

}

size = varInfo.xres * varInfo.yres * varInfo.bits_per_pixel / 8;

/* Map the frame buffers to user space */

displays[0] = (char *) mmap(NULL, size * NUM_BUFS,

PROT_READ | PROT_WRITE,

MAP_SHARED, fd, 0);

if (displays[0] == MAP_FAILED) {

ERR("Failed mmap on %s\n", OSD_DEVICE);

return FAILURE;

}

displays[1] = displays[0] + size;

setOsdBuffer(fd, 0);

return fd;

}

/******************************************************************************

* osdExit

******************************************************************************/

static int osdExit(int osdFd)

{

setOsdBuffer(osdFd, 0);

close(osdFd);

return SUCCESS;

}

/******************************************************************************

* setOsdTransparency

******************************************************************************/

static int setOsdTransparency(unsigned char trans)

{

struct fb_var_screeninfo vInfo;

unsigned short *attrDisplay;

int attrSize;

int fd;

/* Open the attribute device */

fd = open(ATTR_DEVICE, O_RDWR);

if (fd == -1) {

ERR("Failed to open attribute window %s\n", ATTR_DEVICE);

return FAILURE;

}

if (ioctl(fd, FBIOGET_VSCREENINFO, &vInfo) == -1) {

ERR("Error reading variable information.\n");

return FAILURE;

}

/* One nibble per pixel */

attrSize = vInfo.xres_virtual * vInfo.yres / 2;

attrDisplay = (unsigned short *) mmap(NULL, attrSize,

PROT_READ | PROT_WRITE,

MAP_SHARED, fd, 0);

if (attrDisplay == MAP_FAILED) {

ERR("Failed mmap on %s\n", ATTR_DEVICE);

return FAILURE;

}

/* Fill the window with the new attribute value */

memset(attrDisplay, trans, attrSize);

munmap(attrDisplay, attrSize);

close(fd);

return SUCCESS;

}

/******************************************************************************

* waitForVsync

******************************************************************************/

static int waitForVsync(int fd)

{

int dummy;

/* Wait for vertical sync */

if (ioctl(fd, FBIO_WAITFORVSYNC, &dummy) == -1) {

ERR("Failed FBIO_WAITFORVSYNC (%s)\n", strerror(errno));

return FAILURE;

}

return SUCCESS;

}

/******************************************************************************

* getArmCpuLoad

******************************************************************************/

static int getArmCpuLoad(int *procLoad, int *cpuLoad)

{

static unsigned long prevIdle = 0;

static unsigned long prevTotal = 0;

static unsigned long prevProc = 0;

int cpuLoadFound = FALSE;

unsigned long user, nice, sys, idle, total, proc;

unsigned long uTime, sTime, cuTime, csTime;

unsigned long deltaTotal, deltaIdle, deltaProc;

char textBuf[4];

FILE *fptr;

/* Read the overall system information */

fptr = fopen("/proc/stat", "r");

if (fptr == NULL) {

ERR("/proc/stat not found. Is the /proc filesystem mounted?\n");

return FAILURE;

}

/* Scan the file line by line */

while (fscanf(fptr, "%4s %lu %lu %lu %lu %*[^\n]", textBuf,

&user, &nice, &sys, &idle) != EOF) {

if (strcmp(textBuf, "cpu") == 0) {

cpuLoadFound = TRUE;

break;

}

}

if (fclose(fptr) != 0) {

return FAILURE;

}

if (!cpuLoadFound) {

return FAILURE;

}

/* Read the current process information */

fptr = fopen("/proc/self/stat", "r");

if (fptr == NULL) {

ERR("/proc/self/stat not found. Is the /proc filesystem mounted?\n");

return FAILURE;

}

if (fscanf(fptr, "%*d %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %lu "

"%lu %lu %lu", &uTime, &sTime, &cuTime, &csTime) != 4) {

ERR("Failed to get process load information.\n");

fclose(fptr);

return FAILURE;

}

if (fclose(fptr) != 0) {

return FAILURE;

}

total = user + nice + sys + idle;

proc = uTime + sTime + cuTime + csTime;

/* Check if this is the first time, if so init the prev values */

if (prevIdle == 0 && prevTotal == 0 && prevProc == 0) {

prevIdle = idle;

prevTotal = total;

prevProc = proc;

return SUCCESS;

}

deltaIdle = idle - prevIdle;

deltaTotal = total - prevTotal;

deltaProc = proc - prevProc;

prevIdle = idle;

prevTotal = total;

prevProc = proc;

*cpuLoad = 100 - deltaIdle * 100 / deltaTotal;

*procLoad = deltaProc * 100 / deltaTotal;

return SUCCESS;

}

/******************************************************************************

* drawDynamicData

******************************************************************************/

static void drawDynamicData(Engine_Handle hEngine, int osdFd, int *time,

int *displayIdx, int *workingIdx)

{

static unsigned long firstTime = 0;

static unsigned long prevTime;

unsigned long newTime;

unsigned long deltaTime;

struct timeval tv;

struct tm *timePassed;

time_t spentTime;

char tempString[9];

int procLoad;

int armLoad;

int dspLoad;

int fps;

int videoKbps;

float fpsf;

float videoKbpsf;

*time = -1;

if (gettimeofday(&tv, NULL) == -1) {

ERR("Failed to get os time\n");

return;

}

newTime = tv.tv_sec * 1000 + tv.tv_usec / 1000;

if (!firstTime) {

firstTime = newTime;

prevTime = newTime;

return;

}

/* Only update OSD every second */

deltaTime = newTime - prevTime;

if (deltaTime <= 1000) {

return;

}

prevTime = newTime;

spentTime = (newTime - firstTime) / 1000;

if (spentTime <= 0) {

return;

}

*time = spentTime;

fpsf = gblGetAndResetFrames() * 1000.0 / deltaTime;

fps = fpsf + 0.5;

videoKbpsf = gblGetAndResetVideoBytesEncoded() * 8.0 / deltaTime;

videoKbps = videoKbpsf + 0.5;

uiClearScreen(COLUMN_2, 0, COLUMN_3 - COLUMN_2, yScale(220), *workingIdx);

if (getArmCpuLoad(&procLoad, &armLoad) != FAILURE) {

sprintf(tempString, "%d%%", procLoad);

uiDrawText(tempString, COLUMN_2, ROW_1, *workingIdx);

}

else {

ERR("Failed to get ARM CPU load\n");

}

dspLoad = Engine_getCpuLoad(hEngine);

if (dspLoad > -1) {

sprintf(tempString, "%d%%", dspLoad);

uiDrawText(tempString, COLUMN_2, ROW_2, *workingIdx);

}

else {

ERR("Failed to get DSP CPU load\n");

}

sprintf(tempString, "%d fps", fps);

uiDrawText(tempString, COLUMN_2, ROW_3, *workingIdx);

sprintf(tempString, "%d kbps", videoKbps);

uiDrawText(tempString, COLUMN_2, ROW_4, *workingIdx);

timePassed = localtime(&spentTime);

if (timePassed == NULL) {

return;

}

sprintf(tempString, "%.2d:%.2d:%.2d", timePassed->tm_hour,

timePassed->tm_min,

timePassed->tm_sec);

uiDrawText(tempString, COLUMN_2, ROW_5, *workingIdx);

*displayIdx = (*displayIdx + 1) % NUM_BUFS;

*workingIdx = (*workingIdx + 1) % NUM_BUFS;

setOsdBuffer(osdFd, *displayIdx);

waitForVsync(osdFd);

}

/******************************************************************************

* keyAction

******************************************************************************/

static int keyAction(enum msp430lib_keycode key, int displayIdx,

int *osdTransPtr)

{

static int osdVisible = TRUE;

switch(key) {

case MSP430LIB_KEYCODE_OK:

case MSP430LIB_KEYCODE_PLAY:

DBG("Play button pressed\n");

gblSetPlay(TRUE);

if (uiPressButton(BTNIDX_CTRLPLAY, displayIdx) == FAILURE) {

return FAILURE;

}

break;

case MSP430LIB_KEYCODE_PAUSE:

DBG("Pause button pressed\n");

gblSetPlay(FALSE);

if (uiPressButton(BTNIDX_CTRLPAUSE, displayIdx) == FAILURE) {

return FAILURE;

}

break;

case MSP430LIB_KEYCODE_STOP:

DBG("Stop button pressed, quitting demo..\n");

gblSetQuit();

break;

case MSP430LIB_KEYCODE_VOLINC:

DBG("Volume inc button pressed\n");

if (*osdTransPtr < MAX_TRANSPARENCY && osdVisible) {

*osdTransPtr += INC_TRANSPARENCY;

setOsdTransparency(*osdTransPtr);

}

if (uiPressButton(BTNIDX_NAVPLUS, displayIdx) == FAILURE) {

return FAILURE;

}

break;

case MSP430LIB_KEYCODE_VOLDEC:

DBG("Volume dec button pressed\n");

if (*osdTransPtr > MIN_TRANSPARENCY && osdVisible) {

*osdTransPtr -= INC_TRANSPARENCY;

setOsdTransparency(*osdTransPtr);

}

if (uiPressButton(BTNIDX_NAVMINUS, displayIdx) == FAILURE) {

return FAILURE;

}

break;

case MSP430LIB_KEYCODE_INFOSELECT:

DBG("Info/select command received.\n");

if (osdVisible) {

setOsdTransparency(NO_TRANSPARENCY);

osdVisible = FALSE;

}

else {

setOsdTransparency(*osdTransPtr);

osdVisible = TRUE;

}

break;

default:

DBG("Unknown button pressed.\n");

if (uiPressButton(BTNIDX_WRONGPRESSED, displayIdx) == FAILURE) {

return FAILURE;

}

}

return SUCCESS;

}

/******************************************************************************

* getKbdCommand

******************************************************************************/

int getKbdCommand(enum msp430lib_keycode *keyPtr)

{

struct timeval tv;

fd_set fds;

int ret;

char string[80];

FD_ZERO(&fds);

FD_SET(fileno(stdin), &fds);

/* Timeout of 0 means polling */

tv.tv_sec = 0;

tv.tv_usec = 0;

ret = select(FD_SETSIZE, &fds, NULL, NULL, &tv);

if (ret == -1) {

ERR("Select failed on stdin (%s)\n", strerror(errno));

return FAILURE;

}

if (ret == 0) {

return SUCCESS;

}

if (FD_ISSET(fileno(stdin), &fds)) {

if (fgets(string, 80, stdin) == NULL) {

return FAILURE;

}

/* Remove the end of line */

strtok(string, "\n");

/* Assign corresponding msp430lib key */

if (strcmp(string, "play") == 0) {

*keyPtr = MSP430LIB_KEYCODE_PLAY;

}

else if (strcmp(string, "pause") == 0) {

*keyPtr = MSP430LIB_KEYCODE_PAUSE;

}

else if (strcmp(string, "stop") == 0) {

*keyPtr = MSP430LIB_KEYCODE_STOP;

}

else if (strcmp(string, "inc") == 0) {

*keyPtr = MSP430LIB_KEYCODE_VOLDEC;

}

else if (strcmp(string, "dec") == 0) {

*keyPtr = MSP430LIB_KEYCODE_VOLINC;

}

else if (strcmp(string, "hide") == 0) {

*keyPtr = MSP430LIB_KEYCODE_INFOSELECT;

}

else if (strcmp(string, "help") == 0) {

printf("\nAvailable commands:\n"

" play - Play video\n"

" pause - Pause video\n"

" stop - Quit demo\n"

" inc - Increase OSD transparency\n"

" dec - Decrease OSD transparency\n"

" hide - Show / hide the OSD\n"

" help - Show this help screen\n\n");

}

else {

printf("Unknown command: [ %s ]\n", string);

}

if (*keyPtr != MSP430LIB_KEYCODE_STOP) {

printf(COMMAND_PROMPT);

fflush(stdout);

}

else {

printf("\n");

}

}

return SUCCESS;

}

/******************************************************************************

* ctrlThrFxn

******************************************************************************/

void *ctrlThrFxn(void *arg)

{

Engine_Handle hEngine = NULL;

unsigned int initMask = 0;

CtrlEnv *envp = (CtrlEnv *) arg;

int osdTransparency = OSD_TRANSPARENCY;

void *status = THREAD_SUCCESS;

int displayIdx = 0;

int workingIdx = 1;

char *osdDisplays[NUM_BUFS];

enum msp430lib_keycode key;

UIParams uiParams;

int osdFd;

int timeSpent;

/* Initialize the OSD */

osdFd = osdInit(osdDisplays);

if (osdFd == FAILURE) {

cleanup(THREAD_FAILURE);

}

DBG("OSD successfully initialized\n");

initMask |= OSDINITIALIZED;

/* Initialize the OSD transparency */

if (setOsdTransparency(osdTransparency) == FAILURE) {

cleanup(THREAD_FAILURE);

}

DBG("OSD transparency initialized\n");

/* Reset, load, and start DSP Engine */

hEngine = Engine_open(ENGINE_NAME, NULL, NULL);

if (hEngine == NULL) {

ERR("Failed to open codec engine %s\n", ENGINE_NAME);

cleanup(THREAD_FAILURE);

}

DBG("Codec Engine opened in control thread\n");

initMask |= ENGINEOPENED;

/* Initialize the MSP430 library to be able to receive IR commands */

if (msp430lib_init() == MSP430LIB_FAILURE) {

ERR("Failed to initialize msp430lib.\n");

cleanup(THREAD_FAILURE);

}

DBG("MSP430 library initialized\n");

initMask |= MSP430LIBINITIALIZED;

/* Create the user interface */

uiParams.imageWidth = envp->imageWidth;

uiParams.imageHeight = envp->imageHeight;

uiParams.passThrough = envp->passThrough;

uiParams.osdDisplays = osdDisplays;

if (uiCreate(&uiParams) == FAILURE) {

cleanup(THREAD_FAILURE);

}

DBG("User interface created\n");

initMask |= UICREATED;

/* Signal that initialization is done and wait for other threads */

Rendezvous_meet(envp->hRendezvous);

/* Initialize the ARM cpu load */

getArmCpuLoad(NULL, NULL);

if (envp->keyboard) {

printf(COMMAND_PROMPT);

fflush(stdout);

}

DBG("Entering control main loop.\n");

while (!gblGetQuit()) {

/* Draw the cpu load on the OSD */

drawDynamicData(hEngine, osdFd, &timeSpent, &displayIdx, &workingIdx);

/* Has the demo timelimit been hit? */

if (envp->time > FOREVER && timeSpent >= envp->time) {

breakLoop(THREAD_SUCCESS);

}

/* See if an IR remote key has been pressed */

if (msp430lib_get_ir_key(&key) == MSP430LIB_FAILURE) {

DBG("Failed to get IR value.\n");

}

if (envp->keyboard) {

if (getKbdCommand(&key) == FAILURE) {

breakLoop(THREAD_FAILURE);

}

}

/* If an IR key had been pressed, service it */

if (key != 0) {

if (keyAction(key, displayIdx, &osdTransparency) == FAILURE) {

breakLoop(THREAD_FAILURE);

}

}

usleep(REMOTECONTROLLATENCY);

}

cleanup:

/* Make sure the other threads aren't waiting for init to complete */

Rendezvous_force(envp->hRendezvous);

/* Clean up the control thread */

if (initMask & UICREATED) {

uiDelete();

}

if (initMask & MSP430LIBINITIALIZED) {

msp430lib_exit();

}

if (initMask & ENGINEOPENED) {

Engine_close(hEngine);

}

if (initMask & OSDINITIALIZED) {

osdExit(osdFd);

}

return status;

}

/*

* video.h

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

#ifndef _VIDEO_H

#define _VIDEO_H

#include <rendezvous.h>

typedef struct VideoEnv {

Rendezvous_Handle hRendezvous;

int videoBitRate;

int svideoInput;

int passThrough;

int imageWidth;

int imageHeight;

} VideoEnv;

extern void *videoThrFxn(void *arg);

#endif /* _VIDEO_H */

/*

* video.c

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

/* Standard Linux headers */

#include <stdio.h>

#include <fcntl.h>

#include <errno.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <pthread.h>

#include <sys/mman.h>

#include <sys/ioctl.h>

#include <asm/types.h>

#include <linux/videodev2.h>

/* Davinci specific kernel headers */

#include <video/davincifb.h>

#include <media/davinci_vpfe.h>

#include <media/tvp5146.h>

/* Codec Engine headers */

#include <xdc/std.h>

#include <ti/sdo/ce/Engine.h>

#include <ti/sdo/ce/osal/Memory.h>

#include <ti/sdo/ce/video/viddec.h>

#include <ti/sdo/ce/video/videnc.h>

/* Demo headers */

#include <rendezvous.h>

#include <fifoutil.h>

#include "encodedecode.h"

#include "display.h"

#include "video.h"

#include "display.h"

/* The levels of initialization */

#define INFIFOOPENED 0x1

#define OUTFIFOOPENED 0x2

#define DISPLAYTHREADCREATED 0x4

#define CAPTUREDEVICEINITIALIZED 0x8

#define ENGINEOPENED 0x10

#define VIDEODECODERCREATED 0x20

#define VIDEOENCODERCREATED 0x40

#define ENCODEDBUFFERALLOCATED 0x80

#define DISPLAYBUFFERSALLOCATED 0x100

/* Macro for clearing structures */

#define CLEAR(x) memset (&(x), 0, sizeof (x))

/* Number of buffers between video thread and display thread */

#define DISPLAY_BUFFERS 3

/* Black color in UYVY format */

#define UYVY_BLACK 0x10801080

/* Triple buffering for the capture driver */

#define NUM_BUFS 3

/* Work around a bug in the algorithms (using scratch in init) */

#define ALGO_INIT_WORKAROUND

/* Structure containing statistics about the frames in a clip */

typedef struct FrameStats {

int framesRejected;

int iFrames;

int pFrames;

int bFrames;

int idrFrames;

} FrameStats;

/* Describes a capture frame buffer */

typedef struct VideoBuffer {

void *start;

size_t length;

} VideoBuffer;

/* Local function prototypes */

static int videoDecodeAlgCreate(Engine_Handle hEngine,

VIDDEC_Handle *hDecodePtr, int *encBufSizePtr,

int width, int height);

static int videoEncodeAlgCreate(Engine_Handle hEngine,

VIDENC_Handle *hEncodePtr,

int width, int height, int bitrate);

static int encodeVideoBuffer(VIDENC_Handle hEncode, char *inBuf, int inBufSize,

char *outBuf, int outBufMaxSize, int *outBufSize);

static int decodeVideoBuffer(VIDDEC_Handle hDecode, char *inBuf,

int inBufSize, char *outBuf,

int outBufSize, FrameStats *stats);

static int initCaptureDevice(VideoBuffer **vidBufsPtr, int *numVidBufsPtr,

int svideoInput, int captureWidth,

int captureHeight);

static void cleanupCaptureDevice(int fd, VideoBuffer *vidBufs, int numVidBufs);

/******************************************************************************

* videoDecodeAlgCreate

******************************************************************************/

static int videoDecodeAlgCreate(Engine_Handle hEngine,

VIDDEC_Handle *hDecodePtr, int *encBufSizePtr,

int width, int height)

{

#ifndef ALGO_INIT_WORKAROUND

VIDDEC_Status decStatus;

XDAS_Int32 status;

VIDDEC_DynamicParams dynamicParams;

#endif

VIDDEC_Params params;

VIDDEC_Handle hDecode;

params.size = sizeof(VIDDEC_Params);

params.maxFrameRate = 0;

params.maxBitRate = 0;

params.dataEndianness = XDM_BYTE;

params.forceChromaFormat = XDM_YUV_422ILE;

params.maxHeight = D1_HEIGHT;

params.maxWidth = D1_WIDTH;

/* Create H.264 decoder instance */

hDecode = VIDDEC_create(hEngine, "h264dec", &params);

if (hDecode == NULL) {

ERR("Can't open decode algorithm: %s\n", "h264");

return FAILURE;

}

#ifndef ALGO_INIT_WORKAROUND

/* Get buffer information from video decoder */

decStatus.size = sizeof(VIDDEC_Status);

dynamicParams.size = sizeof(VIDDEC_DynamicParams);

status = VIDDEC_control(hDecode, XDM_GETBUFINFO, &dynamicParams,

&decStatus);

if (status != VIDDEC_EOK) {

ERR("XDM_GETBUFINFO failed, status=%ld\n", status);

return FAILURE;

}

*encBufSizePtr = decStatus.bufInfo.minInBufSize[0];

#else

/* Hardcoding encoded buffer size to work around codec issue */

*encBufSizePtr = 1658880;

#endif

*hDecodePtr = hDecode;

return SUCCESS;

}

/******************************************************************************

* videoEncodeAlgCreate

******************************************************************************/

static int videoEncodeAlgCreate(Engine_Handle hEngine,

VIDENC_Handle *hEncodePtr,

int width, int height, int bitrate)

{

VIDENC_DynamicParams dynamicParams;

VIDENC_Status encStatus;

VIDENC_Params params;

VIDENC_Handle hEncode;

XDAS_Int32 status;

params.size = sizeof(VIDENC_Params);

params.encodingPreset = XDM_DEFAULT;

params.rateControlPreset = bitrate < 0 ? IVIDEO_NONE : IVIDEO_LOW_DELAY;

params.maxFrameRate = gblGetYFactor() == NTSCSTD ? 30000 : 25000;

params.maxBitRate = bitrate < 0 ? 0 : bitrate;

params.dataEndianness = XDM_BYTE;

params.maxInterFrameInterval = 0;

params.inputChromaFormat = XDM_YUV_422ILE;

params.inputContentType = IVIDEO_PROGRESSIVE;

params.maxHeight = D1_HEIGHT;

params.maxWidth = D1_WIDTH;

/* Create H.264 encoder instance */

hEncode = VIDENC_create(hEngine, "h264enc", &params);

if (hEncode == NULL) {

ERR("Can't open encode algorithm: %s\n", "h264");

return FAILURE;

}

dynamicParams.size = sizeof(VIDENC_DynamicParams);

dynamicParams.inputHeight = height;

dynamicParams.inputWidth = width;

dynamicParams.targetBitRate = bitrate < 0 ? 0 : bitrate;

dynamicParams.intraFrameInterval = 30;

dynamicParams.generateHeader = XDM_ENCODE_AU;

dynamicParams.captureWidth = 0;

dynamicParams.forceIFrame = 0;

if (gblGetYFactor() == NTSCSTD) {

dynamicParams.targetFrameRate = 30000;

dynamicParams.refFrameRate = 30000;

}

else {

dynamicParams.targetFrameRate = 25000;

dynamicParams.refFrameRate = 25000;

}

/* Set video encoder dynamic parameters */

encStatus.size = sizeof(VIDENC_Status);

status = VIDENC_control(hEncode, XDM_SETPARAMS, &dynamicParams,

&encStatus);

if (status != VIDENC_EOK) {

ERR("XDM_SETPARAMS failed, status=%ld\n", status);

return FAILURE;

}

*hEncodePtr = hEncode;

return SUCCESS;

}

/******************************************************************************

* encodeVideoBuffer

******************************************************************************/

static int encodeVideoBuffer(VIDENC_Handle hEncode, char *inBuf, int inBufSize,

char *outBuf, int outBufMaxSize, int *outBufSize)

{

XDAS_Int32 inBufSizeArray[1];

XDAS_Int32 outBufSizeArray[1];

XDAS_Int32 status;

XDM_BufDesc inBufDesc;

XDM_BufDesc outBufDesc;

VIDENC_InArgs inArgs;

VIDENC_OutArgs outArgs;

inBufSizeArray[0] = inBufSize;

outBufSizeArray[0] = outBufMaxSize;

inBufDesc.numBufs = 1;

inBufDesc.bufSizes = inBufSizeArray;

inBufDesc.bufs = (XDAS_Int8 **) &inBuf;

outBufDesc.numBufs = 1;

outBufDesc.bufSizes = outBufSizeArray;

outBufDesc.bufs = (XDAS_Int8 **) &outBuf;

inArgs.size = sizeof(VIDENC_InArgs);

outArgs.size = sizeof(VIDENC_OutArgs);

/* Encode video buffer */

status = VIDENC_process(hEncode, &inBufDesc, &outBufDesc,

&inArgs, &outArgs);

if (status != VIDENC_EOK) {

ERR("VIDENC_process() failed with a fatal error (%ld ext: %#lx)\n",

status, outArgs.extendedError);

return FAILURE;

}

*outBufSize = outArgs.bytesGenerated;

return SUCCESS;

}

/******************************************************************************

* decodeVideoBuffer

******************************************************************************/

static int decodeVideoBuffer(VIDDEC_Handle hDecode, char *inBuf,

int inBufSize, char *outBuf,

int outBufSize, FrameStats *stats)

{

VIDDEC_DynamicParams dynamicParams;

VIDDEC_InArgs inArgs;

VIDDEC_OutArgs outArgs;

VIDDEC_Status decStatus;

XDM_BufDesc inBufDesc;

XDM_BufDesc outBufDesc;

XDAS_Int32 inBufSizeArray[1];

XDAS_Int32 outBufSizeArray[1];

XDAS_Int32 status;

dynamicParams.size = sizeof(VIDDEC_DynamicParams);

decStatus.size = sizeof(VIDDEC_Status);

inBufSizeArray[0] = inBufSize;

outBufSizeArray[0] = outBufSize;

inBufDesc.numBufs = 1;

inBufDesc.bufSizes = inBufSizeArray;

inBufDesc.bufs = (XDAS_Int8 **) &inBuf;

outBufDesc.numBufs = 1;

outBufDesc.bufSizes = outBufSizeArray;

outBufDesc.bufs = (XDAS_Int8 **) &outBuf;

inArgs.size = sizeof(VIDDEC_InArgs);

inArgs.numBytes = inBufSize;

inArgs.inputID = 0;

outArgs.size = sizeof(VIDDEC_OutArgs);

/* Decode video buffer */

status = VIDDEC_process(hDecode, &inBufDesc, &outBufDesc,

&inArgs, &outArgs);

if (status != VIDDEC_EOK) {

if (status == VIDDEC_ERUNTIME ||

XDM_ISFATALERROR(outArgs.extendedError)) {

ERR("VIDDEC_process() failed with a fatal error (%ld ext: %#lx\n",

status, outArgs.extendedError);

return FAILURE;

}

else {

stats->framesRejected++;

return SUCCESS;

}

}

switch (outArgs.decodedFrameType) {

case IVIDEO_I_FRAME:

stats->iFrames++;

break;

case IVIDEO_P_FRAME:

stats->pFrames++;

break;

case IVIDEO_B_FRAME:

stats->bFrames++;

break;

case IVIDEO_IDR_FRAME:

stats->idrFrames++;

break;

}

return SUCCESS;

}

/******************************************************************************

* initCaptureDevice

******************************************************************************/

static int initCaptureDevice(VideoBuffer **vidBufsPtr, int *numVidBufsPtr,

int svideoInput, int captureWidth,

int captureHeight)

{

struct v4l2_requestbuffers req;

struct v4l2_capability cap;

struct v4l2_cropcap cropCap;

struct v4l2_crop crop;

struct v4l2_format fmt;

struct v4l2_buffer buf;

v4l2_std_id std;

enum v4l2_buf_type type;

int input;

int fd;

int ret;

VideoBuffer *buffers;

int numBufs;

/* Open video capture device */

fd = open(V4L2_DEVICE, O_RDWR | O_NONBLOCK, 0);

if (fd == -1) {

ERR("Cannot open %s (%s)\n", V4L2_DEVICE, strerror(errno));

return FAILURE;

}

/* Select the video input */

if (svideoInput == TRUE) {

input = TVP5146_AMUX_SVIDEO;

}

else {

input = TVP5146_AMUX_COMPOSITE;

}

if (ioctl(fd, VIDIOC_S_INPUT, &input) == -1) {

ERR("Failed to set video input to %d\n", input);

return FAILURE;

}

DBG("Set the capture input to id %d\n", input);

/* Query for capture device capabilities */

if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {

if (errno == EINVAL) {

ERR("%s is no V4L2 device\n", V4L2_DEVICE);

return FAILURE;

}

ERR("Failed VIDIOC_QUERYCAP on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {

ERR("%s is no video capture device\n", V4L2_DEVICE);

return FAILURE;

}

if (!(cap.capabilities & V4L2_CAP_STREAMING)) {

ERR("%s does not support streaming i/o\n", V4L2_DEVICE);

return FAILURE;

}

cropCap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (ioctl(fd, VIDIOC_CROPCAP, &cropCap) == -1) {

ERR("VIDIOC_CROPCAP failed %d, %s\n", errno, strerror(errno));

return FAILURE;

}

/* Auto detect PAL or NTSC using the capture driver as sanity check */

std = VPFE_STD_AUTO;

if(ioctl(fd, VIDIOC_S_STD, &std) == -1) {

ERR("VIDIOC_S_STD (auto) failed on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

do {

ret = ioctl(fd, VIDIOC_QUERYSTD, &std);

} while (ret == -1 && errno == EAGAIN);

if (ret == -1) {

ERR("VIDIOC_QUERYSTD failed on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

switch (std) {

case V4L2_STD_NTSC:

DBG("NTSC camera detected\n");

if (gblGetYFactor() == PALSTD) {

ERR("NTSC camera connected but PAL selected.\n");

return FAILURE;

}

break;

case V4L2_STD_PAL:

DBG("PAL camera detected\n");

if (gblGetYFactor() == NTSCSTD) {

ERR("PAL camera connected but NTSC selected.\n");

return FAILURE;

}

break;

default:

ERR("Camera (%s) using unsupported video standard\n", V4L2_DEVICE);

return FAILURE;

}

/* Use either NTSC or PAL depending on display kernel parameter */

std = gblGetYFactor() == NTSCSTD ? V4L2_STD_NTSC : V4L2_STD_PAL;

if(ioctl(fd, VIDIOC_S_STD, &std) == -1) {

ERR("VIDIOC_S_STD failed on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

/* Set the video capture image format */

CLEAR(fmt);

fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;

fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

fmt.fmt.pix.width = D1_WIDTH;

fmt.fmt.pix.height = D1_HEIGHT;

/* Set the video capture format */

if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {

ERR("VIDIOC_S_FMT failed on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

crop.c.left = D1_WIDTH / 2 - captureWidth / 2;

crop.c.top = D1_HEIGHT / 2 - captureHeight / 2;

crop.c.width = captureWidth;

crop.c.height = captureHeight;

/* Crop the image depending on requested image size */

if (ioctl(fd, VIDIOC_S_CROP, &crop) == -1) {

ERR("VIDIOC_S_CROP failed %d, %s\n", errno, strerror(errno));

return FAILURE;

}

printf("Capturing %dx%d video (cropped to %dx%d)\n",

fmt.fmt.pix.width, fmt.fmt.pix.height, crop.c.width, crop.c.height);

CLEAR(req);

req.count = NUM_BUFS;

req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

req.memory = V4L2_MEMORY_MMAP;

/* Allocate buffers in the capture device driver */

if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {

ERR("VIDIOC_REQBUFS failed on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

DBG("%d capture buffers were successfully allocated.\n", req.count);

if (req.count < NUM_BUFS) {

ERR("Insufficient buffer memory on %s\n", V4L2_DEVICE);

return FAILURE;

}

buffers = calloc(req.count, sizeof(*buffers));

if (!buffers) {

ERR("Failed to allocate memory for capture buffer structs.\n");

return FAILURE;

}

/* Map the allocated buffers to user space */

for (numBufs = 0; numBufs < req.count; numBufs++) {

CLEAR(buf);

buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

buf.memory = V4L2_MEMORY_MMAP;

buf.index = numBufs;

if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {

ERR("Failed VIDIOC_QUERYBUF on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

buffers[numBufs].length = buf.length;

buffers[numBufs].start = mmap(NULL,

buf.length,

PROT_READ | PROT_WRITE,

MAP_SHARED,

fd, buf.m.offset);

if (buffers[numBufs].start == MAP_FAILED) {

ERR("Failed to mmap buffer on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

DBG("Capture buffer %d mapped to address %#lx\n", numBufs,

(unsigned long) buffers[numBufs].start);

if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {

ERR("VIODIOC_QBUF failed on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

}

/* Start the video streaming */

type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {

ERR("VIDIOC_STREAMON failed on %s (%s)\n", V4L2_DEVICE,

strerror(errno));

return FAILURE;

}

*vidBufsPtr = buffers;

*numVidBufsPtr = numBufs;

return fd;

}

/******************************************************************************

* cleanupCaptureDevice

******************************************************************************/

static void cleanupCaptureDevice(int fd, VideoBuffer *vidBufs, int numVidBufs)

{

enum v4l2_buf_type type;

unsigned int i;

/* Shut off the video capture */

type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {

ERR("VIDIOC_STREAMOFF failed (%s)\n", strerror(errno));

}

/* Unmap the capture frame buffers from user space */

for (i = 0; i < numVidBufs; ++i) {

if (munmap(vidBufs[i].start, vidBufs[i].length) == -1) {

ERR("Failed to unmap capture buffer %d\n", i);

}

}

free(vidBufs);

if (close(fd) == -1) {

ERR("Failed to close capture device (%s)\n", strerror(errno));

}

}

/******************************************************************************

* videoThrFxn

******************************************************************************/

void *videoThrFxn(void *arg)

{

BufferElement flush = { DISPLAY_FLUSH };

FrameStats frameStats = { 0, 0, 0, 0, 0 };

Engine_Handle hEngine = NULL;

unsigned int initMask = 0;

VideoEnv *envp = (VideoEnv *) arg;

void *status = THREAD_SUCCESS;

char *encBuf = NULL;

int captureFd = 0;

int numDisplayBufs = 0;

BufferElement bufferElements[DISPLAY_BUFFERS];

struct sched_param schedParam;

VIDDEC_Handle hDecode;

VIDENC_Handle hEncode;

struct v4l2_buffer v4l2buf;

DisplayEnv displayEnv;

unsigned int numVidBufs;

VideoBuffer *vidBufs;

void *ret;

int encBufSize;

int frameSize;

int imageSize;

pthread_t displayThread;

pthread_attr_t attr;

BufferElement e;

int i;

imageSize = envp->imageWidth * envp->imageHeight * SCREEN_BPP / 8;

/* Open the input fifo */

if (FifoUtil_open(&displayEnv.inFifo,

sizeof(BufferElement)) == FIFOUTIL_FAILURE) {

ERR("Failed to open input fifo\n");

cleanup(THREAD_FAILURE);

}

initMask |= INFIFOOPENED;

/* Open the output fifo */

if (FifoUtil_open(&displayEnv.outFifo,

sizeof(BufferElement)) == FIFOUTIL_FAILURE) {

ERR("Failed to open output fifo\n");

cleanup(THREAD_FAILURE);

}

initMask |= OUTFIFOOPENED;

/* Initialize the priming synchronization mutex */

pthread_mutex_init(&displayEnv.prime, NULL);

/* Initialize the thread attributes */

if (pthread_attr_init(&attr)) {

ERR("Failed to initialize thread attrs\n");

cleanup(THREAD_FAILURE);

}

/* Force the thread to use custom scheduling attributes */

if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) {

ERR("Failed to set schedule inheritance attribute\n");

cleanup(THREAD_FAILURE);

}

/* Set the thread to be fifo real time scheduled */

if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {

ERR("Failed to set FIFO scheduling policy\n");

cleanup(THREAD_FAILURE);

}

/* Set the thread priority */

schedParam.sched_priority = sched_get_priority_max(SCHED_FIFO);

if (pthread_attr_setschedparam(&attr, &schedParam)) {

ERR("Failed to set scheduler parameters\n");

cleanup(THREAD_FAILURE);

}

/* Create the thread */

displayEnv.hRendezvous = envp->hRendezvous;

if (pthread_create(&displayThread, &attr, displayThrFxn, &displayEnv)) {

ERR("Failed to create display thread\n");

cleanup(THREAD_FAILURE);

}

initMask |= DISPLAYTHREADCREATED;

/* Initialize the video capture device */

captureFd = initCaptureDevice(&vidBufs, &numVidBufs, envp->svideoInput,

envp->imageWidth, envp->imageHeight);

if (captureFd == FAILURE) {

cleanup(THREAD_FAILURE);

}

DBG("Video capture initialized and started\n");

initMask |= CAPTUREDEVICEINITIALIZED;

if (!envp->passThrough) {

/* Reset, load, and start DSP Engine */

hEngine = Engine_open(ENGINE_NAME, NULL, NULL);

if (hEngine == NULL) {

ERR("Failed to open codec engine %s\n", ENGINE_NAME);

cleanup(THREAD_FAILURE);

}

DBG("Codec Engine opened in video thread\n");

initMask |= ENGINEOPENED;

/* Allocate and initialize video decoder on the engine */

if (videoDecodeAlgCreate(hEngine, &hDecode, &encBufSize,

envp->imageWidth,

envp->imageHeight) == FAILURE) {

cleanup(THREAD_FAILURE);

}

DBG("Video decoder created\n");

initMask |= VIDEODECODERCREATED;

/* Allocate and initialize video encoder on the engine */

if (videoEncodeAlgCreate(hEngine, &hEncode,

envp->imageWidth, envp->imageHeight,

envp->videoBitRate) == FAILURE) {

cleanup(THREAD_FAILURE);

}

DBG("Video encoder created\n");

initMask |= VIDEOENCODERCREATED;

}

/* Allocate intermediate buffer (for encoded data) */

encBuf = (char *) Memory_contigAlloc(encBufSize,

Memory_DEFAULTALIGNMENT);

if (encBuf == NULL) {

ERR("Failed to allocate contiguous memory block.\n");

cleanup(THREAD_FAILURE);

}

DBG("Contiguous buffer allocated at physical address %#lx\n",

Memory_getPhysicalAddress(encBuf));

initMask |= ENCODEDBUFFERALLOCATED;

memset(bufferElements, 0, sizeof(BufferElement) * DISPLAY_BUFFERS);

for (i=0; i < DISPLAY_BUFFERS; i++) {

bufferElements[i].frameBuffer = (char *)

Memory_contigAlloc(imageSize, Memory_DEFAULTALIGNMENT);

if (bufferElements[i].frameBuffer == NULL) {

ERR("Failed to allocate contiguous memory block.\n");

cleanup(THREAD_FAILURE);

}

DBG("Contiguous buffer allocated at physical address 0x%lx\n",

Memory_getPhysicalAddress(bufferElements[i].frameBuffer));

}

initMask |= DISPLAYBUFFERSALLOCATED;

/* Signal that initialization is done and wait for other threads */

Rendezvous_meet(envp->hRendezvous);

/* Lock the display priming mutex */

pthread_mutex_lock(&displayEnv.prime);

/* Tell the display thread that we are priming */

e.id = DISPLAY_PRIME;

if (FifoUtil_put(&displayEnv.outFifo, &e) == FIFOUTIL_FAILURE) {

ERR("Failed to put buffer to output fifo\n");

pthread_mutex_unlock(&displayEnv.prime);

cleanup(THREAD_FAILURE);

}

/* Prime the display thread */

for (i=0; i < DISPLAY_BUFFERS; i++) {

CLEAR(v4l2buf);

v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

v4l2buf.memory = V4L2_MEMORY_MMAP;

/* Dequeue a frame buffer from the capture device driver */

if (ioctl(captureFd, VIDIOC_DQBUF, &v4l2buf) == -1) {

ERR("VIDIOC_DQBUF failed (%s)\n", strerror(errno));

breakLoop(THREAD_FAILURE);

}

if (envp->passThrough) {

/* Copy the buffer without processing */

memcpy(bufferElements[i].frameBuffer, vidBufs[v4l2buf.index].start,

imageSize);

/* Issue capture buffer back to capture device driver */

if (ioctl(captureFd, VIDIOC_QBUF, &v4l2buf) == -1) {

ERR("VIDIOC_QBUF failed (%s)\n", strerror(errno));

breakLoop(THREAD_FAILURE);

}

}

else {

/* Encode the buffer using H.264 */

if (encodeVideoBuffer(hEncode, vidBufs[v4l2buf.index].start,

imageSize, encBuf, encBufSize,

&frameSize) == FAILURE) {

breakLoop(THREAD_FAILURE);

}

/* Issue capture buffer back to capture device driver */

if (ioctl(captureFd, VIDIOC_QBUF, &v4l2buf) == -1) {

ERR("VIDIOC_QBUF failed (%s)\n", strerror(errno));

breakLoop(THREAD_FAILURE);

}

/* Decode the buffer using H.264 */

if (decodeVideoBuffer(hDecode, encBuf, frameSize,

bufferElements[i].frameBuffer, imageSize,

&frameStats) == FAILURE) {

breakLoop(THREAD_FAILURE);

}

}

bufferElements[i].width = envp->imageWidth;

bufferElements[i].height = envp->imageHeight;

/* Send frame buffer to display thread */

if (FifoUtil_put(&displayEnv.outFifo,

&bufferElements[i]) == FIFOUTIL_FAILURE) {

ERR("Failed to put buffer in output fifo\n");

breakLoop(THREAD_FAILURE);

}

numDisplayBufs++;

}

/* Release the display thread */

pthread_mutex_unlock(&displayEnv.prime);

DBG("Entering video main loop.\n");

while (!gblGetQuit()) {

/* Receive a buffer with a displayed frame from the display thread */

if (FifoUtil_get(&displayEnv.inFifo, &e) == FIFOUTIL_FAILURE) {

ERR("Failed to get buffer from input fifo\n");

breakLoop(THREAD_FAILURE);

}

numDisplayBufs--;

/* Is the display thread flushing the pipe? */

if (e.id == DISPLAY_FLUSH) {

breakLoop(THREAD_SUCCESS);

}

CLEAR(v4l2buf);

v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

v4l2buf.memory = V4L2_MEMORY_MMAP;

/* Dequeue a frame buffer from the capture device driver */

if (ioctl(captureFd, VIDIOC_DQBUF, &v4l2buf) == -1) {

ERR("VIDIOC_DQBUF failed (%s)\n", strerror(errno));

breakLoop(THREAD_FAILURE);

}

if (envp->passThrough) {

/* Copy the buffer without processing */

memcpy(e.frameBuffer, vidBufs[v4l2buf.index].start, imageSize);

/* Issue capture buffer back to capture device driver */

if (ioctl(captureFd, VIDIOC_QBUF, &v4l2buf) == -1) {

ERR("VIDIOC_QBUF failed (%s)\n", strerror(errno));

breakLoop(THREAD_FAILURE);

}

}

else {

/* Encode the buffer using H.264 */

if (encodeVideoBuffer(hEncode, vidBufs[v4l2buf.index].start,

imageSize, encBuf, encBufSize,

&frameSize) == FAILURE) {

breakLoop(THREAD_FAILURE);

}

/* Issue capture buffer back to capture device driver */

if (ioctl(captureFd, VIDIOC_QBUF, &v4l2buf) == -1) {

ERR("VIDIOC_QBUF failed (%s)\n", strerror(errno));

breakLoop(THREAD_FAILURE);

}

/* Decode the buffer using H.264 */

if (decodeVideoBuffer(hDecode, encBuf, frameSize, e.frameBuffer,

imageSize, &frameStats) == FAILURE) {

breakLoop(THREAD_FAILURE);

}

}

/* Send frame buffer to display thread */

if (FifoUtil_put(&displayEnv.outFifo, &e) == FIFOUTIL_FAILURE) {

ERR("Failed to put buffer in output fifo\n");

breakLoop(THREAD_FAILURE);

}

numDisplayBufs++;

/* Increment statistics for OSD display */

gblIncVideoBytesEncoded(frameSize);

}

printf("\nTotal I-frames: %d, P-frames: %d, B-frames: %d, IDR-frames: %d "

"rejected: %d\n",

frameStats.iFrames, frameStats.pFrames, frameStats.bFrames,

frameStats.idrFrames, frameStats.framesRejected);

cleanup:

/* Make sure the other threads aren't waiting for init to complete */

Rendezvous_force(envp->hRendezvous);

/* Make sure the video thread isn't stuck in FifoUtil_get() */

FifoUtil_put(&displayEnv.outFifo, &flush);

/* Drain the display thread */

while (numDisplayBufs-- > 0 && e.id != DISPLAY_FLUSH) {

if (FifoUtil_get(&displayEnv.inFifo, &e) == FIFOUTIL_FAILURE) {

ERR("Failed to get buffer from input fifo\n");

break;

}

}

/* Clean up the video thread */

if (initMask & DISPLAYBUFFERSALLOCATED) {

for (i=0; i < DISPLAY_BUFFERS; i++) {

if (bufferElements[i].frameBuffer) {

Memory_contigFree(bufferElements[i].frameBuffer,

imageSize);

}

}

}

if (initMask & ENCODEDBUFFERALLOCATED) {

Memory_contigFree(encBuf, encBufSize);

}

if (initMask & VIDEOENCODERCREATED) {

VIDENC_delete(hEncode);

}

if (initMask & VIDEODECODERCREATED) {

VIDDEC_delete(hDecode);

}

if (initMask & ENGINEOPENED) {

Engine_close(hEngine);

}

if (initMask & CAPTUREDEVICEINITIALIZED) {

cleanupCaptureDevice(captureFd, vidBufs, numVidBufs);

}

if (initMask & DISPLAYTHREADCREATED) {

if (pthread_join(displayThread, &ret) == 0) {

status = ret;

}

pthread_mutex_destroy(&displayEnv.prime);

}

if (initMask & OUTFIFOOPENED) {

FifoUtil_close(&displayEnv.outFifo);

}

if (initMask & INFIFOOPENED) {

FifoUtil_close(&displayEnv.inFifo);

}

return status;

}

/*

* display.h

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

#ifndef _DISPLAY_H

#define _DISPLAY_H

#include <pthread.h>

#include <fifoutil.h>

#include <rendezvous.h>

/* Display thread commands */

#define DISPLAY_FLUSH -1

#define DISPLAY_PRIME -2

typedef struct BufferElement {

int id;

int width;

int height;

char *frameBuffer;

} BufferElement;

typedef struct DisplayEnv {

Rendezvous_Handle hRendezvous;

FifoUtil_Obj outFifo;

FifoUtil_Obj inFifo;

pthread_mutex_t prime;

} DisplayEnv;

extern void *displayThrFxn(void *arg);

#endif /* _DISPLAY_H */

/*

* display.c

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

/* Standard Linux headers */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#include <unistd.h>

#include <errno.h>

#include <sys/mman.h>

#include <sys/ioctl.h>

#include <pthread.h>

#include <linux/fb.h>

/* Davinci specific kernel headers */

#include <video/davincifb.h>

/* Demo headers */

#include <rendezvous.h>

#include <fifoutil.h>

#include "encodedecode.h"

#include "display.h"

/* Video display is triple buffered */

#define NUM_BUFS 3

/* Black color in UYVY format */

#define UYVY_BLACK 0x10801080

/* The levels of initialization */

#define DISPLAYDEVICEINITIALIZED 0x1

static int waitForVsync(int fd);

static int flipDisplayBuffers(int fd, int displayIdx);

static int initDisplayDevice(char *displays[]);

static void cleanupDisplayDevice(int fd, char *displays[]);

/******************************************************************************

* waitForVsync

******************************************************************************/

static int waitForVsync(int fd)

{

int dummy;

/* Wait for vertical sync */

if (ioctl(fd, FBIO_WAITFORVSYNC, &dummy) == -1) {

ERR("Failed FBIO_WAITFORVSYNC (%s)\n", strerror(errno));

return FAILURE;

}

return SUCCESS;

}

/******************************************************************************

* flipDisplayBuffers

******************************************************************************/

static int flipDisplayBuffers(int fd, int displayIdx)

{

struct fb_var_screeninfo vInfo;

if (ioctl(fd, FBIOGET_VSCREENINFO, &vInfo) == -1) {

ERR("Failed FBIOGET_VSCREENINFO (%s)\n", strerror(errno));

return FAILURE;

}

vInfo.yoffset = vInfo.yres * displayIdx;

/* Swap the working buffer for the displayed buffer */

if (ioctl(fd, FBIOPAN_DISPLAY, &vInfo) == -1) {

ERR("Failed FBIOPAN_DISPLAY (%s)\n", strerror(errno));

return FAILURE;

}

return SUCCESS;

}

/******************************************************************************

* initDisplayDevice

******************************************************************************/

static int initDisplayDevice(char *displays[])

{

struct fb_var_screeninfo varInfo;

unsigned int *buf;

int fd;

int i;

/* Open video display device */

fd = open(FBVID_DEVICE, O_RDWR);

if (fd == -1) {

ERR("Failed to open fb device %s (%s)\n", FBVID_DEVICE,

strerror(errno));

return FAILURE;

}

if (ioctl(fd, FBIOGET_VSCREENINFO, &varInfo) == -1) {

ERR("Failed FBIOGET_VSCREENINFO on %s (%s)\n", FBVID_DEVICE,

strerror(errno));

return FAILURE;

}

varInfo.xres = D1_WIDTH;

varInfo.yres = D1_HEIGHT;

varInfo.bits_per_pixel = SCREEN_BPP;

/* Set video display format */

if (ioctl(fd, FBIOPUT_VSCREENINFO, &varInfo) == -1) {

ERR("Failed FBIOPUT_VSCREENINFO on %s (%s)\n", FBVID_DEVICE,

strerror(errno));

return FAILURE;

}

if (varInfo.xres != D1_WIDTH ||

varInfo.yres != D1_HEIGHT ||

varInfo.bits_per_pixel != SCREEN_BPP) {

ERR("Failed to get the requested screen size: %dx%d at %d bpp\n",

D1_WIDTH, D1_HEIGHT, SCREEN_BPP);

return FAILURE;

}

/* Map the video buffers to user space */

displays[0] = (char *) mmap (NULL,

D1_FRAME_SIZE * NUM_BUFS,

PROT_READ | PROT_WRITE,

MAP_SHARED,

fd, 0);

if (displays[0] == MAP_FAILED) {

ERR("Failed mmap on %s (%s)\n", FBVID_DEVICE, strerror(errno));

return FAILURE;

}

/* Clear the video buffers */

buf = (unsigned int *) displays[0];

for (i=0; i<D1_FRAME_SIZE * NUM_BUFS / sizeof(unsigned int); i++) {

buf[i] = UYVY_BLACK;

}

DBG("Display buffer %d mapped to address %#lx\n", 0,

(unsigned long) displays[0]);

for (i=0; i<NUM_BUFS-1; i++) {

displays[i+1] = displays[i] + D1_FRAME_SIZE;

DBG("Display buffer %d mapped to address %#lx\n", i+1,

(unsigned long) displays[i+1]);

}

return fd;

}

/******************************************************************************

* cleanupDisplayDevice

******************************************************************************/

static void cleanupDisplayDevice(int fd, char *displays[])

{

munmap(displays[0], D1_FRAME_SIZE * NUM_BUFS);

close(fd);

}

/******************************************************************************

* copyFrame

******************************************************************************/

static void copyFrame(char *dst, char *src, int width, int height)

{

int lineWidth = width * SCREEN_BPP / 8;

int xoffset = (D1_LINE_WIDTH - lineWidth) / 2;

int ystart = ( (D1_HEIGHT - height) / 2 ) & ~1;

int y;

/* Truncate if frame buffer higher than display buffer */

if (ystart < 0) {

ystart = 0;

}

dst += ystart * D1_LINE_WIDTH + xoffset;

/* Copy the frame into the middle of the screen */

for (y=0; y < height && y < D1_HEIGHT; y++) {

memcpy(dst, src, lineWidth);

dst += D1_LINE_WIDTH;

src += lineWidth;

}

}

/******************************************************************************

* displayThrFxn

******************************************************************************/

void *displayThrFxn(void *arg)

{

DisplayEnv *envp = (DisplayEnv *) arg;

BufferElement flush = { DISPLAY_FLUSH };

void *status = THREAD_SUCCESS;

unsigned int initMask = 0;

int displayIdx = 0;

int fbFd = 0;

char *displays[NUM_BUFS];

BufferElement e;

/* Initialize the video display device */

fbFd = initDisplayDevice(displays);

if (fbFd == FAILURE) {

cleanup(THREAD_FAILURE);

}

DBG("Video display device initialized.\n");

initMask |= DISPLAYDEVICEINITIALIZED;

/* Signal that initialization is done and wait for other threads */

Rendezvous_meet(envp->hRendezvous);

/* Wait for the vertical sync of the display device */

waitForVsync(fbFd);

DBG("Entering display main loop.\n");

while (TRUE) {

if (!gblGetPlay() && !gblGetQuit()) {

usleep(PAUSE);

continue;

}

/* Receive a buffer with a decoded frame from the video thread */

if (FifoUtil_get(&envp->outFifo, &e) == FIFOUTIL_FAILURE) {

breakLoop(THREAD_FAILURE);

}

/* Is the video thread flushing the pipe? */

if (e.id == DISPLAY_FLUSH) {

breakLoop(THREAD_SUCCESS);

} else if (e.id == DISPLAY_PRIME) {

pthread_mutex_lock(&envp->prime);

pthread_mutex_unlock(&envp->prime);

continue;

}

/* Increment the display index */

displayIdx = (displayIdx + 1) % NUM_BUFS;

/* Copy the supplied frame to the display frame buffer */

copyFrame(displays[displayIdx], e.frameBuffer, e.width, e.height);

/* Give back the buffer to the video thread */

if (FifoUtil_put(&envp->inFifo, &e) == FIFOUTIL_FAILURE) {

breakLoop(THREAD_FAILURE);

}

/* Flip display buffer and working buffer */

flipDisplayBuffers(fbFd, displayIdx);

/* Wait for the vertical sync of the display device */

waitForVsync(fbFd);

gblIncFrames();

}

cleanup:

/* Make sure the other threads aren't waiting for init to complete */

Rendezvous_force(envp->hRendezvous);

/* Make sure the video thread isn't stuck in FifoUtil_get() */

FifoUtil_put(&envp->inFifo, &flush);

/* Clean up the display thread */

if (initMask & DISPLAYDEVICEINITIALIZED) {

cleanupDisplayDevice(fbFd, displays);

}

return status;

}

/*

* loader.h

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

#ifndef _LOADER_H

#define _LOADER_H

typedef struct LoaderState {

int inputFd; // INPUT - The file descriptor of the input file

int loop; // INPUT - true if clip is to start over

char *readBuffer; // INPUT - A large CMEM allocated buffer

int readBufSize; // INPUT - Total size of the readBuffer

int readSize; // INPUT - Size of the 'window'

int doneMask; // INPUT - VIDEO_DONE or SOUND_DONE

int firstFrame; // OUTPUT - True if first frame of a clip

int endClip; // OUTPUT - True if time to start clip over

char *curPtr; // INTERNAL - Points to current frame

char *readPtr; // INTERNAL - Points to the end of current 'window'

} LoaderState;

extern int loaderPrime(LoaderState *state, char **framePtr);

extern int loaderGetFrame(LoaderState *state, int frameSize, char **framePtr);

#endif /* _LOADER_H */

/*

* loader.c

*

* ============================================================================

* Copyright (c) Texas Instruments Inc 2005

*

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================

*/

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <errno.h>

#include "decode.h"

#include "loader.h"

/******************************************************************************

* loaderPrime

******************************************************************************/

int loaderPrime(LoaderState *statep, char **framePtr)

{

int numBytes;

/* Read a full 'window' of encoded data */

numBytes = read(statep->inputFd, statep->readBuffer, statep->readSize);

if (numBytes == -1) {

ERR("Error reading data from video file [%s]\n",strerror(errno));

return FAILURE;

}

/* Initialize the state */

statep->curPtr = statep->readBuffer;

statep->readPtr = statep->readBuffer + numBytes;

*framePtr = statep->curPtr;

statep->firstFrame = TRUE;

statep->endClip = FALSE;

return SUCCESS;

}

/******************************************************************************

* loaderGetFrame

******************************************************************************/

int loaderGetFrame(LoaderState *statep, int frameSize, char **framePtr)

{

int numBytes;

int dataLeft;

int spaceLeft;

char *endBuf;

statep->firstFrame = FALSE;

statep->curPtr += frameSize;

dataLeft = statep->readPtr - statep->curPtr;

if (dataLeft <= 0) {

/* End of file */

while (!gblGetQuit() && !gblAllDone(statep->doneMask)) {

usleep(PAUSE);

}

gblResetDone(statep->doneMask);

if (statep->loop) {

/* Restart at beginning of file */

statep->endClip = TRUE;

if (lseek(statep->inputFd, 0, SEEK_SET) == -1) {

ERR("Failed lseek on file (%s)\n", strerror(errno));

return FAILURE;

}

}

else {

gblSetQuit();

}

}

else {

endBuf = statep->readBuffer + statep->readBufSize;

spaceLeft = endBuf - statep->curPtr;

if (spaceLeft < statep->readSize) {

/* Could not fit 'window', start over at beginning of buffer */

memcpy(statep->readBuffer, statep->curPtr, dataLeft);

statep->curPtr = statep->readBuffer;

statep->readPtr = statep->readBuffer + dataLeft;

}

if (dataLeft == (statep->readSize - frameSize)) {

/* Incremental read making full we have a full 'window' */

numBytes = read(statep->inputFd, statep->readPtr, frameSize);

if (numBytes == -1) {

ERR("Error reading data from file (%s)\n", strerror(errno));

return FAILURE;

}

statep->readPtr += numBytes;

}

*framePtr = statep->curPtr;

}

return SUCCESS;

}

Writing Services

Essay Writing
Service

Find out how the very best essay writing service can help you accomplish more and achieve higher marks today.

Assignment Writing Service

From complicated assignments to tricky tasks, our experts can tackle virtually any question thrown at them.

Dissertation Writing Service

A dissertation (also known as a thesis or research project) is probably the most important piece of work for any student! From full dissertations to individual chapters, we’re on hand to support you.

Coursework Writing Service

Our expert qualified writers can help you get your coursework right first time, every time.

Dissertation Proposal Service

The first step to completing a dissertation is to create a proposal that talks about what you wish to do. Our experts can design suitable methodologies - perfect to help you get started with a dissertation.

Report Writing
Service

Reports for any audience. Perfectly structured, professionally written, and tailored to suit your exact requirements.

Essay Skeleton Answer Service

If you’re just looking for some help to get started on an essay, our outline service provides you with a perfect essay plan.

Marking & Proofreading Service

Not sure if your work is hitting the mark? Struggling to get feedback from your lecturer? Our premium marking service was created just for you - get the feedback you deserve now.

Exam Revision
Service

Exams can be one of the most stressful experiences you’ll ever have! Revision is key, and we’re here to help. With custom created revision notes and exam answers, you’ll never feel underprepared again.