#ifndef __DECODE_STREAM_FROM_CAMERA__
#define __DECODE_STREAM_FROM_CAMERA__
extern "C"{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libavfilter/avfilter.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/avutil.h"
}
#pragma warning(disable:4996)
class DecodeStream
{
public:
DecodeStream();
BOOL OpenStream(const char* url);
BOOL FindStream();
BOOL ReadStream(HWND hVideoWnd = NULL, int DlgItemID = 0);
BOOL CloseStream();
~DecodeStream();
private:
void ShowRGBToWnd(HWND hWnd, BYTE* data, int width, int height);
private:
AVFormatContext *m_pFormatCtx;
unsigned int m_videoStream;
AVCodecContext *m_pCodecCtx;
AVCodec *m_pCodec;
AVFrame *m_pFrame, *m_pFrameRGB;
struct SwsContext *m_pSwsCtx;
int m_frameFinished;
int m_PictureSize;
uint8_t *m_buf;
int m_open;
BYTE *m_bitBuffer;
};
#endif //__DECODE_STREAM_FROM_CAMERA__
#include "DecodeStream.h"
DecodeStream::DecodeStream()
{
m_pFormatCtx = avformat_alloc_context();
av_register_all();
avformat_network_init();
avdevice_register_all();
m_pFrame = av_frame_alloc();
m_pFrameRGB = av_frame_alloc();
m_videoStream = -1;
m_bitBuffer = NULL;
}
BOOL DecodeStream::OpenStream(const char* url)
{
AVDictionary* opts = NULL;
av_dict_set(&opts, "stimeout", "5000000", 0);
AVInputFormat *ifmt = av_find_input_format("vfw");
if (avformat_open_input(&m_pFormatCtx, url, ifmt, &opts) != 0)
{
return FALSE;
}
m_open = 1;
return TRUE;
}
BOOL DecodeStream::FindStream()
{
if (avformat_find_stream_info(m_pFormatCtx, NULL) < 0)
{
avformat_close_input(&m_pFormatCtx);
return FALSE;
}
for (size_t i = 0; i < m_pFormatCtx->nb_streams; i++)
if (m_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
m_videoStream = i;
}
if (m_videoStream == -1)
{
avformat_close_input(&m_pFormatCtx);
return FALSE;
}
m_pCodecCtx = m_pFormatCtx->streams[m_videoStream]->codec;
m_pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id);
if (m_pCodec == NULL)
{
avformat_close_input(&m_pFormatCtx);
return FALSE;
}
if (avcodec_open2(m_pCodecCtx, m_pCodec, NULL) < 0)
{
avformat_close_input(&m_pFormatCtx);
return FALSE;
}
m_PictureSize = avpicture_get_size(AV_PIX_FMT_BGR24, m_pCodecCtx->width, m_pCodecCtx->height);
m_buf = (uint8_t*)av_malloc(m_PictureSize);
if (m_buf == NULL)
{
avformat_close_input(&m_pFormatCtx);
avcodec_close(m_pCodecCtx);
return FALSE;
}
avpicture_fill((AVPicture *)m_pFrameRGB, m_buf, AV_PIX_FMT_BGR24, m_pCodecCtx->width, m_pCodecCtx->height);
m_pSwsCtx = sws_getContext(m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt, m_pCodecCtx->width, m_pCodecCtx->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
return TRUE;
}
BOOL DecodeStream::ReadStream(HWND hVideoWnd /* = NULL */, int DlgItemID/* = 0*/)
{
AVPacket* packet = av_packet_alloc();
while (av_read_frame(m_pFormatCtx, packet) >= 0 && m_open == 1){
if (packet->stream_index == m_videoStream){
//真正的解码
avcodec_decode_video2(m_pCodecCtx, m_pFrame, &m_frameFinished, packet);
if (m_frameFinished){
//转换图像格式,将解压出来的YUV420P的图像转换为BRG24的图像
sws_scale(m_pSwsCtx, m_pFrame->data, m_pFrame->linesize, 0, m_pCodecCtx->height, m_pFrameRGB->data, m_pFrameRGB->linesize);
if (hVideoWnd != NULL && ItemID != 0)
showRGBToWnd(hVideo, m_pFrameRGB->data[0], m_pCodecCtx->width, m_pCodecCtx->height);
}
}
av_free_packet(packet);
}
avformat_close_input(&m_pFormatCtx);
av_packet_free(&packet);
sws_freeContext(m_pSwsCtx);
avcodec_close(m_pCodecCtx);
return TRUE;
}
BOOL DecodeStream::CloseStream()
{
m_open = 0;
return TRUE;
}
void DecodeStream::ShowRGBToWnd(HWND hWnd, BYTE* data, int width, int height)
{
if (data == NULL)
return;
static BITMAPINFO *bitMapinfo = NULL;
static bool First = TRUE;
if (First)
{
m_bitBuffer = new BYTE[40 + 4 * 256];//开辟一个内存区域
if (m_bitBuffer == NULL)
{
return;
}
First = FALSE;
memset(m_bitBuffer, 0, 40 + 4 * 256);
bitMapinfo = (BITMAPINFO *)m_bitBuffer;
bitMapinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitMapinfo->bmiHeader.biPlanes = 1;
for (int i = 0; i < 256; i++)
{ //颜色的取值范围 (0-255)
bitMapinfo->bmiColors[i].rgbBlue = bitMapinfo->bmiColors[i].rgbGreen = bitMapinfo->bmiColors[i].rgbRed = (BYTE)i;
}
}
bitMapinfo->bmiHeader.biHeight = -height;
bitMapinfo->bmiHeader.biWidth = width;
bitMapinfo->bmiHeader.biBitCount = 3 * 8;
CRect drect;
GetClientRect(hWnd, drect); //pWnd指向CWnd类的一个指针
HDC hDC = GetDC(hWnd); //HDC是Windows的一种数据类型,是设备描述句柄;
SetStretchBltMode(hDC, COLORONCOLOR);
StretchDIBits(hDC,
0,
0,
drect.right, //显示窗口宽度
drect.bottom, //显示窗口高度
0,
0,
width, //图像宽度
height, //图像高度
data,
bitMapinfo,
DIB_RGB_COLORS,
SRCCOPY
);
ReleaseDC(hWnd, hDC);
}
DecodeStream::~DecodeStream()
{
if (m_pFrame != NULL && m_pFrameRGB != NULL){
av_free(m_pFrame);
av_free(m_pFrameRGB);
}
if(m_bitBuffer != NULL)
delete[] m_bitBuffer;
}