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