ffmpeg对接darknet优化

该博客详细介绍了如何使用ffmpeg对接darknet进行视频流处理优化,包括连接设置、解码过程、图像格式转换,并展示了对接YOLO模型进行目标检测的实现。涉及关键步骤如avformat_open_input、avcodec_open2、图像数据转换等,以及优化操作,如选择合适的图像格式和大小以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include "H264DecoderThread.h"
#include "Poco/Thread.h"  
#include<iostream>
#include<fstream>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

using namespace std;
using Poco::Thread;

FFmpegErrorCode H264DecoderThread::connect()
{
    AVDictionary *opts = 0;
    av_dict_set(&opts, "rtsp_transport", "tcp", 0);
    av_dict_set(&opts, "stimeout", "1000000", 0);
    FFmpegErrorCode res = FFmpeg_NoError;

    printf("H264DecoderThread connect()\n");

    do 
    {
        if (avformat_open_input(&m_pFormatCtx, m_strMrl.c_str(), NULL, &opts) != 0)
        {
            res = FFmpeg_ConnectFail;
            break;
        }

        if (avformat_find_stream_info(m_pFormatCtx, NULL) < 0)
        {
            res = FFmpeg_FindStreamInfo;
            break;
        }

        m_nVideoStreamIndex = av_find_best_stream(m_pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
        if (m_nVideoStreamIndex < 0)
        {
            res = FFmpeg_FindBestStream;
            break;
        }
        AVStream* st = m_pFormatCtx->streams[m_nVideoStreamIndex];
        AVCodec *pCodec = avcodec_find_decoder(st->codec->codec_id);
        if (!pCodec || avcodec_open2(st->codec, pCodec, NULL) < 0)
        {
            res = FFmpeg_FindDecoder;
            break;
        }
    } while (false);
    if (res != FFmpeg_NoError)
    {
        avformat_close_input(&m_pFormatCtx);
    }
    else
    {
        m_bConnected = true;

        string names_file = "coco.names";
        string cfg_file = "yolov3.cfg";
        string weights_file = "yolov3.weights";

       pDetector = new Detector(cfg_file, weights_file);
        
        if (pDetector == NULL) 
        {
            printf("error pDetector == NULL\n");
        }

        #if 0
        m_dst_pix_fmt = AV_PIX_FMT_RGB24;
        m_dst_w = 1280;
        m_dst_h = 720;
        m_dst_c = 3;
        #else
        m_dst_pix_fmt = AV_PIX_FMT_BGR24;
        m_dst_w = 416;
        m_dst_h = 416;
        m_dst_c = 3;
        #endif
        
    }
    av_dict_free(&opts);
    return res;
}

void H264DecoderThread::AddTask(PicInfo &picInfo)
{
    
    printf("H264DecoderThread AddTask()\n");
}

//点符号初始化方式
//       注意在此方式在,和C
//风格不同,成员初始化不可以乱序初始化,否则编辑器将给出错误:“对不起,尚未实现:不平凡的代理初始值设定不受支持”。

/*
typedef struct AVPixFmtDescriptor {
    const char *name;
    uint8_t nb_components;  ///< The number of components each pixel has, (1-4)
    uint8_t log2_chroma_w;
    uint8_t log2_chroma_h;
    uint64_t flags;
    AVComponentDescriptor comp[4];
    const char *alias;
} AVPixFmtDescriptor;

注意: c++ 初始化 , 数组必须按以下枚举顺序, 且结构体内部按顺序
enum AVPixelFormat {
    AV_PIX_FMT_NONE = -1,
    AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
    AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
    AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
    AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
    AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
    AV_PIX_FMT_YUV444P, 

*/
static const AVPixFmtDescriptor my_av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
    [AV_PIX_FMT_YUV420P] = {
        .name = "yuv420p",
        .nb_components = 3,
        .log2_chroma_w = 1,
        .log2_chroma_h = 1,
        .flags = AV_PIX_FMT_FLAG_PLANAR,
        .comp = {
            { 0, 1, 0, 0, 8, 0, 7, 1 },        /* Y */
            { 1, 1, 0, 0, 8, 0, 7, 1 },        /* U */
            { 2, 1, 0, 0, 8, 0, 7, 1 },        /* V */
        },
        .alias = 0,

    },

    [AV_PIX_FMT_YUYV422] = {
        .name = "yuyv422",
        .nb_components = 3,
        .log2_chroma_w = 1,
        .log2_chroma_h = 0,
        .flags = 0,
        .comp = {
            { 0, 2, 0, 0, 8, 1, 7, 1 },        /* Y */
            { 0, 4, 1, 0, 8, 3, 7, 2 },        /* U */
            { 0, 4, 3, 0, 8, 3, 7, 4 },        /* V */
        },
        .alias = 0,
    },

    [AV_PIX_FMT_RGB24] = {
        .name = "rgb24",
        .nb_components = 3,
        .log2_chroma_w = 0,
        .log2_chroma_h = 0,
         .flags = AV_PIX_FMT_FLAG_RGB,
        .comp = {
            { 0, 3, 0, 0, 8, 2, 7, 1 },        /* R */
            { 0, 3, 1, 0, 8, 2, 7, 2 },        /* G */
            { 0, 3, 2, 0, 8, 2, 7, 3 },        /* B */
        },
       .alias = 0,
    },
    [AV_PIX_FMT_BGR24] = {
        .name = "bgr24",
        .nb_components = 3,
        .log2_chroma_w = 0,
        .log2_chroma_h = 0,
        .flags = AV_PIX_FMT_FLAG_RGB,
        .comp = {
            { 0, 3, 2, 0, 8, 2, 7, 3 },        /* R */
            { 0, 3, 1, 0, 8, 2, 7, 2 },        /* G */
            { 0, 3, 0, 0, 8, 2, 7, 1 },        /* B */
        },
        .alias = 0,
    },

};


static inline
int my_image_get_linesize(int width, int plane,
                       int max_step, int max_step_comp,
                       const AVPixFmtDescriptor *desc)
{
    int s, shifted_w, linesize;

    if (!desc)
        return AVERROR(EINVAL);

    if (width < 0)
        return AVERROR(EINVAL);
    s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0;
    shifted_w = ((width + (1 << s) - 1)) >> s;
    if (shifted_w && max_step > INT_MAX / shifted_w)
        return AVERROR(EINVAL);
    linesize = max_step * shifted_w;

    if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
        linesize = (linesize + 7) >> 3;
    return linesize;
}

const AVPixFmtDescriptor *my_av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
{
    printf("A my_av_pix_fmt_desc_get pix_fmt %d \n", pix_fmt);
    if (pix_fmt < 0 || pix_fmt >= AV_PIX_FMT_NB)
        return NULL;

    
    printf("B my_av_pix_fmt_desc_get pix_fmt %d \n", pix_fmt);
    return &my_av_pix_fmt_descriptors[pix_fmt];
}


int my_av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
{
    int i, ret;
    const AVPixFmtDescriptor *desc = my_av_pix_fmt_desc_get(pix_fmt);
    int max_step     [4];       /* max pixel step for each plane */
    int max_step_comp[4];       /* the component for each plane which has the max pixel step */

    printf("-------------------4*sizeof(linesizes[0]) %d desc %p desc->flags %d\n", 4*sizeof(linesizes[0]), desc, desc->flags);
    memset(linesizes, 0, 4*sizeof(linesizes[0]));

    //Pixel format is an HW accelerated format.
    //#define AV_PIX_FMT_FLAG_HWACCEL      (1 << 3)
    if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
    {
        printf(" error: AVERROR(EINVAL) \n\n");
        return AVERROR(EINVAL);
    }

    av_image_fill_max_pixsteps(max_step, max_step_comp, desc);
    
    for (i = 0; i < 4; i++) {
        if ((ret = my_image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0)
            return ret;

        printf("i %d -> max_step[i] %d, max_step_comp[i] %d, ret  %d\n", i, max_step[i], max_step_comp[i],  ret);
        linesizes[i] = ret;
    }

    return 0;
}

int my_av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, uint8_t *ptr, const int linesizes[4])
{
    int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 };

    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
    memset(data     , 0, sizeof(data[0])*4);

    if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
        return AVERROR(EINVAL);

    data[0] = ptr;
    if (linesizes[0] > (INT_MAX - 1024) / height)
        return AVERROR(EINVAL);
    size[0] = linesizes[0] * height;

    if (desc->flags & AV_PIX_FMT_FLAG_PAL ||
        desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) {
        data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */
        return size[0] + 256 * 4;
    }

    for (i = 0; i < 4; i++)
        has_plane[desc->comp[i].plane] = 1;

    total_size = size[0];
    for (i = 1; i < 4 && has_plane[i]; i++) {
        int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
        data[i] = data[i-1] + size[i-1];
        h = (height + (1 << s) - 1) >> s;
        if (linesizes[i] > INT_MAX / h)
            return AVERROR(EINVAL);
        size[i] = h * linesizes[i];
        if (total_size > INT_MAX - size[i])
            return AVERROR(EINVAL);
        total_size += size[i];
    }

    return total_size;
}


/*
如果您想要在函数中传递一个一维数组作为参数,您必须以下面三种方式来声明函数形式参数,
这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指
针。同样地,您也可以传递一个多维数组作为形式参数。
void myFunction(int *param)
void myFunction(int param[10])
void myFunction(int param[])
*/
//改为int my_av_image_fill_arrays(uint8_t *dst_data[99], int dst_linesize[0], 结果一样
//改为int my_av_image_fill_arrays(uint8_t **dst_data, int *dst_linesize, 结果一样
//align 排整齐; 校准
int my_av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
                         const uint8_t *src, enum AVPixelFormat pix_fmt,
                         int width, int height, int align)
{
    int ret, i;

    ret = av_image_check_size(width, height, 0, NULL);
    if (ret < 0)
        return ret;

    //AV_PIX_FMT_RGB24 2
    printf("my_av_image_fill_arrays  sizeof(dst_linesize) %d, sizeof(dst_data) %d, pix_fmt %d, width  %d , align %d\n", sizeof(dst_linesize), sizeof(dst_data), pix_fmt, width, align);
    //my_av_image_fill_arrays  sizeof(dst_linesize) 8, sizeof(dst_data) 8, pix_fmt 2, width  1280 align 1
    //ret = my_av_image_fill_linesizes(dst_linesize, pix_fmt, width);
    ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);
    if (ret < 0)
        return ret;

    for (i = 0; i < 4; i++)
        dst_linesize[i] = FFALIGN(dst_linesize[i], align);

    ret = av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);

    for (i = 0; i < 8; i++){
        printf("i-> %d  dst_data[i] %p dst_linesize[i] %d\n", i,  dst_data[i], dst_linesize[i]);
    }
    return ret;
}


int my_avpicture_fill(AVPicture *picture, const uint8_t *ptr,
                   enum AVPixelFormat pix_fmt, int width, int height)
{
    
    printf("my_avpicture_fill run() sizeof(picture->data) %d  sizeof(uint8_t *) %d\n", sizeof(picture->data), sizeof(uint8_t *));
    printf("my_avpicture_fill run() sizeof(picture->linesize) %d, sizeof(int) %d\n", sizeof(picture->linesize), sizeof(int));
    //AV_NUM_DATA_POINTERS = 8
    //uint8_t *data[AV_NUM_DATA_POINTERS];
    //int linesize[AV_NUM_DATA_POINTERS];
    
    //输出my_avpicture_fill run() sizeof(picture->data) 64 sizeof(uint8_t *)  8
    //输出my_avpicture_fill run() sizeof(picture->linesize) 32 , sizeof(int) 4
    return my_av_image_fill_arrays(picture->data, picture->linesize,
                                ptr, pix_fmt, width, height, 1);
}


static image_t my_make_empty_image(int w, int h, int c)
{
    image_t out;
    out.data = 0;
    out.h = h;
    out.w = w;
    out.c = c;
    return out;
}

static image_t my_make_image_custom(int w, int h, int c)
{
    image_t out = my_make_empty_image(w, h, c);
    out.data = (float *)calloc(h*w*c, sizeof(float));
    return out;
}

void H264DecoderThread::run()
{
    printf("H264DecoderThread run()\n");

    AVFrame *frame = av_mallocz(sizeof(*frame));
    printf("H264DecoderThread run()sizeof(*frame) %d\n", sizeof(*frame));
    printf("H264DecoderThread run()sizeof(AVFrame) %d\n", sizeof(AVFrame));
    /*
    H264DecoderThread run()sizeof(*frame) 488
    H264DecoderThread run()sizeof(AVFrame) 488
  */
    AVCodecContext* avctx = m_pFormatCtx->streams[m_nVideoStreamIndex]->codec;
    //sws_scale将输入参数, 转成RGB24
      /*
  enum AVPixelFormat {
      AV_PIX_FMT_NONE = -1,
      AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
      AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
      AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
      AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
  
  */
    //输出0 表示 AV_PIX_FMT_YUV420P
    printf("H264DecoderThread::run() pix_fmt:  %d \n", avctx->pix_fmt);

    //参数int flags选择缩放算法(只有当输入输出图像大小不同时有效) SWS_BILINEAR
    /*
    struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat 
    srcFormat,
                                      int dstW, int dstH, enum AVPixelFormat 
    dstFormat,
                                      int flags, 
                                      SwsFilter *srcFilter, SwsFilter *dstFilter, 
    const double *param);
    参数int srcW, int srcH, enum AVPixelFormat srcFormat
    定义输入图像信息(寬、高、颜色空间(像素格式))
    参数int dstW, int dstH, enum AVPixelFormat dstFormat
    定义输出图像信息寬、高、颜色空间(像素格式))
    参数int flags选择缩放算法(只有当输入输出图像大小不同时有效)
    参数SwsFilter *srcFilter, SwsFilter *dstFilter
    分别定义输入/输出图像滤波器信息,如果不做前后图像滤波,输入NULL
    参数const double *param定义特定缩放算法需要的参数(?),默认为NULL
    函数返回SwsContext结构体,定义了基本变换信息。
    如果是对一个序列的所有帧做相同的处理,函数sws_getContext
    只需要调用一次就可以了。
    sws_getContext(w, h, YV12, w, h, NV12, 0, NULL, NULL, NULL);      // YV12->
    NV12 色彩空间转换
    sws_getContext(w, h, YV12, w/2, h/2, YV12, 0, NULL, NULL, NULL);  // YV12
    图像缩小到原图1/4
    sws_getContext(w, h, YV12, 2w, 2h, YN12, 0, NULL, NULL, NULL);    // YV12
    图像放大到原图4倍,并转换为NV12结构

    */


    SwsContext * pSwsCtx = sws_getContext(avctx->width, avctx->height, avctx->pix_fmt, m_dst_w, m_dst_h,m_dst_pix_fmt, SWS_BILINEAR, NULL, NULL, NULL);
    AVPacket packet;
    //分配 sizeof(AVFrame) 488个字节, 并做简单初始化填充
    AVFrame* pYUVFrame = av_frame_alloc();
    AVFrame* pRGBFrame = av_frame_alloc();
    //rgbBufSize:  1280 X 720 X 3 = 2764800 
    int rgbBufSize = avpicture_get_size(m_dst_pix_fmt, m_dst_w, m_dst_h);
    printf("H264DecoderThread::run() rgbBufSize:  %d \n", rgbBufSize);
    /*
    typedef signed char             int8_t;
    typedef short int               int16_t;
    typedef int                     int32_t;
    typedef unsigned char           
    uint8_t;typedef unsigned short int      uint16_t;
    typedef unsigned 
    int            uint32_t;
    */
    //H264DecoderThread::run() sizeof(uint8_t):  1 
    //rgbBufSize*sizeof(uint8_t) = 1280 X 720 X 3 X 1= 2764800
    uint8_t* rgbBuf = (uint8_t*)(av_malloc(rgbBufSize*sizeof(uint8_t)));    
    printf("H264DecoderThread::run() sizeof(uint8_t):  %d \n", sizeof(uint8_t));
    /*
    typedef struct AVPicture {
        attribute_deprecated
        uint8_t *data[AV_NUM_DATA_POINTERS];    ///< pointers to the image data planes
        attribute_deprecated
        int linesize[AV_NUM_DATA_POINTERS];     ///< number of bytes per line
    } AVPicture;
    avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB565, pCodecCtx->
    width, pCodecCtx->height);
    复制代码
    这句调用时,pFrameRGB和buffer都是已经申请到的一段内存, 会将pFrameRGB的数据按
    RGB565格式自动"关联"到buffer。
    //以上就是为pFrameRGB挂上buffer。这个buffer是用于存缓冲数据的
    sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->
    height, pFrameRGB->data, pFrameRGB->linesize)
    复制代码
    转换完成的数据保存到了pFrameRGB,也自动到了buffer里面。


    注意: AVPicture 结果已经不再使用, 为了avpicture_fill 接口兼容, 不做改动
    所以将AVFrame *强制转成 AVPicture*, 只使用 AVFrame的data及linesize字段

         * pointer to the picture/channel planes.
         * This might be different from the first allocated byte
         *
         * Some decoders access areas outside 0,0 - width,height, please
         * see avcodec_align_dimensions2(). Some filters and swscale can read
         * up to 16 bytes beyond the planes, if these filters are to be used,
         * then 16 extra bytes must be allocated.
         *
         * NOTE: Except for hwaccel formats, pointers not needed by the format
         * MUST be set to NULL.

    uint8_t *data[AV_NUM_DATA_POINTERS];
         * For video, size in bytes of each picture line.
         * For audio, size in bytes of each plane.
         *
         * For audio, only linesize[0] may be set. For planar audio, each channel
         * plane must be the same size.
         *
         * For video the linesizes should be multiples of the CPUs alignment
         * preference, this is 16 or 32 for modern desktop CPUs.
         * Some code requires such alignment other code can be slower without
         * correct alignment, for yet other it makes no difference.
         *
         * @note The linesize may be larger than the size of usable data -- there
         * may be extra padding present for performance reasons.

    int linesize[AV_NUM_DATA_POINTERS];


    int avpicture_fill(AVPicture *picture, const uint8_t *ptr,
                       enum AVPixelFormat pix_fmt, int width, int height)
    {
        return av_image_fill_arrays(picture->data, picture->linesize,
                                    ptr, pix_fmt, width, height, 1);
    }

    int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
                             const uint8_t *src, enum AVPixelFormat pix_fmt,
                             int width, int height, int align)
    {
        int ret, i;

        //查看这个宽高是不是一个正常图片宽高
        //if ((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/8)
        //必须满足上面的条件, 不然会报图像无效
        //av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);
        ret = av_image_check_size(width, height, 0, NULL);
        if (ret < 0)
            return ret;

        //用格式参数填充linesizes
        ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);
        if (ret < 0)
            return ret;
    
        for (i = 0; i < 4; i++)
            dst_linesize[i] = FFALIGN(dst_linesize[i], align);

        //用分的内存填充pointers
        return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, 
    dst_linesize);
    }

    
    */

    my_avpicture_fill((AVPicture *) pRGBFrame, (uint8_t *)rgbBuf, m_dst_pix_fmt, m_dst_w, m_dst_h);
    av_read_play(m_pFormatCtx);//play RTSP
    Poco::Int64 nFrameNum = 0;


    while(!m_stop)
    {
        if (av_read_frame(m_pFormatCtx, &packet) != 0)
        {
            // 线程退出、启动timer(另一个线程跑)
            m_bConnected = false;
            m_timer.stop();
            m_interval = 2;
            m_timer.setPeriodicInterval(m_interval * 1000);
            m_timer.start(Poco::TimerCallback<Connector>(m_connector, &Connector::onTimer));
            break;
        }

        if(packet.stream_index == m_nVideoStreamIndex)
        {//packet is video

            int got_picture = 0;
            int res = avcodec_decode_video2(avctx, pYUVFrame, &got_picture, &packet);

             //printf("res %d, %d\n", res, got_picture);

             if (res>=0 && got_picture)
            {
                ++nFrameNum;
                if (m_stop)
                {
                    break;
                }
                做转换, 将原来的420p 转成 AV_PIX_FMT_RGB24
                /*
        // 做转换
        int sws_scale(struct SwsContext *c, 
                      const uint8_t *const srcSlice[], const int srcStride[], 
                      int srcSliceY, int srcSliceH,
                      uint8_t *const dst[], const int dstStride[]);
        参数struct SwsContext *c,为上面sws_getContext函数返回值;
        参数const uint8_t *const srcSlice[], const int srcStride[]
        定义输入图像信息(当前处理区域的每个通道数据指针,每个通道行字节数)
        stride定义下一行的起始位置。stride和width不一定相同,这是因为:
        //这里的 stride 与 opencv里 step 一样
        1.由于数据帧存储的对齐,有可能会向每行后面增加一些填充字节这样 stride = width 
        + N;
        2.packet色彩空间下,每个像素几个通道数据混合在一起,例如RGB24,每个像素3
        字节连续存放,因此下一行的位置需要跳过3*width字节。
        srcSlice和srcStride的维数相同,由srcFormat值来。
        csp       维数        宽width      跨度stride      高
        YUV420     3        w, w/2, w/2    s, s/2, s/2   h, h/2, h/2
        YUYV       1        w, w/2, w/2   2s, 0, 0       h, h, h
        NV12       2        w, w/2, w/2    s, s, 0       h, h/2
        RGB24      1        w, w,   w     3s, 0, 0       h, 0, 0           
        参数int srcSliceY, int srcSliceH,定义在输入图像上处理区域,srcSliceY
        是起始位置,srcSliceH是处理多少行。如果srcSliceY=0,srcSliceH=height
        ,表示一次性处理完整个图像。
        这种设置是为了多线程并行,例如可以创建两个线程,第一个线程处理 [0, h/2-1]
        行,第二个线程处理 [h/2, h-1]行。并行处理加快速度。
        参数uint8_t *const dst[], const int dstStride[]
        定义输出图像信息(输出的每个通道数据指针,每个通道行字节数)


        注意:
        Stride 只是步长, 跨度意思
        不是输出图像真正内容, 真正输出内容在 rgbBufSize中
        */

                for ( int i = 0; i< 8 ;i++)
                {
                    printf("i %d pYUVFrame linesize %d \n", i, pYUVFrame->linesize[i]);
                }
                
                for ( int i = 0; i< 8  ;i++)
                {

                    char name[20];
                    sprintf(name,"yuv_name_%d",i);
                    printf("i %s \n", name);

                    FILE * fp;
                    fp=fopen(name,"w+");
                    if(fp==NULL) return;

                    fwrite( pRGBFrame->data[i], 1, pRGBFrame->linesize[i] , fp );
                    fclose(fp);
                }

            /*
            结果
            i 0 pYUVFrame linesize 1280 
            i 1 pYUVFrame linesize 640 
            i 2 pYUVFrame linesize 640 
            i 3 pYUVFrame linesize 0 
            i 4 pYUVFrame linesize 0 
            i 5 pYUVFrame linesize 0 
            i 6 pYUVFrame linesize 0 
            i 7 pYUVFrame linesize 0 
            i yuv_name_0 
            i yuv_name_1 
            i yuv_name_2 
            i yuv_name_3 
            i yuv_name_4 
            i yuv_name_5 
            i yuv_name_6 
            i yuv_name_7 

            */
                

                   /*
                   具体每一帧数据的处理。
                   
                   struct SwsContext *c                   // 像素格式转换的上下文
                   
                   uint8_t *const srcSlice[]                // src的Slice
                   ,对应的具体数据的数组,是指针数组,也就是二维数组,YUV420P(三行数据)
                   
                   const int srcStride[]                      // linesize, 一行对应的大小。
                   
                   int srcSliceY                                 // 用不到,直接传0即可。
                   
                   int srcSliceH                                // 图像的高度。
                   
                   uint8_t *const dst[]                      // 目标的地址。也是一个指针数组。
                   
                   const int dstStride[]                     // 输入的linesize

                   */
                sws_scale(pSwsCtx, pYUVFrame->data, pYUVFrame->linesize, 0, avctx->height, pRGBFrame->data, pRGBFrame->linesize);

                for ( int i = 0; i< 8 ;i++)
                {
                    printf("i %d pRGBFrame linesize %d \n", i, pRGBFrame->linesize[i]);
                }

                for ( int i = 0; i< 8  ;i++)
                {

                    char name[20];
                    sprintf(name,"name_%d",i);
                    printf("i %s \n", name);

                    FILE * fp;
                    fp=fopen(name,"w+");
                    if(fp==NULL) return;

                    fwrite( pRGBFrame->data[i], 1, pRGBFrame->linesize[i] , fp );
                    fclose(fp);
                }
                
                {
                    FILE * fp;
                    fp=fopen("myrgbBuf","w+");
                    if(fp==NULL) return;

                    fwrite( rgbBuf, 1, rgbBufSize , fp );
                    fclose(fp);

                }

                /*
                i 0 pRGBFrame linesize 1248 
                i 1 pRGBFrame linesize 0 
                i 2 pRGBFrame linesize 0 
                i 3 pRGBFrame linesize 0 
                i 4 pRGBFrame linesize 0 
                i 5 pRGBFrame linesize 0 
                i 6 pRGBFrame linesize 0 
                i 7 pRGBFrame linesize 0 
                i name_0 
                i name_1 
                i name_2 
                i name_3 
                i name_4 
                i name_5 
                i name_6 
                i name_7 

                */


                #if 1
                if (1)
                    {
                    
                    struct timeval tv, tv1, tv2;
                            int w = m_dst_w;
                            int h = m_dst_h;
                            int c = m_dst_c;
                            image_t im = my_make_image_custom(w, h, c);
                            unsigned char *datayolo = rgbBuf; //(unsigned char *)pRGBFrame->data;
                            int step = m_dst_w * m_dst_c;

                            IplImage* pImg = cvCreateImage(cvSize(m_dst_w , m_dst_h), 8, 3);
                            memcpy(pImg->imageData, rgbBuf, rgbBufSize);

                            cv::Mat src(pImg);
                            //cv::cvtColor(cv::Mat(pImg), src, CV_BGR2RGB);//CV_RGB2BGR
                            //cv::cvtColor(cv::Mat(pImg), src, CV_RGB2BGR);//CV_RGB2BGR

                            imwrite("./ttCV_3311RGB2BGR416.jpg", src); 

                                gettimeofday(&tv,NULL);

                            for (int y = 0; y < h; ++y) {
                              for (int k = 0; k < c; ++k) {
                                  for (int x = 0; x < w; ++x) {
                                      im.data[k*w*h + y*w + x] = datayolo[y*step + x*c + k] / 255.0f;
                                  }
                              }
                            }
                            
                            gettimeofday(&tv1,NULL);
                            auto diff = tv1.tv_sec*1000 + tv1.tv_usec/1000 - (tv.tv_sec*1000 + tv.tv_usec/1000);
                            
                            cout << "diff : " << diff << endl;
                            printf("diff is :%ld\n",diff);  //毫秒


                            auto box_list = pDetector->detect(src);
                            for(auto& b: box_list)
                            {
                            //正确
                              cout << "Object type: " << b.obj_id << ", x: " << b.x << ", y: " << b.y << endl;
                            }
                            //auto box_list = pDetector->detect_resized(im, 1280, 720);
                            auto box_list1 = pDetector->detect_resized(im, 416, 416);
                            //std::vector<bbox_t> detect_resized(image_t img, int init_w, int init_h, float thresh = 0.2, bool use_mean = false)
                            for(auto& b: box_list1)
                            {
                            //错误
                              cout << "Object type: " << b.obj_id << ", x: " << b.x << ", y: " << b.y << endl;
                            }


                            //exit();

                }


                #endif

                


                /*
        image_t img;
        img.h = avctx->height;
        img.w = avctx->width;
        img.c = 3;
        img.data = (float *)rgbBuf;


        printf("H264DecoderThread A\n");

        auto box_list = pDetector->detect(img);


        printf("H264DecoderThread B\n");

        for(auto& b: box_list)
        {
            cout << "Object type: " << b.obj_id << ", x: " << b.x << ", y: " << b.y << endl;
        }


        printf("H264DecoderThread exit(0)\n");

        exit();
        */

               double exec_time = cv::getTickCount();

                struct timeval tv, tv1, tv2;

                #if 0
                exec_time = ((double)cv::getTickCount() - exec_time)*1000. / cv::getTickFrequency();
                cout << "exec_time1 : " << exec_time << endl;


                IplImage* pImg = cvCreateImage(cvSize(avctx->width, avctx->height), 8, 3);
                memcpy(pImg->imageData, rgbBuf, rgbBufSize);

                exec_time = ((double)cv::getTickCount() - exec_time)*1000. / cv::getTickFrequency();
                cout << "exec_time2 : " << exec_time << endl;

                
                cvCvtColor(pImg, pImg, CV_RGB2BGR);
                ImageFrame data(pImg, "1");
                data.frameNum = nFrameNum;

                exec_time = ((double)cv::getTickCount() - exec_time)*1000. / cv::getTickFrequency();
                cout << "exec_time3 : " << exec_time << endl;


                cv::Mat src;
                cv::cvtColor(cv::Mat(pImg), src, CV_BGR2RGB);
                printf("sH264DecoderThread A\n");

                exec_time = ((double)cv::getTickCount() - exec_time)*1000. / cv::getTickFrequency();
                cout << "exec_time4 : " << exec_time << endl;
                #endif


                //cv::Mat Img=cv::imread("data/person.jpg");  
                cv::Mat Img=cv::imread("t8.jpg");  

                gettimeofday(&tv,NULL);
                
                auto box_list = pDetector->detect(Img);
                
                gettimeofday(&tv1,NULL);
                auto diff = tv1.tv_sec*1000 + tv1.tv_usec/1000 - (tv.tv_sec*1000 + tv.tv_usec/1000);
                
                cout << "diff : " << diff << endl;

                for(auto& b: box_list)
                {
                    cout << "Object type: " << b.obj_id << ", x: " << b.x << ", y: " << b.y << endl;
                }

                exit();

                

                static int Static_nCount = 0;
                printf("avcodec_decode_video2 Count %d,  Interval %d\n", Static_nCount, m_nDetectionInterval);

                //if(Static_nCount % m_nDetectionInterval == 0)
                {
                    //m_frameCallback(data);
                }

                Static_nCount++;
            }
             
        }
        
        av_free_packet(&packet);
    }
    av_read_pause(m_pFormatCtx);
    av_frame_free(&pYUVFrame);
    av_frame_free(&pRGBFrame);
    av_free(rgbBuf);
    sws_freeContext(pSwsCtx);
    avcodec_close(avctx);
    //avformat_close_input(&m_pFormatCtx);
}

void H264DecoderThread::start(const std::function<frameCBfunc> &cb)
{
    printf("H264DecoderThread start()\n");

    if (!m_pFormatCtx)
    {
        
        printf("m_pFormatCtx == Null\n");
        return;
    }

    
    printf("H264DecoderThread start() b\n");
    m_connector.m_do = std::bind(&H264DecoderThread::reconnect, this);
    m_frameCallback = cb;
    m_thread.start(*this);
}

void H264DecoderThread::exit()
{
    m_stop = true;
    m_thread.join();
}

FFmpegErrorCode H264DecoderThread::init(const std::string &strMrl, Poco::Logger* pLogger, int nDetectionInterval)
{
    printf("H264DecoderThread init()\n");
    m_nDetectionInterval = nDetectionInterval;
    av_register_all();
    avformat_network_init();
    m_strMrl = strMrl;
    FFmpegErrorCode res = connect();
    return res;
}

void H264DecoderThread::reconnect()
{
    std::cout <<"H264DecoderThread reconnect"  <<std::endl;

    if (connect() == FFmpeg_NoError)
    {
    
        std::cout <<"H264DecoderThread reconnect A"  <<std::endl;
        //stop the timer and start decoder thread
        m_timer.restart(0);
        m_thread.start(*this);
        if (m_connectCallback)
        {
            m_connectCallback(true);
        }
    }
    else
    {
    
        std::cout <<"H264DecoderThread reconnect B"  <<std::endl;
        if (m_interval < 256)
        {
            m_interval = (m_interval * 2) % 257;
        }
        m_timer.setPeriodicInterval(m_interval * 1000);
        if (m_disconnectCallback)
        {
            m_disconnectCallback(false);
        }
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值