精华内容
下载资源
问答
  • 海思编解码芯片添加64M nor flash

    千次阅读 2017-07-08 12:37:30
    uboot和内核都必须修改。 struct spi_info hisfc350_spi_info_table[] ; 在结构体里面添加自己的flash节点,我这里用的是MX66LS51235E { "MX66L(S512)35(E/F)", //chip name {0xC2,0x20, 0x1A}, ///chip ...

    uboot和内核都必须修改。

    struct spi_info hisfc350_spi_info_table[] ;
    
    在结构体里面添加自己的flash节点,我这里用的是MX66LS51235E
    
    {
    		 "MX66L(S512)35(E/F)", //chip name
    		 {0xC2,0x20, 0x1A}, ///chip id nor flash has itself ID
    		 3,  //ID len
    		 _64M, //flash size
    		 _64K, //falsh sectors size
    		 4, //clock
    		 {
    			&READ_STD(0,  INFINITE, 40/*50*/), //standard read clock, in datesheet 
    			&READ_FAST(1, INFINITE, 104),///fast read clock, in datesheet 
    			&READ_DUAL(2, INFINITE, 104),///dual read clock, in datesheet 
    			&READ_DUAL_ADDR(1, INFINITE, 84),///dual read addr clock, in datesheet 
    #ifndef CONFIG_CLOSE_SPI_8PIN_4IO
    			&READ_QUAD_ADDR(3, INFINITE, 70),///qual read addr clock, in datesheet 
    #endif
    			0
    		},
    		{
    			&WRITE_STD(0, 256, 75),
    			0
    		},
    
    		{
    			&ERASE_SECTOR_64K(0, _64K, 80),
    			0
    		},
    		&spi_driver_mx66lS512, // 驱动函数,寻找类似的芯片修改即可!,如果没有要看detasheet 编写相应的驱动程序
    }


    展开全文
  • ADPCM_DIV4编解码,海思音频解码 车载监控实时码流音频编解码
  • 海思AAC编解码

    2019-04-02 20:16:45
    Hi3516A_SDK_V1.0.5.0_component-audio-AAC、Hi3516CV300_SDK_V2.0.2.0_component、Hi3531_SDK_V2.0.A.0_component、Hi3518_SDK_V1.0.9.0_componen_AMR_AAC
  • 海思3536解码G711音频

    千次阅读 2019-08-13 10:29:08
    而HI3536这款芯片是支持对G711进行CPU软件编解码的,所有的解码功能都基于独立封装的海思音频解码库,核心解码器工作在用户态,使用 CPU 软件解码。 对于海思的芯片来说,如果想要解码标准的G711音频数据的话,需要...

    海思3536解码G711音频


    最近的一个项目,需要增加对G711的解码功能。而HI3536这款芯片是支持对G711进行CPU软件编解码的,所有的解码功能都基于独立封装的海思音频解码库,核心解码器工作在用户态,使用 CPU 软件解码。
    对于海思的芯片来说,如果想要解码标准的G711音频数据的话,需要在G711音频数据流的每一帧前面都要加上一个海思的数据头,这样的G711音频数据才能被海思所解码。对于G711来说,HI3536能获取每帧数据长度为:N*40 (N 为[1,5]的任意正整数)。
    海思语音帧结构为:
    在这里插入图片描述
    代码处理:

    FILE* fp = fopen(argv[1], "rb");
    
    fseek(fp,0L,SEEK_END); //定位到文件末尾  
    int flen = ftell(fp); // 得到文件大小 
    
    fseek(fp,0L,SEEK_SET);// 回到文件头部
    
    printf("flen = %d\n",flen);
    
    int size  = 2 * 1024 * 1024;
    
    char* buffer = (char*)malloc(size);
    bzero(buffer,size);
    if(fp)
    {
    	fread(buffer, 1, size , fp);
    	fclose(fp);
    }
    
    int newlen = flen/200;
    if( flen %200 )
    {
    	newlen += 1;
    }
    
    printf("newlen = %d\n",newlen);
    
    newlen = flen + newlen*4;
    printf("newlen = %d\n",newlen);
    short * p = (short *)malloc(newlen);
    bzero(p,newlen);
    
    HisiVoiceAddHisiHeader((short *)buffer,(short *)p,200,flen);
    
    free(buffer);
    

    从标准的G711音频文件中读取数据,然后在按帧长度为200的间隔,对每个帧前加上一个海思的语音帧结构。

    对于3536解码G711的过程,参考了海思提供的SDK,其中有个音频解码的demo sample_audio.c,具体的代码就不做分析,只是介绍一下大体上是怎么实现的,有兴趣的可以自己去看该代码。

    G711解码流程:

    1. MMP系统初始化
    2. 设置音频输出设备属性,比如:采样率,数据宽度,I2S主从模式等
    3. 根据所设置的属性,创建ADEC通道
    4. 设置 AO 设备属性、启用 AO 设备、启用 AO 通道
    5. 数据源到数据接收者进行绑定
    6. 发送音频码流到音频解码通道

    大体上的流程就是这样,还是个小白,只是想将学习的过程记录下来.

    展开全文
  • 海思视频编解码VI图谱

    千次阅读 2018-05-21 10:32:45
     HI_MPI_AE_Register 海思的API,注册ISP单元AE,用来自动曝光  HI_MPI_AWB_Register 自动白平衡  HI_MPI_AF_Register 自动对焦  HI_MPI_ISP_MemInit 对ISP分配必要的内存  HI_MPI_ISP_SetWDRMode 设置宽...

    main 
    SAMPLE_VENC_1080P_CLASSIC
        SAMPLE_COMM_VI_GetSizeBySensor //step 1: init sys variable 
        SAMPLE_COMM_SYS_CalcPicVbBlkSize
        SAMPLE_COMM_SYS_GetPicSize

        SAMPLE_COMM_SYS_Init //step 2: mpp system init. 
            HI_MPI_SYS_Exit();
            HI_MPI_VB_Exit();
            HI_MPI_VB_SetConf
            HI_MPI_VB_Init
            HI_MPI_SYS_SetConf
            HI_MPI_SYS_Init

        SAMPLE_COMM_VI_StartVi //step 3: start vi dev & chn to capture
            IsSensorInput (判断是否传统还是现在的sensor)
            SAMPLE_COMM_VI_StartIspAndVi ()
                SAMPLE_COMM_VI_StartMIPI (step 1: mipi configure)
                    SAMPLE_COMM_VI_SetMipiAttr   操作sensor,对sensor做必要的初始化
                        open("/dev/hi_mipi", O_RDWR)
                        ioctl(fd, HI_MIPI_SET_DEV_ATTR, pstcomboDevAttr)
                    SAMPLE_COMM_ISP_Init (step 2:)  ISP:对图像(自动曝光之类)处理,一般外面加了处理芯片,所以一般不用3518E内部的ISP,所以一般关闭
                        sensor_register_callback  在Sensor驱动里面能找到,注册sensor的回调
                        HI_MPI_AE_Register 海思的API,注册ISP单元AE,用来自动曝光
                        HI_MPI_AWB_Register 自动白平衡
                        HI_MPI_AF_Register 自动对焦
                        HI_MPI_ISP_MemInit 对ISP分配必要的内存
                        HI_MPI_ISP_SetWDRMode 设置宽动态模式
                        HI_MPI_ISP_SetPubAttr 写入ISP单元内部,将来ISP会根据设的参数处理图像
                        HI_MPI_ISP_Init ISP系统初始化
                    SAMPLE_COMM_ISP_Run (step 3: run isp thread )ISP跑起来,HI3518E内部的ISP单元隶属于VI模块的
                        pthread_create(&gs_IspPid, &attr, (void* (*)(void*))Test_ISP_Run, NULL)
                            Test_ISP_Run
                                HI_MPI_ISP_Run
                    SAMPLE_COMM_VI_StartDev (step 4 : config & start vicap dev)
                        HI_MPI_VI_SetDevAttr 真正写入硬件单元生效
                        HI_MPI_ISP_GetWDRMode
                        HI_MPI_VI_SetWDRAttr
                        HI_MPI_VI_Ena bleDev Dev打开
                        SAMPLE_COMM_VI_StartChn (Step 5: config & start vicap chn (max 1))
                        HI_MPI_VI_SetChnAttr 设置Chn通道
                        HI_MPI_VI_SetRotate
                        HI_MPI_VI_EnableChn
                        SAMPLE_COMM_ISP_Stop
                        HI_MPI_ISP_Exit
                        HI_MPI_AF_UnRegister
                        HI_MPI_AWB_UnRegister
                        HI_MPI_AE_UnRegister
                        sensor_unregister_callback

        SAMPLE_COMM_SYS_GetPicSize //step 4: start vpss and vi bind vpss
            HI_MPI_VPSS_CreateGrp
            HI_MPI_VPSS_GetNRParam
            HI_MPI_VPSS_SetNRParam
            HI_MPI_VPSS_StartGrp
        SAMPLE_COMM_VPSS_StartGroup
        SAMPLE_COMM_VI_BindVpss
            SAMPLE_COMM_VI_Mode2Param
            HI_MPI_SYS_Bind
        SAMPLE_COMM_VPSS_EnableChn
            HI_MPI_VPSS_SetChnAttr
            HI_MPI_VPSS_SetExtChnAttr
            HI_MPI_VPSS_SetChnMode
            HI_MPI_VPSS_EnableChn
        SAMPLE_COMM_VENC_Start  //step 5: start stream venc
        SAMPLE_COMM_VENC_BindVpss
        SAMPLE_COMM_VENC_StartGetStream  //step 6: stream venc process -- get stream, then save it to file. 
        SAMPLE_COMM_VENC_StopGetStream  //step 7: exit process

    展开全文
  • 海思Hi3515编解码处理器用户手册,网上这款片子的资料比较少。。。
  • 海思 DVR 方案 3521嵌入式芯片H264 编解码处理器简介
  • 海思HiMPP视频子系统:视频系统初始化模块(MPP_SYS_CONF_S)、视频输入模块(VI)、视频前处理模块(VPSS)、视频编码模块(VENC)和视频输出模块(VO)的说明和API介绍及例子。
  • 海思推出强大的视频编解码芯片Hi365,能对视频以及音频进行H264编码,官方芯片手册仔细看,细心体会工作过程。
  • 海思3516CV300平台音频编解码库,包括aac,amr,amrwb,mp3等音频格式的编解码库,包含sample程序
  • 海思HiMPP视频编解码开发文档3.0,包括:视频系统初始化模块(MPP_SYS_CONF_S)、视频输入模块(VI)、视频前处理模块(VPSS)、视频编码模块(VENC)和视频输出模块(VO)
  • 海思 DVR 方案 3520D 嵌入式芯片H264 编解码处理器简介
  • 海思3518Ev200 AAC音频编解码库 , 这个资源你懂的。 需要的下载
  • 海思Hi35XX和Hi37XX系列编解码处理器简介,属于海思的官方文档,包括Hi3798MV100、Hi3520DV200、Hi3535、Hi3536C、Hi3536DV100和Hi3796MV200芯片的编解码处理器简介,对于要了解海思芯片的同学有一定的帮助
  • HI35XX平台音视频编解码程序demo样例是基于海思平台做的,主要是演示海思凭条芯片如何进行音视频解码,给程序编写提供一些设计参考。
  • 海思MPP测试代码,包括:视频系统初始化模块(MPP_SYS_CONF_S)、视频输入模块(VI)、视频前处理模块(VPSS)、视频编码模块(VENC)和视频输出模块(VO)
  • 海思Hi3515 H.264编解码处理器简介
  • 这里主要讲解海思sample\common\sample_comm_vdec.c文件中SAMPLE_COMM_VDEC_SendStream函数的代码。 SAMPLE_COMM_VDEC_SendStream是一个线程。 代码段1: //cStreamFile为视频文件完整路径 snprintf...

    这里主要讲解海思sample\common\sample_comm_vdec.c文件中SAMPLE_COMM_VDEC_SendStream函数的代码。

    SAMPLE_COMM_VDEC_SendStream是一个线程。

    代码段1:

    //cStreamFile为视频文件完整路径
        snprintf(cStreamFile, sizeof(cStreamFile), "%s/%s", pstVdecThreadParam->cFilePath,pstVdecThreadParam->cFileName);
        if(cStreamFile != 0)
        {
            fpStrm = fopen(cStreamFile, "rb");   // 打开视频文件
            if(fpStrm == NULL)
            {
                SAMPLE_PRT("chn %d can't open file %s in send stream thread!\n", pstVdecThreadParam->s32ChnId, cStreamFile);
                return (HI_VOID *)(HI_FAILURE);
            }
        }
    	// pu8Buf用于读取视频文件中读取的数据
        pu8Buf = malloc(pstVdecThreadParam->s32MinBufSize);//(1920X1080*3)/2
        if(pu8Buf == NULL)
        {
            SAMPLE_PRT("chn %d can't alloc %d in send stream thread!\n", pstVdecThreadParam->s32ChnId, pstVdecThreadParam->s32MinBufSize);
            fclose(fpStrm);
            return (HI_VOID *)(HI_FAILURE);
        }
        fflush(stdout);
    
        u64PTS = pstVdecThreadParam->u64PtsInit;

    这段代码很简单,就是使用fopen打开视频文件,然后分配读取一帧图像的视频空间内存大小。这里补充,因为是YVU420空间,即每4个Y分量共用一个UV分量,因此UV分量的尺寸只有原来的四分之一,因此s32MinBufSize的大小为图像宽度x图像高度x3/2。

    代码段2:

        while (1)
        {
            if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_STOP)
            {
                break;
            }
            else if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_PAUSE)
            {
                sleep(1);
                continue;
            }
    
            bEndOfStream = HI_FALSE;
            bFindStart   = HI_FALSE;
            bFindEnd     = HI_FALSE;
            u32Start     = 0;
            fseek(fpStrm, s32UsedBytes, SEEK_SET);// 文件指针定位到s32UsedBytes位置
            s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);  // 读取一帧图像数据到pu8Buf
            if (s32ReadLen == 0)  // 读取文件完毕
            {
                if (pstVdecThreadParam->bCircleSend == HI_TRUE) // 循环读取
                {
                    memset(&stStream, 0, sizeof(VDEC_STREAM_S) );
                    stStream.bEndOfStream = HI_TRUE;
                    HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1); // 向视频解码通道发送码流数据
    
                    s32UsedBytes = 0;
                    fseek(fpStrm, 0, SEEK_SET);// 再定位到文件头
                    s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
                }
                else
                {
                    break;  // 非循环读取,结束
                }
            }
    

    我们再来看第2个代码段, 这是一个while循环,循环从文件中读取数据去做解码

    fseek(fpStrm, s32UsedBytes, SEEK_SET)将文件指针位置定位到s32UsedBytes处,一开始为0位置,s32UsedBytes是变量随着whiile循环逐渐变大。 

    s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);读取一帧数据到pu8Buf,一帧数据大小就是上面说的s32MinBufSize。

    这里有一个判断if (s32ReadLen == 0) ,即判断文件数据是否已读取完毕,如果读取完毕,再判断是否循环读取。不过不是,则break 出 while循环,结束。如果是循环读取,则将stStream清空后再发给到VDEC,之后再将文件指针定位到开头处,再从头开始读取一帧。

    代码段3:

            // 解码264视频文件
            if (pstVdecThreadParam->s32StreamMode==VIDEO_MODE_FRAME && pstVdecThreadParam->enType == PT_H264)
            {
                // 找到一个条带(slice)位置
                for (i=0; i<s32ReadLen-8; i++)
                {
                    int tmp = pu8Buf[i+3] & 0x1F;
                    if (  pu8Buf[i] == 0 && pu8Buf[i+1] == 0 && pu8Buf[i+2] == 1 &&
                           (  ((tmp == 0x5 || tmp == 0x1) && ((pu8Buf[i+4]&0x80) == 0x80)) ||
                               (tmp == 20 && (pu8Buf[i+7]&0x80) == 0x80) )
                       )
                    {
                        bFindStart = HI_TRUE;
                        i += 8;
                        break;
                    }
                }
    
                // 找到下一帧数据流的开始位置
                for (; i<s32ReadLen-8; i++)
                {
                    int tmp = pu8Buf[i+3] & 0x1F;
                    if (  pu8Buf[i] == 0 && pu8Buf[i+1] == 0 && pu8Buf[i+2] == 1 &&
                                (tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6 ||
                           ((tmp == 5 || tmp == 1) && ((pu8Buf[i+4]&0x80) == 0x80))||
                            (tmp == 20 && (pu8Buf[i+7]&0x80) == 0x80) ))
                    {
                        bFindEnd = HI_TRUE;
                        break;
                    }
                }
    
                if(i>0)s32ReadLen = i;
                if (bFindStart == HI_FALSE)
                {
                    SAMPLE_PRT("chn %d can not find H264 start code!s32ReadLen %d, s32UsedBytes %d.!\n",
                        pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);
                }
                if (bFindEnd == HI_FALSE)
                {
                    s32ReadLen = i+8;
                }
    
            }

    这段代码的作用是找到视频文件数据流中一帧的数据长度,怎么找呢?根据H.264文件的视频流结构。这里有两个for循环,第1个for从零开始查到,直到符合条件,得到一个i值,第二个for在第1个for的基础上继续查找,再得到一个i值,i值赋值给s32ReadLen,这个就是要读取的数据长度。我们来看两个for查到的是什么东西。

    for循环里有(pu8Buf[i+3] & 0x1F)接触过H.264的就很容易知道,这个就是nal_uint_type值,,

    我们再次列出这个值的意义,如下:

    代码中第一个for循环要求tmp等于0x5或0x1,也就是说是IDR或者非IDR,简单来说就是I 条带、P条带、B条带,这里不能说是I帧,因为SPS,PPS也属于I帧的一部分,但代码里不是从SPS开始,而是要从条带开始。

    补充说明:
    (1)IDR帧肯定为I帧
    (2)I帧包含了SPS, PPS, I条带
    (3)P帧包含P条带;B帧包含B条带

    我们来看一段视频的二进制流,我们直接看I Slice:

    (0x65&0x1F)等于0x5符合tmp的要求。第2个要求是((pu8Buf[i+4]&0x80) == 0x80),也就是说pu8Buf[i+4]要大于等于0x80,以上I Slice 符合要求。

    我们可以再看下P Slice的开头,也是符合要求的。

    我们在找一个有B帧的视频来看,如下,也是符合要求的。

    因此以上第一个for循环的作用是找到I、P 、B的开始位置,即当前的i值(并自加8),这里第一个for循环结束。

     

    第2个for循环,tmp的条件更多,第1个条件tmp == 15 || tmp == 7 || tmp == 8 || tmp == 6,也就是说,nal单元为15, SPS, PPS, SEI其中之一即可,很明显,除了15以外,这是I帧的开始位置。再来看后面的条件: ((tmp == 5 || tmp == 1) && ((pu8Buf[i+4]&0x80) == 0x80)) || (tmp == 20 && (pu8Buf[i+7]&0x80) == 0x80),与第1个for循环是一致的。因此第2个for循环就是要找到下一个NAL单元的开始位置,得到此时的位置值i,将i赋值给到s32ReadLen。

    结合两个for循环来看,其实就是找到一帧的数据长度,假设视频文件流为SPS, PPS, I Slice,P Slice,那么i的位置就是P Slice的开始位置,因此i就包括了SPS, PPS, I Slice的长度,这三者组成了一个I帧。

    代码段4:

            stStream.u64PTS       = u64PTS;//0
            stStream.pu8Addr      = pu8Buf + u32Start; // 码流包的地址
            stStream.u32Len       = s32ReadLen;  // 一帧的长度
            stStream.bEndOfFrame  = (pstVdecThreadParam->s32StreamMode==VIDEO_MODE_FRAME)? HI_TRUE: HI_FALSE;  // 当前帧是否结束
            stStream.bEndOfStream = bEndOfStream; 
            stStream.bDisplay     = 1;// 当前帧是否输出显示
    
    SendAgain:
            s32Ret=HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, pstVdecThreadParam->s32MilliSec);
            if( (HI_SUCCESS != s32Ret) && (THREAD_CTRL_START == pstVdecThreadParam->eThreadCtrl) )
            {
                usleep(pstVdecThreadParam->s32IntervalTime);
                goto SendAgain;
            }
            else
            {
                bEndOfStream = HI_FALSE;
                s32UsedBytes = s32UsedBytes +s32ReadLen + u32Start;
                u64PTS += pstVdecThreadParam->u64PtsIncrease;
            }
            usleep(pstVdecThreadParam->s32IntervalTime);

    根据sample_vdec.c中的设定,解码H.264是采用了VIDEO_MODE_FRAME模式解码,即以帧方式发送码流。

    u64PTS:这里的u64PTS虽然有pstVdecThreadParam->u64PtsIncrease,但pstVdecThreadParam->u64PtsIncrease为0(上图),解码器不会更改此值,其帧率控制控制由VO来控制。

    u32Start:在解码JPEG才用到,解码H.264和H.265都为0。

    s32ReadLen:就是之前两个for循环得到的帧长度。

    bEndOfFrame:当前帧是否结束,仅 COMPAT 模式发送码流时有效,即当解码JPEG时才有效。

    bEndOfStream :是否发完所有码流,根据之前的代码段,只有当读取到最后一帧时,bEndOfStream才被置为HI_TRUE,其他时候都为HI_FALSE,而且每次解码完后都被置为HI_FALSE。

    s32UsedBytes:这个参数是定位文件指针的位置的,之前提到过,开头时该值为0,这里自增s32ReadLen + u32Start,即加上一帧的长度,下次就跳到s32ReadLe的位置开始读取数据。

    s32IntervalTime:值为1000,即usleep了一毫秒。

    好了,目前就讲到这里,重点就是讲了VDEC是如何区分两个帧的。

    展开全文
  • 海思Hi3520 H.264编解码处理器用户指南
  • 海思Hi3515 H.264编解码处理器用户指南
  • Hi3520DV300_H.264编解码处理器简介
  • 海思Hi3511/Hi3512 H.264编解码处理器用户指南
  • 华为海思_Hi3531_H.264编解码处理器用户指南_-1182页
  • 华为海思HI3536 H.264-H.265编解码开发手册 --高清扫描版
  • 海思Hi3531 H.264编解码处理器官方硬件原理图PCB文件+硬件参考设计资料
  • Hi3510既可以作为独立的编码器工作,也可以作为独立的解码器工作,也可以同时编解码工作,充分考虑到了编解码市场的各种应用场合。Hi3510是一个典型的多应用的单芯片解决方案,大大降低了设备的BOM组成和成本。如图2...
  • 整理对比了三个海思编解码处理芯片的详细参数,供设计选型使用 整理对比了三个海思编解码处理芯片的详细参数,供设计选型使用 整理对比了三个海思编解码处理芯片的详细参数,供设计选型使用
  • Frame base/Line base WDR和 Local Tone Mapping *提供PC端ISP tuning tools 音频编解码 *通过软件实现多协议语音编解码 *支持G.711/G.726/AAC/等音频编码格式 *支持音频3A(AEC/ANR/ALC)处理 安全引擎 *硬件...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 178
精华内容 71
关键字:

海思编解码