DavinciDM6467T周期产生SPS/PPS、IDR帧

来源:互联网 发布:模拟人生4网络股票 编辑:程序博客网 时间:2024/05/06 06:07


TI的encode源程序只在第一帧的时候产生SPS/PPS和IDR帧(根据TI的产生流程,为了方便本文的IDR帧指的是不带SPS/PPS的),之后都是I帧,而且没有提供直接修改IDR帧周期的参数。不过TI提供了一个产生SPS/PPS和IDR帧的流程,如下图:


简单做一下解释:1是改变编码器的动态参数为只产生头,也就是指产生SPS/PPS。

                                2是调用control函数将改变的动态参数修改到编码器中。VIDENC1_process的调用参照Venc1_create函数。我这里将对VIDENC1_process的调用写成了一个函数:Venc1_control(hVe1, dynParams);可以直接在video.c中调用。

Int Venc1_control(Venc1_Handle hVe, VIDENC1_DynamicParams *dynParams){            //VIDENC1_Handle hEncode;            XDAS_Int32              status;                        VIDENC1_Status encStatus;            encStatus.size = sizeof(VIDENC1_Status);            encStatus.data.buf = NULL;             status = VIDENC1_control(hVe->hEncode, XDM_SETPARAMS, dynParams, &encStatus);            //if (status != VIDENC1_EOK) {              //  Dmai_err1("XDM_SETPARAMS failed, status=%d\n", status);             //   VIDENC1_delete(hEncode);             //   free(hVe);              //   return NULL;              //}            printf("status=%ld\n",status);            hVe->dynParams = *dynParams;            return 0;           }

                     3是根据修改后的参数编写一帧数据。流程上是调用 VIDENC1_process,其实直接调用Venc1_process就可以  。

                     4、5、6将都态参数改成产生IDR帧并编码

                     7、8将动态参数改回原始状态

       TI流程上没有详细说明的一点是:源程序是调用一次process编出一帧数据,然后送到writer线程中,唤醒阻塞的writer线程。现在调用两次process,如果只用一次FIFO_put(), 前一帧数据就被覆盖了。

       所以,得开辟一块内存,在第一次调用process之后将编出来的帧存到buffer中,第二次调用process之后将两个buffer合并,在调用FIFO_put激活writer线程。小插曲:一开始memcpy的时候忘了包含头文件,导致拷贝不进去数据,但是编译链接只有warning没有报错。

下面上程序:

/* * video.c * * This source file has the implementations for the video thread * functions implemented for 'DVSDK encode demo' on Dm6467 platform * * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/  *  *  *  Redistribution and use in source and binary forms, with or without  *  modification, are permitted provided that the following conditions  *  are met: * *    Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer. * *    Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the    *    distribution. * *    Neither the name of Texas Instruments Incorporated nor the names of *    its contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. * *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include <xdc/std.h>#include <ti/sdo/ce/Engine.h>#include <stdlib.h>#include <ti/sdo/dmai/Fifo.h>#include <ti/sdo/dmai/Pause.h>#include <ti/sdo/dmai/BufTab.h>#include <ti/sdo/dmai/VideoStd.h>#include <ti/sdo/dmai/BufferGfx.h>#include <ti/sdo/dmai/Rendezvous.h>#include <ti/sdo/dmai/ce/Venc1.h>#include "video.h"#include "../demo.h"#include <pthread.h>  #include <string.h> #include   <unistd.h>#include <ti/sdo/dmai/Buffer.h>/* Number of buffers in the pipe to the capture thread */#define NUM_VIDEO_BUFS           3/****************************************************************************** * videoThrFxn ******************************************************************************/Void *videoThrFxn(Void *arg){    VideoEnv               *envp                = (VideoEnv *) arg;    Void                   *status              = THREAD_SUCCESS;    VIDENC1_Params          defaultParams       = Venc1_Params_DEFAULT;    VIDENC1_DynamicParams   defaultDynParams    = Venc1_DynamicParams_DEFAULT;    BufferGfx_Attrs         gfxAttrs            = BufferGfx_Attrs_DEFAULT;    Venc1_Handle            hVe1                = NULL;    Engine_Handle           hEngine             = NULL;    BufTab_Handle           hBufTab             = NULL;    Int                     frameCnt            = 0;    Buffer_Handle           hCapBuf, hDstBuf;    VIDENC1_Params         *params;    VIDENC1_DynamicParams  *dynParams;    Int                     fifoRet;    Int                     bufIdx;    /* Buffer to copy buffer(hDstBuf) of IDR Frame without SPS/PPS */ //added by wanglin    Int8* IDR_buffer=NULL;    IDR_buffer = (unsigned char*)calloc(8000000,sizeof(char));     /* end */    /* Open the codec engine */    hEngine = Engine_open(envp->engineName, NULL, NULL);    if (hEngine == NULL) {        ERR("Failed to open codec engine %s\n", envp->engineName);        cleanup(THREAD_FAILURE);    }    gblSignalHandlerInstall();    /* Use supplied params if any, otherwise use defaults */    params = envp->params ? envp->params : &defaultParams;    dynParams = envp->dynParams ? envp->dynParams : &defaultDynParams;    /* Set up codec parameters */    params->maxWidth          = envp->imageWidth;    params->maxHeight         = envp->imageHeight;    params->inputChromaFormat = XDM_YUV_420SP;    params->reconChromaFormat = XDM_CHROMA_NA;    /* Set up codec parameters depending on bit rate */    if (envp->videoBitRate < 0) {        /* Variable bit rate */        params->rateControlPreset = IVIDEO_NONE;        /*         * If variable bit rate use a bogus bit rate value (> 0)         * since it will be ignored.         */        params->maxBitRate        = 2000000;    }    else {        /* Constant bit rate */        params->rateControlPreset = IVIDEO_LOW_DELAY;        params->maxBitRate        = 2000000;//envp->videoBitRate;    }    params->dataEndianness        = XDM_LE_32;    //dynParams->targetBitRate = params->maxBitRate;   //changede by wanglin    dynParams->targetBitRate = (envp->videoBitRate < 0)?2000000:envp->videoBitRate;      //added by wanglin    dynParams->inputWidth    = params->maxWidth;    dynParams->inputHeight   = params->maxHeight;    /* */    //dynParams->forceFrame = IVIDEO_IDR_FRAME;    /* Set length of GOP*/    dynParams->intraFrameInterval=25;// added by wanglin    /* Create the video encoder */    //VIDENC1_Handle hEncode;    hVe1 = Venc1_create(hEngine,envp->videoEncoder, params, dynParams);    if (hVe1 == NULL) {        ERR("Failed to create video encoder: %s\n", envp->videoEncoder);        cleanup(THREAD_FAILURE);    }    /* Store the output buffer size in the environment */    envp->outBufSize = Venc1_getOutBufSize(hVe1);    /* Signal that the codec is created and output buffer size available */    Rendezvous_meet(envp->hRendezvousWriter);    gfxAttrs.colorSpace = ColorSpace_YUV420PSEMI;    gfxAttrs.dim.width = envp->imageWidth;    gfxAttrs.dim.height = envp->imageHeight;    gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(gfxAttrs.dim.width,                                                       gfxAttrs.colorSpace);    /*     * Ask the codec how much input data it needs and create a table of     * buffers with this size.     */    hBufTab = BufTab_create(NUM_VIDEO_BUFS, Venc1_getInBufSize(hVe1),                            BufferGfx_getBufferAttrs(&gfxAttrs));    if (hBufTab == NULL) {        ERR("Failed to allocate contiguous buffers\n");        cleanup(THREAD_FAILURE);    }    /* Send buffers to the capture thread to be ready for main loop */    for (bufIdx = 0; bufIdx < NUM_VIDEO_BUFS; bufIdx++) {        if (Fifo_put(envp->hCaptureInFifo,                     BufTab_getBuf(hBufTab, bufIdx)) < 0) {            ERR("Failed to send buffer to display thread\n");            cleanup(THREAD_FAILURE);        }    }    /* Signal that initialization is done and wait for other threads */    Rendezvous_meet(envp->hRendezvousInit);    //frame count     Int32 Frame_count=0;    while (!gblGetQuit()) {               /* Pause processing? */        Pause_test(envp->hPauseProcess);        /* Get a buffer to encode from the capture thread */        fifoRet = Fifo_get(envp->hCaptureOutFifo, &hCapBuf);        if (fifoRet < 0) {            ERR("Failed to get buffer from video thread\n");            cleanup(THREAD_FAILURE);        }        /* Did the capture thread flush the fifo? */        if (fifoRet == Dmai_EFLUSH) {            cleanup(THREAD_SUCCESS);        }        /* Get a buffer to encode to from the writer thread */        //Buffer_getNumBytesUsed(hDstBuf);        fifoRet = Fifo_get(envp->hWriterOutFifo, &hDstBuf);        if (fifoRet < 0) {            ERR("Failed to get buffer from video thread\n");            cleanup(THREAD_FAILURE);        }        /* Did the writer thread flush the fifo? */        if (fifoRet == Dmai_EFLUSH) {            cleanup(THREAD_SUCCESS);        }        /* Make sure the whole buffer is used for input */        BufferGfx_resetDimensions(hCapBuf);        /* Force SPS/PPS and IDR Frame*/  //added by wanglin        //printf("Frame_count=%ld\n",Frame_count);        //printf("Frame_count%25=%d\n",Frame_count%25);        if( (Frame_count%25 == 0) && Frame_count != 0){                      /* IDR */            unsigned int IDR_bits;            dynParams->generateHeader = XDM_ENCODE_AU;            dynParams->forceFrame = IVIDEO_IDR_FRAME;            Venc1_control(hVe1, dynParams);                      if (Venc1_process(hVe1, hCapBuf, hDstBuf) < 0) {            ERR("Failed to encode video buffer\n");            cleanup(THREAD_FAILURE);            }                        IDR_bits = Buffer_getNumBytesUsed(hDstBuf);               memcpy(IDR_buffer,Buffer_getUserPtr(hDstBuf),IDR_bits);                       /* SPS/PPS */            unsigned int Header_bits;            dynParams->generateHeader = XDM_GENERATE_HEADER;            dynParams->forceFrame = IVIDEO_NA_FRAME;            Venc1_control(hVe1, dynParams);            if (Venc1_process(hVe1, hCapBuf, hDstBuf) < 0) {            ERR("Failed to encode video buffer\n");            cleanup(THREAD_FAILURE);            }            Header_bits = Buffer_getNumBytesUsed(hDstBuf);            Buffer_setNumBytesUsed(hDstBuf, IDR_bits+Header_bits);                        memcpy(Buffer_getUserPtr(hDstBuf)+Header_bits,IDR_buffer,IDR_bits);            //fwrite(Buffer_getUserPtr(hDstBuf),Buffer_getNumBytesUsed(hDstBuf), 1, stream);            //printf("Buffer_getNumBytesUsed(hDstBuf)=%ld\n",Buffer_getNumBytesUsed(hDstBuf));            dynParams->generateHeader = XDM_ENCODE_AU;            dynParams->forceFrame = IVIDEO_NA_FRAME;            Venc1_control(hVe1, dynParams);                   }        else{                        if (Venc1_process(hVe1, hCapBuf, hDstBuf) < 0) {            ERR("Failed to encode video buffer\n");            cleanup(THREAD_FAILURE);            }        }        /* end */ //added by wanglin               /* Decode the video buffer */        //if (Venc1_process(hVe1, hCapBuf, hDstBuf) < 0) {        //ERR("Failed to encode video buffer\n");        //cleanup(THREAD_FAILURE);        //}        Frame_count++;              /* Send encoded buffer to writer thread for filesystem output */        if (Fifo_put(envp->hWriterInFifo, hDstBuf) < 0) {        ERR("Failed to send buffer to display thread\n");        cleanup(THREAD_FAILURE);        }        /* Return buffer to capture thread */        if (Fifo_put(envp->hCaptureInFifo, hCapBuf) < 0) {            ERR("Failed to send buffer to display thread\n");            cleanup(THREAD_FAILURE);        }        /* Increment statistics for the user interface */        gblIncVideoBytesProcessed(Buffer_getNumBytesUsed(hDstBuf));        frameCnt++;    }cleanup:    /* Make sure the other threads aren't waiting for us */    Rendezvous_force(envp->hRendezvousInit);    Rendezvous_force(envp->hRendezvousWriter);    Pause_off(envp->hPauseProcess);    Fifo_flush(envp->hWriterInFifo);    Fifo_flush(envp->hCaptureInFifo);    /* Make sure the other threads aren't waiting for init to complete */    Rendezvous_meet(envp->hRendezvousCleanup);    /* Clean up the thread before exiting */    if (hBufTab) {        BufTab_delete(hBufTab);    }    if (hVe1) {        Venc1_delete(hVe1);    }    if (hEngine) {        Engine_close(hEngine);    }    /* Free Buffer */    if (IDR_buffer) {        free(IDR_buffer);    }    return status;}


	
				
		
原创粉丝点击