DavinciDM6467T周期产生SPS/PPS、IDR帧


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;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值