- #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;
- <span style="white-space:pre"> </span>m_bitBuffer = NULL;<span style="font-family: Arial, Helvetica, sans-serif;"></span>
- }
- 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);
- }
- <span style="white-space:pre"> </span>if(m_bitBuffer != NULL)
- <span style="white-space:pre"> </span>delete[] m_bitBuffer;
- }