50、OAK的VideoEncoder节点编码h265和使用ffmpeg进行解码播放

基本思想:幸亏会一点点ffmpeg的视频编解码进行了视频播放,本篇博客教你如何直接解码h265进行视频播放,还得立下flag 要学如何硬解码

50、OAK的VideoEncoder节点编码h265和使用ffmpeg进行解码播放_第1张图片

cmakelists.txt

cmake_minimum_required(VERSION 3.16)
project(depthai)
set(CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
#message(STATUS ${OpenCV_INCLUDE_DIRS})
#添加头文件
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/include/utility)
#链接Opencv库
find_package(depthai CONFIG REQUIRED)
add_executable(depthai main.cpp include/utility/utility.cpp)
target_link_libraries(depthai ${OpenCV_LIBS}  depthai::opencv -lavformat -lavcodec -lswscale -lavutil -lz)

main.cpp


#include 
#include 
#include 
#include 
#include 
#include 

extern "C"
{
#include 
#include 
#include 
#include 
}


#include "utility.hpp"

#include "depthai/depthai.hpp"

using namespace std::chrono;

int main(int argc, char **argv) {
    dai::Pipeline pipeline;
    //定义
    auto cam = pipeline.create();
    cam->setBoardSocket(dai::CameraBoardSocket::RGB);
    cam->setResolution(dai::ColorCameraProperties::SensorResolution::THE_1080_P);
    cam->setVideoSize(1920, 1080);
    auto Encoder = pipeline.create();
    Encoder->setDefaultProfilePreset(cam->getVideoSize(), cam->getFps(),
                                     dai::VideoEncoderProperties::Profile::H265_MAIN);


    cam->video.link(Encoder->input);


    //定义输出
    auto xlinkoutpreviewOut = pipeline.create();
    xlinkoutpreviewOut->setStreamName("out");

    Encoder->bitstream.link(xlinkoutpreviewOut->input);


    //结构推送相机
    dai::Device device(pipeline);
    //取帧显示
    auto outqueue = device.getOutputQueue("out", cam->getFps(), false);//maxsize 代表缓冲数据


    auto videoFile = std::ofstream("video.h265", std::ios::binary);


    int width = 1920;
    int height = 1080;
    AVCodec *pCodec = avcodec_find_decoder(AV_CODEC_ID_H265);
    AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec);
    int ret = avcodec_open2(pCodecCtx, pCodec, NULL);
    if (ret < 0) {//打开解码器
        printf("Could not open codec.\n");
        return -1;
    }
    AVFrame *picture = av_frame_alloc();
    picture->width = width;
    picture->height = height;
    picture->format = AV_PIX_FMT_YUV420P;
    ret = av_frame_get_buffer(picture, 1);
    if (ret < 0) {
        printf("av_frame_get_buffer error\n");
        return -1;
    }
    AVFrame *pFrame = av_frame_alloc();
    pFrame->width = width;
    pFrame->height = height;
    pFrame->format = AV_PIX_FMT_YUV420P;
    ret = av_frame_get_buffer(pFrame, 1);
    if (ret < 0) {
        printf("av_frame_get_buffer error\n");
        return -1;
    }
    AVFrame *pFrameRGB = av_frame_alloc();
    pFrameRGB->width = width;
    pFrameRGB->height = height;
    pFrameRGB->format = AV_PIX_FMT_RGB24;
    ret = av_frame_get_buffer(pFrameRGB, 1);
    if (ret < 0) {
        printf("av_frame_get_buffer error\n");
        return -1;
    }


    int picture_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, width, height,
                                                1);//计算这个格式的图片,需要多少字节来存储
    uint8_t *out_buff = (uint8_t *) av_malloc(picture_size * sizeof(uint8_t));
    av_image_fill_arrays(picture->data, picture->linesize, out_buff, AV_PIX_FMT_YUV420P, width,
                         height, 1);
    //这个函数 是缓存转换格式,可以不用 以为上面已经设置了AV_PIX_FMT_YUV420P
    SwsContext *img_convert_ctx = sws_getContext(width, height, AV_PIX_FMT_YUV420P,
                                                 width, height, AV_PIX_FMT_RGB24, 4,
                                                 NULL, NULL, NULL);
    AVPacket *packet = av_packet_alloc();


    while (true) {

        auto h265Packet = outqueue->get();
        videoFile.write((char *) (h265Packet->getData().data()), h265Packet->getData().size());

        packet->data = (uint8_t *) h265Packet->getData().data();    //这里填入一个指向完整H264数据帧的指针
        packet->size = h265Packet->getData().size();        //这个填入H265 数据帧的大小
        packet->stream_index = 0;
        ret = avcodec_send_packet(pCodecCtx, packet);
        if (ret < 0) {
            printf("avcodec_send_packet \n");
            continue;
        }
        av_packet_unref(packet);
        int got_picture = avcodec_receive_frame(pCodecCtx, pFrame);
        av_frame_is_writable(pFrame);
        if (got_picture < 0) {
            printf("avcodec_receive_frame \n");
            continue;
        }

        sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
                  height,
                  pFrameRGB->data, pFrameRGB->linesize);


        cv::Mat mRGB(cv::Size(width, height), CV_8UC3);
        mRGB.data = (unsigned char *) pFrameRGB->data[0];
        cv::Mat mBGR;
        cv::cvtColor(mRGB, mBGR, cv::COLOR_RGB2BGR);

        cv::imshow("demo", mBGR);
        cv::waitKey(1);


    }


    return 0;
}

测试结果

你可能感兴趣的:(硬件的基本知识,ffmpeg)