⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode.c

📁 采集视频信号进行H264压缩并通过UDP传送
💻 C
📖 第 1 页 / 共 3 页
字号:

/*
 * 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 <stdlib.h>
#include <string.h>

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sched.h>
#include <pthread.h>

#include <asm/types.h>

#include <linux/videodev2.h>
#include <linux/fb.h>
#include <media/davinci_vpfe.h>

/* Application header file */
#include "encodedecode.h"
#include "global.h"

/* Custom Davinci FBDEV defines (should be in device driver header) */
#define VID0_INDEX 0
#define VID1_INDEX 1
#define ZOOM_1X    0
#define ZOOM_2X    1
#define ZOOM_4X    2

struct Zoom_Params
{
    u_int32_t WindowID;
    u_int32_t Zoom_H;
    u_int32_t Zoom_V;
};
#define FBIO_SETZOOM        _IOW('F', 0x24, struct Zoom_Params)
#define FBIO_WAITFORVSYNC   _IOW('F', 0x20, u_int32_t)
#define FBIO_GETSTD         _IOR('F', 0x25, u_int32_t)

/* Macro for clearing structures */
#define CLEAR(x) memset (&(x), 0, sizeof (x))

/* Bits per pixel for video window */
#define SCREEN_BPP          16

/* D1 screen dimensions */
#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)

/* CIF screen dimensions */
#define CIF_WIDTH           352
#define CIF_HEIGHT          YSCALE(240)
#define CIF_LINE_WIDTH      (CIF_WIDTH * SCREEN_BPP / 8)
#define CIF_FRAME_SIZE      (CIF_LINE_WIDTH * CIF_HEIGHT)

/* Position of CIF image */
#define CIF_XPOS            364
#define CIF_YPOS            240

#define UYVY_BLACK          0x10801080

/* Double buffered for both capture and display drivers */
#define NUM_BUFS            2

/* Describes a capture frame buffer */
typedef struct VideoBuffer {
    void   *start;
    size_t  length;
} VideoBuffer;

enum InitLevels {
    DISPLAYDEVICEINITIALIZED = 1,
    CAPTUREDEVICEINITIALIZED,
    ENGINEOPENED,
    VIDEOENCODERCREATED,
    VIDEODECODERCREATED,
    ENCODEDBUFFERALLOCATED,
    CIFBUFFERALLOCATED
};

/* 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);
static int  encodeVideoBuffer(VIDENC_Handle hEncode, char *inBuf, int inBufSize,
                             char *outBuf, int *outBufSize);
static int  decodeVideoBuffer(VIDDEC_Handle hDecode, char *inBuf,
                              int inBufSize, char *outBuf,
                              int outBufSize, int *framesDroppedPtr);
static int  flipDisplayBuffers(int fd, int displayIdx);
static int  initCaptureDevice(enum Resolution resolution,
                              VideoBuffer **vidBufsPtr, int *numVidBufsPtr,
                              int *captureWidth, int *captureHeight);
static void cleanupCaptureDevice(int fd, VideoBuffer *vidBufs, int numVidBufs);
static int  initDisplayDevice(enum Resolution resolution, char *displays[]);
static void cleanupDisplayDevice(int fd, char *displays[]);
static inline int waitForFrame(int fd);

/******************************************************************************
 * videoDecodeAlgCreate
 ******************************************************************************/
static int videoDecodeAlgCreate(Engine_Handle hEngine,
                                VIDDEC_Handle *hDecodePtr, int *encBufSizePtr,
                                int width, int height)
{
    VIDDEC_Params           params;
    VIDDEC_Status           decStatus;
    XDAS_Int32              status;
    VIDDEC_DynamicParams    dynamicParams;
    VIDDEC_Handle           hDecode;

    /* Create H.264 decoder instance */
    params.size              = sizeof(VIDDEC_Params);
    params.maxFrameRate      = 30000;
    params.maxBitRate        = 1000000;
    params.dataEndianness    = XDM_BYTE;
    params.forceChromaFormat = XDM_YUV_422ILE;

    params.maxHeight         = height;
    params.maxWidth          = width;

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

    if (hDecode == NULL) {
        ERR("Can't open decode algorithm: %s\n", "h264");
        return FAILURE;
    }

    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];
    *hDecodePtr = hDecode;

    return SUCCESS;
}

/******************************************************************************
 * videoEncodeAlgCreate
 ******************************************************************************/
static int videoEncodeAlgCreate(Engine_Handle hEngine,
                                VIDENC_Handle *hEncodePtr,
                                int width, int height)
{
    VIDENC_Params params;
    VIDENC_Handle hEncode;

    params.size                  = sizeof(VIDENC_Params);
    params.encodingPreset        = XDM_DEFAULT;
    params.rateControlPreset     = 1;
    params.maxFrameRate          = 30000;
    params.maxBitRate            = 4000000;
    params.dataEndianness        = XDM_BYTE;
    params.maxInterFrameInterval = 0;
    params.inputChromaFormat     = XDM_YUV_422ILE;
    params.inputContentType      = IVIDEO_PROGRESSIVE;

    params.maxHeight             = height;
    params.maxWidth              = 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;
    }

    *hEncodePtr = hEncode;

    return SUCCESS;
}

/******************************************************************************
 * encodeVideoBuffer
 ******************************************************************************/
static int encodeVideoBuffer(VIDENC_Handle hEncode, char *inBuf, int inBufSize,
                             char *outBuf, int *outBufSize)
{
    VIDENC_DynamicParams    dynamicParams;
    XDAS_Int32              inBufSizeArray[1];
    XDAS_Int32              outBufSizeArray[1];
    XDAS_Int32              status;
    XDM_BufDesc             inBufDesc;
    XDM_BufDesc             outBufDesc;
    VIDENC_InArgs           inArgs;
    VIDENC_OutArgs          outArgs;
    VIDENC_Status           encStatus;

    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(VIDENC_InArgs);
    outArgs.size            = sizeof(VIDENC_OutArgs);

    status = VIDENC_process(hEncode, &inBufDesc, &outBufDesc,
                            &inArgs, &outArgs);

    if (status != VIDENC_EOK) {
        status = VIDENC_control(hEncode, XDM_GETSTATUS, &dynamicParams,
                                &encStatus);
        if (status != VIDENC_EOK) {
            ERR("XDM_GETSTATUS failed, status=%ld\n", status);
            return FAILURE;
        }

        ERR("Extended error %ld\n", encStatus.extendedError);
        return FAILURE;
    }

    *outBufSize = outArgs.bytesGenerated;

    return SUCCESS;
}

/******************************************************************************
 * decodeVideoBuffer
 ******************************************************************************/
static int decodeVideoBuffer(VIDDEC_Handle hDecode, char *inBuf,
                             int inBufSize, char *outBuf,
                             int outBufSize, int *framesDroppedPtr)
{
    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);

    status = VIDDEC_process(hDecode, &inBufDesc, &outBufDesc,
                            &inArgs, &outArgs);

    if (status != VIDDEC_EOK) {
        status = VIDDEC_control(hDecode, XDM_GETSTATUS, &dynamicParams,
                                &decStatus);
        if (status != VIDDEC_EOK) {
            ERR("XDM_GETSTATUS failed, status=%ld\n", status);
            return FAILURE;
        }

        if (status == VIDDEC_ERUNTIME ||
            XDM_ISFATALERROR(decStatus.extendedError)) {

            ERR("VIDDEC_process() failed with a fatal error (%ld ext: %#lx\n",
                status, decStatus.extendedError);
            return FAILURE;
        }
        else {
            *framesDroppedPtr++;
            return SUCCESS;
        }
    }

    if (status != VIDDEC_EOK) {
        ERR("VIDDEC_process() failed, status=%ld\n", status);
        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;
}

/******************************************************************************
 * initCaptureDevice
 ******************************************************************************/
static int initCaptureDevice(enum Resolution resolution,
                             VideoBuffer **vidBufsPtr, int *numVidBufsPtr,
                             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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -