您尚未登录。

楼主 #1 2018-04-05 18:26:37

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

参考链接1: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据
参考链接2: 把NV12格式的视频原始数据, 传送给V3s的编解码器,让其输出h.264码流


1. ubuntu 安装 视频编解码工具 avconv:

sudo apt-get install libav-tools

windows下载 vlc-3.0.1-win32.exe 并安装.

2. 使用avconv工具把 mp4格式的h.264视频文件解码成NV12格式:

avconv -i demp.mp4 -vf pad="trunc((iw+31)/32)*32" -vf pad="trunc((iw+31)/32)*32"  -pix_fmt nv12 -f rawvideo demo.nv12

demo.mp4 是输入文件
demo.nv12 是输出文件
nv12是输出格式

3.使用vlc打开nv12文件:

QQ20180405183634.png

点击 【文件】 -> 【打开多个文件】-> 【添加】第二步生成的demo.nv12 文件
编辑选项填写好格式即可播放。

:demux=rawvideo :rawvid-width=640 :rawvid-height=480 :rawvid-chroma=NV12  :rawvid-fps=5





离线

楼主 #2 2018-04-05 18:42:51

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

按上面的步骤依次执行,  保证生成的NV12文件正确无误,即可完成大象装到冰箱的艰难一步。





离线

#3 2018-04-05 21:23:10

kgp0213
会员
注册时间: 2018-01-15
已发帖子: 149
积分: 149

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

翘首期待

离线

#4 2020-05-13 14:04:26

sunbird606
会员
注册时间: 2020-02-10
已发帖子: 17
积分: 107

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

坐在这里敲碗等着晕哥

离线

楼主 #5 2020-12-19 19:28:55

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,223
积分: 9197

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

linux3.4 bsp linux 摄像头NV12格式原始视频格式数据采集源码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>           
#include <fcntl.h>            
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
 
#include <asm/types.h>        
#include <linux/videodev2.h>

#define BUF_NUM                         4
#define FRAMESINBUF                     1

struct CJ_Buffer {
        void *memory;
        int length;
};

struct CJ_Buffer *gpV4l2Buf;
 
int gMemMapLen;

int file_fd;
char *dev_name = "/dev/video0";
int fd;


int getFullSize(int * full_w, int * full_h)
{
    struct v4l2_frmsizeenum size_enum;
    size_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    size_enum.pixel_format = V4L2_PIX_FMT_NV12;
    size_enum.index = 0;
    if (-1 == ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &size_enum))
    {
        perror("VIDIOC_ENUM_FRAMESIZES failed");  
        return 0;   
    }
    
    *full_w = size_enum.discrete.width;
    *full_h = size_enum.discrete.height;

        printf("getFullSize: %dx%d\n", *full_w, *full_h);
    
    return 1;
}

int tryFmtSize(int *width, int *height)
{
    int ret = -1;
    struct v4l2_format fmt;

    printf("%dx%d", *width, *height);

    memset(&fmt, 0, sizeof(fmt));
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width  = *width;
    fmt.fmt.pix.height = *height;

    //fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    //fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
    //fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;

    fmt.fmt.pix.field = V4L2_FIELD_NONE;

    ret = ioctl(fd, VIDIOC_TRY_FMT, &fmt);
    if (ret < 0)
    {
        perror("VIDIOC_TRY_FMT failed");
        return ret;
    }

    // driver surpport this size
    *width = fmt.fmt.pix.width;
    *height = fmt.fmt.pix.height;

    return 0;
}

int setContrastValue(int value)
{
    int ret = -1;
    struct v4l2_control ctrl;

    ctrl.id = V4L2_CID_CONTRAST;
    ctrl.value = value;
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0) {
        perror("VIDIOC_S_CTRL failed");
    } else {
        printf("setContrastValue ok\n");
    }

    return ret;
}
int setBrightnessValue(int value)
{
    struct v4l2_control ctrl;
    int ret = -1;

    ctrl.id = V4L2_CID_BRIGHTNESS;
    ctrl.value = value;
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0) {
        perror("VIDIOC_S_CTRL failed");
    } else {
        printf("setBrightnessValue ok\n");
    }
    return ret;
}

int setSaturationValue(int value)
{
    struct v4l2_control ctrl;
    int ret = -1;

    ctrl.id = V4L2_CID_SATURATION;
    ctrl.value = value;
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0) {
        perror("VIDIOC_S_CTRL failed");
    } else {
        printf("setSaturationValue ok\n");
    }
    return ret;
}

int setSharpnessValue(int value)
{
    struct v4l2_control ctrl;
    int ret = -1;

    ctrl.id = V4L2_CID_SHARPNESS;
    ctrl.value = value;
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0) {
        perror("VIDIOC_S_CTRL failed");
    } else {
        printf("setSharpnessValue ok\n");
    }
    return ret;
}

int setHueValue(int value)
{
    struct v4l2_control ctrl;
    int ret = -1;

    ctrl.id = V4L2_CID_HUE;
    ctrl.value = value;
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0) {
        perror("VIDIOC_S_CTRL failed");
    } else {
        printf("setHueValue ok\n");
    }

    return ret;
}

int setHflip(int value)
{
    struct v4l2_control ctrl;
    int ret = -1;
    
    ctrl.id = V4L2_CID_HFLIP_THUMB;
    ctrl.value = value;
    printf("V4L2CameraDevice::setHflip value=%d\n", value);
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0)
    {
        //setSharpnessValue failed
        perror("setHflip thumb failed\n");
    }
    ctrl.id = V4L2_CID_HFLIP;
    ctrl.value = value;
    printf("V4L2CameraDevice::setHflip value=%d\n", value);
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0)
    {
        //setSharpnessValue failed
        perror("setHflip failed\n");
    }
    return ret;
}

int setVflip(int value)
{
    struct v4l2_control ctrl;
    int ret = -1;
    
    ctrl.id = V4L2_CID_VFLIP_THUMB;
    ctrl.value = value;
    printf("V4L2CameraDevice::setVflip value=%d\n", value);
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0)
    {
        //setSharpnessValue failed
        perror("setVflip thumb failed111\n");
    }
    ctrl.id = V4L2_CID_VFLIP;
    ctrl.value = value;
    printf("V4L2CameraDevice::setVflip value=%d\n", value);
    ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
    if (ret < 0)
    {
        //setSharpnessValue failed
        perror("setVflip failed111\n");
    }

    return ret;
}

int v4l2setCaptureParams(int framerate)
{
    printf("framerate=%d", framerate);
    int ret = -1;
    
    struct v4l2_streamparm params;
    params.parm.capture.timeperframe.numerator = 1;
    params.parm.capture.timeperframe.denominator = framerate;
    params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    params.parm.capture.capturemode = V4L2_MODE_VIDEO;

    printf("VIDIOC_S_PARM mFrameRate: %d, capture mode: %d\n", framerate, params.parm.capture.capturemode);

    ret = ioctl(fd, VIDIOC_S_PARM, &params);
    if (ret < 0) {
        perror("VIDIOC_S_PARM failed");
    } else {
        printf("v4l2setCaptureParams ok\n");
    }

    return ret;
}

void v4l2SetVideoParams(int width, int height, int sub_w, int sub_h, unsigned int pix_fmt)
{
    struct v4l2_format format;

    printf("main:%dx%d, sub:%dx%d, pfmt: 0x%x\n", width, height, sub_w, sub_h, pix_fmt);
    memset(&format, 0, sizeof(format));
    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    format.fmt.pix.width  = width;
    format.fmt.pix.height = height;
    //format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    //format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
    //format.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
    format.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
    format.fmt.pix.field = V4L2_FIELD_NONE;

    if ((sub_w > 0 && sub_w < width) && (sub_h > 0 && sub_h < height)) {
        struct v4l2_pix_format sub_fmt;
        memset(&sub_fmt, 0, sizeof(sub_fmt));
        format.fmt.pix.subchannel = &sub_fmt;
        format.fmt.pix.subchannel->width = sub_w;
        format.fmt.pix.subchannel->height = sub_h;
        format.fmt.pix.subchannel->pixelformat = pix_fmt;
        format.fmt.pix.subchannel->field = V4L2_FIELD_NONE;
        format.fmt.pix.subchannel->rot_angle = 0;
        printf("sub_w=%d, sub_h=%d\n", sub_w, sub_h);
    }

    if (ioctl(fd, VIDIOC_S_FMT, &format) < 0)
    {
        perror("VIDIOC_S_FMT failed");
        return;
    }

    return;
}

void initV4l2Buffer()
{
    gpV4l2Buf = (struct CJ_Buffer *)malloc(sizeof(struct CJ_Buffer) * BUF_NUM);
    if (gpV4l2Buf == NULL) {
        perror("alloc V4l2Buffer_tag error!!");
        return;
    }
    memset(gpV4l2Buf, 0, sizeof(struct CJ_Buffer) * BUF_NUM);
}

void setFramesInV4L2BufNum()
{
        unsigned int nFramesInBuf = FRAMESINBUF;
    printf("mFramesInV4l2buf=%u\n", FRAMESINBUF);
    if (ioctl (fd, VIDIOC_SET_NFRAME_BUF, &nFramesInBuf) < 0) {
        perror("VIDIOC_SET_NFRAME_BUF failed");
    }
}

int v4l2ReqBufs(int * buf_cnt)
{
    int ret = 0;
    struct v4l2_requestbuffers rb;

    printf("TO VIDIOC_REQBUFS count: %d\n", *buf_cnt);

    memset(&rb, 0, sizeof(rb));
    rb.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    rb.memory = V4L2_MEMORY_MMAP;
    rb.count  = *buf_cnt;

    ret = ioctl(fd, VIDIOC_REQBUFS, &rb);
    if (ret < 0)
    {
        perror("VIDIOC_REQBUFS failed");
        return ret;
    }

    *buf_cnt = rb.count;
    printf("VIDIOC_REQBUFS count: %d\n", *buf_cnt);

    return 1;
}

int v4l2QueryBuf()
{
        int i;
    int ret = 0;
    struct v4l2_buffer buf;

    for (i = 0; i < BUF_NUM; i++)
    {
        memset (&buf, 0, sizeof (struct v4l2_buffer));
        buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index  = i;

        ret = ioctl (fd, VIDIOC_QUERYBUF, &buf);
        if (ret < 0)
        {
            perror("VIDIOC_QUERYBUF failed");
            return ret;
        }

        gpV4l2Buf[i].memory = mmap(0, buf.length,
                                PROT_READ | PROT_WRITE, 
                                MAP_SHARED, 
                                fd, 
                                buf.m.offset);

                gMemMapLen = buf.length;
        printf("index: %d, mem: %x, len: %d, offset: %x\n", i, (int)gpV4l2Buf[i].memory, buf.length, buf.m.offset);
 
        if (gpV4l2Buf[i].memory == MAP_FAILED)
        {
            perror("mmap failed");
            return -1;
        }
        }

    for (i = 0; i < BUF_NUM; i++)
    {
        memset (&buf, 0, sizeof (struct v4l2_buffer));
        buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index  = i;
        // start with all buffers in queue
        ret = ioctl(fd, VIDIOC_QBUF, &buf);
        if (ret < 0)
        {
            perror("VIDIOC_QBUF failed");
            return ret;
        }
    }

    return 1;
}

int v4l2StartStreaming()
{
    int ret = 0;
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    ret = ioctl (fd, VIDIOC_STREAMON, &type);
    if (ret < 0)
    {
        perror("VIDIOC_STREAMON failed");
        return ret;
    }

    return 1;
}

int v4l2StopStreaming()
{
    int ret = 0;
    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    ret = ioctl (fd, VIDIOC_STREAMOFF, &type);
    if (ret < 0)
    {
        perror("VIDIOC_STREAMOFF failed");
        return ret;
    }
    printf("V4L2Camera::v4l2StopStreaming ok\n");

    return 1;
}

int v4l2UnmapBuf()
{
        int i;
    int ret = 0;

    for (i = 0; i < BUF_NUM; i++)
    {
        ret = munmap(gpV4l2Buf[i].memory, gMemMapLen);
        if (ret < 0)
        {
            perror("munmap failed");
            return ret;
        }

        gpV4l2Buf[i].memory = NULL;
    }

    return 1;
}

int main (int argc,char ** argv)
{
        struct v4l2_capability cap;
        struct v4l2_format fmt;
        struct v4l2_pix_format sub_fmt;
        struct v4l2_requestbuffers req;
        struct v4l2_buffer buf; 
    struct v4l2_input inp;
        unsigned int i;
        enum v4l2_buf_type type;
        
        int width, height;
     
     
        fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);

        ioctl (fd, VIDIOC_QUERYCAP, &cap);
        printf("Driver Name:%s\n Card Name:%s\n Bus info:%s\n\n", cap.driver, cap.card, cap.bus_info);
        printf("capabilities:%d\n", cap.capabilities);
        
    if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0 &&
                (cap.capabilities & V4L2_CAP_STREAMING) == 0) 
    {
        perror("cap capabilities format fail");  
        return -2 ;   
    }


    inp.index = 0;
    if (-1 == ioctl(fd, VIDIOC_S_INPUT, &inp))
    {
        perror("VIDIOC_S_INPUT error!");  
        return -2 ;   
    }
        
        getFullSize(&width, &height);
        
        width = 640; height = 480;
        /*tryFmtSize(&width, &height);
        setContrastValue(50);
        setBrightnessValue(50);
        setSaturationValue(0);
        setSharpnessValue(10);
        setHueValue(30);
        setHflip(0);
        setVflip(0);*/
        
        v4l2setCaptureParams(30);
        v4l2SetVideoParams(640, 480, 320, 240, V4L2_PIX_FMT_NV12);
        
        initV4l2Buffer();
        setFramesInV4L2BufNum();

    int buf_cnt = BUF_NUM;
    v4l2ReqBufs(&buf_cnt);
        
        v4l2QueryBuf();
        v4l2StartStreaming();
        
        //for (i = 0; i < 10; i++)
        //      sleep(1);

    //struct v4l2_control ctrl;

   // ctrl.id = V4L2_CID_TAKE_PICTURE;
    //if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
  //      perror("VIDIOC_S_CTRL failed");
  //  } else {
  //      perror("setTakePictureCtrl ok\n");
 //   }
        
        
        FILE* fp = fopen("test2.nv12", "w");
        if(fp == NULL)
        {
                printf("open file error.\n");
                goto end;
        }

        for (i = 0; i < 200; i++)
        {
                fd_set fds;

                FD_ZERO(&fds);
                FD_SET(fd, &fds);

                select(fd + 1, &fds, NULL, NULL, NULL);

            memset(&buf, 0, sizeof(struct v4l2_buffer));
                buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                buf.memory = V4L2_MEMORY_MMAP;
                ioctl(fd, VIDIOC_DQBUF, &buf);

            void *pMem = gpV4l2Buf[buf.index].memory;
                printf("frame addr = %x, length=%d, %d\n", (unsigned int)pMem, gpV4l2Buf[buf.index].length, buf.length);

                fwrite(pMem, 640 * 480 * 3 / 2, 1, fp);
#if 0
                if (i == 199)
                {
                        file_fd = open("test.jpg", O_RDWR | O_CREAT, 0777);
                        write(file_fd, pMem, 640 * 480 * 3 / 2);
                        close (file_fd);
                        printf("frame index = %d, size = %d.\n", buf.index, buf.length);
                }
#endif
                ioctl(fd, VIDIOC_QBUF, &buf);
        }

end:
        fclose(fp);     
        v4l2StopStreaming();
        v4l2UnmapBuf();
        

        close (fd);
        printf("Camera Done.\n");


        return 0;
}

b5fdce65aa04d77f1066453a0468ffe8.png

1a3b4bb98783a39ad0c052ba7c25e45f.png

NV12录像文件下载: nv12_data.7z





离线

#6 2021-01-10 21:29:04

歌以咏志
会员
注册时间: 2019-09-21
已发帖子: 219
积分: 210

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

试一试 Qt5 运行 OpenGL 程序
http://whycan.com/t_5820.html#p57901
(出处:哇酷开发者社区【计算机图形/GUI/RTOS/FileSystem/OpenGL/DirectX/SDL2】)


https://rawpixels.net/ (貌似要科学上网)

试了一下, 可以显示:

QQ截图20210110212335.png

离线

#7 2021-03-21 19:10:44

九重天
会员
注册时间: 2020-10-06
已发帖子: 25
积分: 17.5

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

歌以咏志 说:

试一试 Qt5 运行 OpenGL 程序
http://whycan.com/t_5820.html#p57901
(出处:哇酷开发者社区【计算机图形/GUI/RTOS/FileSystem/OpenGL/DirectX/SDL2】)


https://rawpixels.net/ (貌似要科学上网)

试了一下, 可以显示:

https://whycan.com/files/members/2003/QQ截图20210110212335.png

这个在线工具不错, 没想到这么直观,搞解码必备啊.

离线

#8 2022-02-25 15:32:06

memory
会员
注册时间: 2021-08-11
已发帖子: 206
积分: 181

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

@歌以咏志

https://rawpixels.net/ (貌似要科学上网)

这个好, 现学现用:

D1 哪吒解码视频文件测试
https://bbs.aw-ol.com/topic/1078/share/2

离线

#9 2023-04-02 11:48:12

memory
会员
注册时间: 2021-08-11
已发帖子: 206
积分: 181

Re: 把mp4格式的h.264视频文件解码成NV12格式, 并使用VLC播放 / V3s 摄像头录制成NV12原始数据

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn