📄 video.c
字号:
/* * 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>/* 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>/* Demo headers */#include <rendezvous.h>#include <fifoutil.h>#include "decode.h"#include "video.h"#include "display.h"#include "loader.h"/* The size of the read buffer */#define READBUFSIZE 3 * 1024 * 1024/* The levels of initialization */#define VIDEOFILEINITIALIZED 0x1#define INFIFOOPENED 0x2#define OUTFIFOOPENED 0x4#define DISPLAYTHREADCREATED 0x8#define ENGINEOPENED 0x10#define VIDEODECODERCREATED 0x20#define READBUFFERALLOCATED 0x40#define DISPLAYBUFFERSALLOCATED 0x80/* Number of buffers between video thread and display thread */#define DISPLAY_BUFFERS 3/* Negative value of outputID means the decoder kept the buffer */#define BUFFER_KEPT_SEND_NEW_DST -1#define BUFFER_KEPT_RESUBMIT_DST -2/* Structure containing statistics about the frames in a clip */typedef struct FrameStats { int framesRejected; int iFrames; int pFrames; int bFrames; int idrFrames;} FrameStats;/* Video decoder names */static char *videoDecodeAlgNames[NUM_VIDEO_DECODERS] = { "mpeg4dec", "h264dec", "mpeg2dec"};/* Local function prototypes */static int getClipSize(VIDDEC_Handle hDecode, int *widthPtr, int *heightPtr);static int videoDecodeAlgCreate(Engine_Handle hEngine, VIDDEC_Handle *hDecodePtr, enum VideoDecoder videoDecoder, int *readSizePtr);static int decodeVideoBuffer(VIDDEC_Handle hDecode, char *inBuf, int inBufSize, int inputID, char *outBuf, int *bytesProcessed, int *outputIDPtr, FrameStats *stats, int *frameDonePtr);/****************************************************************************** * getClipSize ******************************************************************************/static int getClipSize(VIDDEC_Handle hDecode, int *widthPtr, int *heightPtr){ VIDDEC_DynamicParams dynamicParams; VIDDEC_Status decStatus; XDAS_Int32 status; /* Get the codec status (which includes width and height of last frame) */ dynamicParams.size = sizeof(VIDDEC_DynamicParams); decStatus.size = sizeof(VIDDEC_Status); status = VIDDEC_control(hDecode, XDM_GETSTATUS, &dynamicParams, &decStatus); if (status != VIDDEC_EOK) { ERR("XDM_GETSTATUS failed, status=%ld\n", status); return FAILURE; } if (decStatus.outputWidth > D1_WIDTH || decStatus.outputHeight > D1_MAX_HEIGHT) { ERR("Clip size (%ldx%ld) bigger than a D1 screen (%dx%d)\n", decStatus.outputWidth, decStatus.outputHeight, D1_WIDTH, D1_MAX_HEIGHT); return FAILURE; } /* Set the global variables for OSD update */ gblSetImageWidth(decStatus.outputWidth); gblSetImageHeight(decStatus.outputHeight); *widthPtr = decStatus.outputWidth; *heightPtr = decStatus.outputHeight; return SUCCESS;}/****************************************************************************** * videoDecodeAlgCreate ******************************************************************************/static int videoDecodeAlgCreate(Engine_Handle hEngine, VIDDEC_Handle *hDecodePtr, VideoDecoder videoDecoder, int *readSizePtr){ VIDDEC_Handle hDecode; VIDDEC_Status decStatus; XDAS_Int32 status; VIDDEC_Params params; VIDDEC_DynamicParams dynamicParams; char *algName; algName = videoDecodeAlgNames[videoDecoder]; params.size = sizeof(VIDDEC_Params); params.maxHeight = D1_MAX_HEIGHT; params.maxWidth = D1_WIDTH; params.maxFrameRate = 0; params.maxBitRate = 0; params.dataEndianness = XDM_BYTE; params.forceChromaFormat = XDM_YUV_422ILE; /* Create video decoder instance */ hDecode = VIDDEC_create(hEngine, algName, ¶ms); if (hDecode == NULL) { ERR("Failed to open video decode algorithm\n"); return FAILURE; } dynamicParams.size = sizeof(VIDDEC_DynamicParams); dynamicParams.decodeHeader = XDM_DECODE_AU; dynamicParams.displayWidth = XDM_DEFAULT; dynamicParams.frameSkipMode = IVIDEO_NO_SKIP; /* Set video decoder dynamic params */ decStatus.size = sizeof(VIDDEC_Status); status = VIDDEC_control(hDecode, XDM_SETPARAMS, &dynamicParams, &decStatus); if (status != VIDDEC_EOK) { ERR("XDM_SETPARAMS failed, status=%ld\n", status); return FAILURE; } /* 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; }//Liang*readSizePtr = 1024*1024; // *readSizePtr = decStatus.bufInfo.minInBufSize[0]; *hDecodePtr = hDecode; return SUCCESS;}/****************************************************************************** * decodeVideoBuffer ******************************************************************************/static int decodeVideoBuffer(VIDDEC_Handle hDecode, char *inBuf, int inBufSize, int inputID, char *outBuf, int *bytesProcessed, int *outputIDPtr, FrameStats *stats, int *frameDonePtr){ 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] = D1_MAX_FRAME_SIZE; inBufDesc.bufSizes = inBufSizeArray; inBufDesc.bufs = (XDAS_Int8 **) &inBuf; inBufDesc.numBufs = 1; outBufDesc.bufSizes = outBufSizeArray; outBufDesc.bufs = (XDAS_Int8 **) &outBuf; outBufDesc.numBufs = 1; inArgs.size = sizeof(VIDDEC_InArgs); inArgs.numBytes = inBufSize; inArgs.inputID = inputID; outArgs.size = sizeof(VIDDEC_OutArgs); /* Decode video buffer */ status = VIDDEC_process(hDecode, &inBufDesc, &outBufDesc, &inArgs, &outArgs); *bytesProcessed = outArgs.bytesConsumed; if (status != VIDDEC_EOK) { if (status == VIDDEC_ERUNTIME || outArgs.bytesConsumed == 0 || 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; } } /* Get frame status to see if this was an interlaced frame */ status = VIDDEC_control(hDecode, XDM_GETSTATUS, &dynamicParams, &decStatus); if (status != VIDDEC_EOK) { ERR("XDM_GETSTATUS failed, status=%ld\n", status); return FAILURE; } if (decStatus.contentType == IVIDEO_INTERLACED) { (*frameDonePtr) ^= 1; } 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; } /* Did the decoder keep the frame? */ if (outArgs.displayBufs.bufs[0] == NULL) { if ((outArgs.decodedFrameType != IVIDEO_B_FRAME) & *frameDonePtr) { *outputIDPtr = BUFFER_KEPT_SEND_NEW_DST; } else { *outputIDPtr = BUFFER_KEPT_RESUBMIT_DST; } } else { *outputIDPtr = outArgs.outputID; } return SUCCESS;}/****************************************************************************** * videoThrFxn ******************************************************************************/void *videoThrFxn(void *arg){ BufferElement flush = { DISPLAY_FLUSH }; FrameStats frameStats = { 0, 0, 0, 0, 0 }; Engine_Handle hEngine = NULL; unsigned int initMask = 0; int numDisplayBufs = 0; VideoEnv *envp = (VideoEnv *) arg; void *status = THREAD_SUCCESS; BufferElement bufferElements[DISPLAY_BUFFERS]; struct sched_param schedParam; pthread_t displayThread; pthread_attr_t attr; VIDDEC_Handle hDecode; DisplayEnv displayEnv; LoaderState lState; int frameDone; int outputID; char *framePtr; int clipWidth; int clipHeight; int frameSize; void *ret; BufferElement e; int i; /* Initialize loader state */ lState.loop = envp->loop; lState.readBufSize = READBUFSIZE; lState.doneMask = VIDEO_DONE; /* Open the input video file */ lState.inputFd = open(envp->videoFile, O_RDONLY); if (lState.inputFd == -1) { ERR("Failed to open %s (%s)\n", envp->videoFile, strerror(errno));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -