📄 video_thread.c
字号:
/* * video_thread.c *//* Standard Linux headers */#include <stdio.h> // always include stdio.h#include <stdlib.h> // always include stdlib.h#include <string.h> // defines memset and memcpy methods#include <sys/ioctl.h> // defines ioctl method#include <linux/fb.h> // defines framebuffer driver methods#include <asm/types.h> // standard typedefs required by v4l2 header#include <linux/videodev2.h> // v4l2 driver definitions/* Codec Engine headers */#include <xdc/std.h> // xdc base definitions. Must come 1st#include <ti/sdo/ce/Engine.h> // required for any CE application#include <ti/sdo/ce/CERuntime.h> // required for any CE application#include <ti/sdo/ce/video/viddec.h> // defines video decoder functions#include <ti/sdo/ce/video/videnc.h> // defines video encoder functions/* Application header files */#include "debug.h" // DBG and ERR macros#include "video_thread.h" // video thread definitions#include "video_osd.h" // OSD window functions#include "video_output.h" // Video display device functions#include "video_input.h" // Video input device functions#include "engine.h" // Helper utilities for engine_open and close#include "video_decoder.h" // Video decoder functions#include "video_encoder.h" // Video encoder functions/* Video encoder and decoder used */#define VIDEO_ENCODER "video_encoder"#define VIDEO_DECODER "video_decoder"/* Video capture and display devices used */#define FBVID_VIDEO "/dev/fb/3"#define FBVID_ATTR "/dev/fb/2"#define FBVID_OSD "/dev/fb/0"#define V4L2_DEVICE "/dev/video0"/* Input file */#define INPUTFILE "/tmp/video.raw"#define PICTUREFILE "osd.r16"/* Double-buffered display, triple-buffered capture */#define NUM_DISP_BUFS 2#define NUM_CAP_BUFS 3/* Other Definitions */#define SCREEN_BPP 16#define D1_WIDTH 720#define D1_HEIGHT 480/* Macro for clearing structures */#define CLEAR(x) memset (&(x), 0, sizeof (x))/****************************************************************************** * video_thread_fxn ******************************************************************************//* input parameters: *//* void *arg -- a pointer to a video_thread_env structure as *//* defined in video_thread.h *//* *//* arg.quit -- when quit != 0, thread will cleanup and exit *//* *//* return value: *//* void * -- VIDEO_THREAD_SUCCESS or VIDEO_THREAD_FAILURE as *//* defined in video_thread.h *//******************************************************************************/void *video_thread_fxn(void *arg){/* Thread parameters and return value */ video_thread_env *env = arg; // see above void *status = VIDEO_THREAD_SUCCESS; // see above/* The levels of initialization for initMask */#define OSDSETUPCOMPLETE 0x1#define DISPLAYDEVICEINITIALIZED 0x2#define CAPTUREDEVICEINITIALIZED 0x4#define VIDEOENCODERCREATED 0x8#define VIDEODECODERCREATED 0x10#define ENCODEDBUFFERALLOCATED 0x20#define ENGINEOPENED 0x40 unsigned int initMask = 0x0;/* Capture and display driver variables */ FILE *inputFile = NULL; // input file pointer int osdFd = 0; // OSD file descriptor int attrFd = 0; // attr window file descriptor int fbFd = 0; // video fb driver file desc int captureFd = 0; // capture driver file descriptor unsigned short *osdDisplay; // OSD display buffer unsigned short *attrDisplay; // attribute display buffer VideoBuffer *vidBufs; // capture frame descriptors unsigned int numVidBufs = NUM_CAP_BUFS; // number of capture frames int captureWidth; // width of a capture frame int captureHeight; // height of a capture frame int captureSize; // bytes in a capture frame struct v4l2_buffer v4l2buf; // stores a dequeue'd frame#define PICTURE_HEIGHT 60#define PICTURE_WIDTH 720 unsigned short picture[PICTURE_HEIGHT * PICTURE_WIDTH]; // osd picture char *displays[NUM_DISP_BUFS]; // display frame pointers int displayWidth; // width of a display frame int displayHeight; // height of a display frame int displayBufSize; // bytes in a display frame int displayIdx = 0; // frame being displayed int workingIdx = 1; // next frame, being built char *dst; // pointer to working frame/* OSD scrolling variables */ int xoffset = 0; int yoffset = 0;/* Intermediate buffer for encoded video */ char *encBuf = NULL; // pointer to encoded buffer int encBufSize = 0; // size of encoded buffer (numbytes = int numbytes; // how full, numbytes < encBufSize) /* Codec engine variables */ Engine_Handle engineHandle = NULL; VIDENC_Handle encoderHandle = NULL; // handle to video encoder VIDDEC_Handle decoderHandle = NULL; // handle to video decoder /* Thread Setup Phase -- secure and initialize resources */ /* Initialize video attribute window to fully opaque OSD (0x77) */ if( video_osd_setup(&osdFd, &attrFd, FBVID_OSD, FBVID_ATTR, 0x00, &osdDisplay, &attrDisplay) == VOSD_FAILURE ){ ERR("Failed video_osd_setup in video_thread_function\n"); status = VIDEO_THREAD_FAILURE; goto cleanup; } initMask |= OSDSETUPCOMPLETE; /* Place a circular alpha-blended OSD frame around video screen */ video_osd_circframe(osdDisplay, attrDisplay, 0xFFFF, 0x33); /* Open the display picture for OSD */ if((inputFile = fopen(PICTUREFILE, "r")) == NULL) { ERR("Failed to open input file %s\n", PICTUREFILE); status = VIDEO_THREAD_FAILURE; goto cleanup; } DBG("Opened file %s with FILE pointer %p\n", PICTUREFILE, inputFile); /* read in picture */ if(fread(picture, sizeof(short), PICTURE_HEIGHT * PICTURE_WIDTH, inputFile) < PICTURE_HEIGHT * PICTURE_WIDTH){ ERR("Error reading osd picture from file\n"); fclose(inputFile); goto cleanup; } fclose(inputFile); DBG("OSD Picture read successful, placing picture\n"); video_osd_place(osdDisplay, attrDisplay, picture, 0x77, 0, 420, PICTURE_WIDTH, PICTURE_HEIGHT); /* Initialize the video display device */ displayWidth = D1_WIDTH; displayHeight = D1_HEIGHT; if( video_output_setup(&fbFd, FBVID_VIDEO, displays, NUM_DISP_BUFS, &displayWidth, &displayHeight, ZOOM_1X) == VOUT_FAILURE) { ERR("Failed video_output_setup in video_thread_function\n"); status = VIDEO_THREAD_FAILURE; goto cleanup; } /* Calculate size of a display buffer in bytes */ displayBufSize = displayWidth * displayHeight * SCREEN_BPP/8; /* Record that display device was opened in initialization bitmask */ initMask |= DISPLAYDEVICEINITIALIZED; /* Initialize the video capture device */ captureWidth = D1_WIDTH; captureHeight = D1_HEIGHT; if( video_input_setup(&captureFd, V4L2_DEVICE, &vidBufs, &numVidBufs, &captureWidth, &captureHeight) == VIN_FAILURE) { ERR("Failed video_input_setup in video_thread_function\n"); status = VIDEO_THREAD_FAILURE; goto cleanup; } /* Calculate size of a raw frame */ captureSize = captureWidth * captureHeight * SCREEN_BPP / 8; /* Record that cpature device was opened in initialization bitmask */ initMask |= CAPTUREDEVICEINITIALIZED; /* open the codec engine */ /* note: codec engine should be opened in each thread that uses it */ if(engine_setup(&engineHandle, env->engineName, NULL) != ENGINE_SUCCESS){ ERR("engine_setup failed in video_thread_fxn\n"); status = VIDEO_THREAD_FAILURE; goto cleanup; } initMask |= ENGINEOPENED; /* Allocate and initialize video encoder on the engine */ /* uses engineHandle global variable assumed set before entry */ if (video_encoder_setup(engineHandle, VIDEO_ENCODER, &encoderHandle) == VENC_FAILURE) { ERR("Failed video_encoder_setup in video_thread_fxn\n"); status = VIDEO_THREAD_FAILURE; goto cleanup; } initMask |= VIDEOENCODERCREATED; /* Allocate and initialize video decoder on the engine */ /* uses numbytes as a temporary variable for minInBufSize */ if (video_decoder_setup(engineHandle, VIDEO_DECODER, &decoderHandle) == VDEC_FAILURE) { ERR("Failed video_decoder_setup in video_thread_fxn"); status = VIDEO_THREAD_FAILURE; goto cleanup; } initMask |= VIDEODECODERCREATED; /* Set buffer size for intermediate buffer (for encoded data) */ /* as the maximum of the encoders max output size and the decoders */ /* minimum input size */ encBufSize = captureSize; /* Allocate intermediate buffer */ /* Must use contiguous buffers if passed to DSP! */ /* (Driver buffers are automatically allocated contiguous */ encBuf = (char *) malloc(encBufSize); if (encBuf == NULL) { ERR("Failed to allocate video buffer in video_thread_fxn.\n"); status = VIDEO_THREAD_FAILURE; goto cleanup; } initMask |= ENCODEDBUFFERALLOCATED; DBG("Allocated intermediate video buffer of size %d\n", encBufSize); DBG("\tat location %p\n", encBuf); /* Thread Execute Phase -- perform I/O and processing */ DBG("Entering video_thread_fxn processing loop.\n"); while (!env->quit) {#define X_RATE 5#define Y_RATE 0 xoffset += X_RATE; yoffset += Y_RATE; if(xoffset >= PICTURE_WIDTH) xoffset = 0; if(yoffset >= PICTURE_HEIGHT) yoffset = 0; video_osd_scroll(osdDisplay, attrDisplay, picture, 0, 420, PICTURE_WIDTH, PICTURE_HEIGHT, xoffset, yoffset); /* Read input buffer from video capture device */ if (wait_for_frame(captureFd) == VIN_FAILURE) { ERR("wait_for_frame failed in video_thread_fxn\n"); status = VIDEO_THREAD_FAILURE; break; } 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) {// if (errno == EAGAIN) {// continue;// } ERR("VIDIOC_DQBUF failed in video_thread_fxn\n"); status = VIDEO_THREAD_FAILURE; break; } /* on input, numbytes specifies full size of intermediate buffer */ numbytes = encBufSize; /* Encode the buffer */ if (encode_video(encoderHandle, vidBufs[v4l2buf.index].start, captureSize, encBuf, &numbytes) == VENC_FAILURE) { ERR("encode_video failed in video_thread_fxn\n"); status = VIDEO_THREAD_FAILURE; break; } dst = displays[workingIdx]; /* Decode the buffer */ if (decode_video(decoderHandle, encBuf, numbytes, dst, displayBufSize) == VDEC_FAILURE) { ERR("decode_video failed in video_thread_fxn\n"); status = VIDEO_THREAD_FAILURE; break; } /* Issue capture buffer back to capture device driver */ if (ioctl(captureFd, VIDIOC_QBUF, &v4l2buf) == -1) { ERR("VIDIOC_QBUF failed in video_thread_fxn\n"); status = VIDEO_THREAD_FAILURE; break; } /* Flip display buffer and working buffer */ displayIdx = (displayIdx + 1) % NUM_DISP_BUFS; workingIdx = (workingIdx + 1) % NUM_DISP_BUFS; flip_display_buffers(fbFd, displayIdx); }cleanup: DBG("Exited video_thread_fxn processing loop\n"); DBG("\tStarting video thread cleanup\n"); /* Thread Cleanup Phase -- free resources no longer needed by thread */ /* Uses the init_bitmask to only free resources that were allocated */ /* Cleanup osd */ if (initMask & OSDSETUPCOMPLETE) { DBG("Closing FILE ptr %p\n", inputFile); video_osd_cleanup(osdFd, attrFd, osdDisplay, attrDisplay); } /* Close video capture device */ if (initMask & CAPTUREDEVICEINITIALIZED) { video_input_cleanup(captureFd, vidBufs, numVidBufs); } /* Close video display device */ if (initMask & DISPLAYDEVICEINITIALIZED) { video_output_cleanup(fbFd, displays, NUM_DISP_BUFS); } /* Delete video decoder */ if (initMask & VIDEODECODERCREATED) { video_decoder_cleanup(decoderHandle); } /* Delete video encoder */ if (initMask & VIDEOENCODERCREATED) { video_encoder_cleanup(encoderHandle); } /* Close the engine */ if (initMask & ENGINEOPENED){ engine_cleanup(engineHandle); } /* Free intermediate (encoded) buffer */ if (initMask & ENCODEDBUFFERALLOCATED) { DBG("Freed intermediate video buffer at %p\n", encBuf); free(encBuf); } /* Return the status of thread execution */ DBG("Video thread cleanup complete. Exiting video_thread_fxn\n"); return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -