RTSP H264 提取bmp图片

本文在

ffmpeg解码视频存为BMP文件

http://blog.csdn.net/husthlj/article/details/6640574

基础上修改而成:

#include "stdafx.h"


#include <windows.h>
 #include <stdio.h>
#include <stdlib.h>
#include <string.h>


#pragma once  


 #ifdef __cplusplus
extern "C" {
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
}
#endif


//定义BMP文件头
#ifndef _WINGDI_ 
#define _WINGDI_
typedef struct tagBITMAPFILEHEADER{ 
        WORD    bfType;
        DWORD   bfSize; 
        WORD    bfReserved1; 
        WORD    bfReserved2; 
        DWORD   bfOffBits; 
}BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER; 
 
typedef struct tagBITMAPINFOHEADER{ 
        DWORD      biSize; 
        LONG       biWidth; 
        LONG       biHeight; 
        WORD       biPlanes; 
        WORD       biBitCount; 
        DWORD      biCompression; 
        DWORD      biSizeImage; 
        LONG       biXPelsPerMeter; 
        LONG       biYPelsPerMeter; 
        DWORD      biClrUsed; 
        DWORD      biClrImportant; 
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; 
 
#endif 
 int flag = 0;
//保存BMP文件的函数
void SaveAsBMP (AVFrame *pFrameRGB, int width, int height, int index1, int bpp) 

/**/
char buf[5] = {0}; 
BITMAPFILEHEADER bmpheader; 
BITMAPINFOHEADER bmpinfo; 
FILE *fp; 
static int index = 0;
 
char *filename = new char[255];
       //文件存放路径,根据自己的修改
sprintf_s(filename,255,"%s%d.bmp","D:/bmptest/bmp",index);
if ( (fp=fopen(filename,"wb+")) == NULL ) 

  printf ("open file failed!\n"); 
  return; 

index ++;
bmpheader.bfType = 0x4d42; 
bmpheader.bfReserved1 = 0; 
bmpheader.bfReserved2 = 0; 
bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 
bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp/8; 
 
bmpinfo.biSize = sizeof(BITMAPINFOHEADER); 
bmpinfo.biWidth = width; 
bmpinfo.biHeight = height; 
bmpinfo.biPlanes = 1; 
bmpinfo.biBitCount = bpp; 
bmpinfo.biCompression = BI_RGB; 
bmpinfo.biSizeImage = (width*bpp+31)/32*4*height; 
bmpinfo.biXPelsPerMeter = 100; 
bmpinfo.biYPelsPerMeter = 100; 
bmpinfo.biClrUsed = 0; 
bmpinfo.biClrImportant = 0; 
 
fwrite (&bmpheader, sizeof(bmpheader), 1, fp); 
fwrite (&bmpinfo, sizeof(bmpinfo), 1, fp); 
fwrite (pFrameRGB->data[0], width*height*bpp/8, 1, fp); 
 
fclose(fp); 
/***/



 static   DWORD WINAPI  rtsp2bmp(LPVOID lpParameter);
static   DWORD WINAPI  rtsp2bmp(LPVOID lpParameter)
//主函数
//int _tmain(int argc, _TCHAR* argv[])

unsigned int i = 0, videoStream = -1; 
AVCodecContext *pCodecCtx; 
AVFormatContext *pFormatCtx; 
AVCodec *pCodec; 
AVFrame *pFrame, *pFrameRGB; 
struct SwsContext *pSwsCtx; 
AVPacket packet; 
int frameFinished; 
int PictureSize; 
uint8_t *buf; 
LARGE_INTEGER l_lgint_start, l_lgint_end;
LARGE_INTEGER l_lgint_freq;
QueryPerformanceFrequency(&l_lgint_freq);



printf("\n======================================\n");
QueryPerformanceCounter(&l_lgint_start);
char filepath[]="rtsp://192.168.1.102:8556/PSIA/Streaming/channels/2?videoCodecType=H.264";
av_register_all();//注册所有的文件格式和编解码器的库
avformat_network_init();//打开流媒体初始化
pFormatCtx = avformat_alloc_context();


if(avformat_open_input(&pFormatCtx,filepath,NULL,NULL)!=0)

printf ("av open input file failed!\n"); 
exit (1); 

//获取流信息
if ( av_find_stream_info(pFormatCtx) < 0 ) 

printf ("av find stream info failed!\n"); 
exit (1); 

//获取视频流
for ( i=0; i<pFormatCtx->nb_streams; i++ ) 
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)

  videoStream = i; 
  break; 

 
if (videoStream == -1) 

printf ("find video stream failed!\n"); 
exit (1); 

 
pCodecCtx = pFormatCtx->streams[videoStream]->codec; 

pCodec = avcodec_find_decoder (pCodecCtx->codec_id); 
 
if (pCodec == NULL) 

printf ("avcode find decoder failed!\n"); 
exit (1); 

//打开解码器
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)

printf ("avcode open failed!\n"); 
exit (1); 

 
   //为每帧图像分配内存
pFrame = avcodec_alloc_frame(); 
pFrameRGB = avcodec_alloc_frame(); 
 
if ( (pFrame==NULL)||(pFrameRGB==NULL) ) 

printf("avcodec alloc frame failed!\n"); 
exit (1); 





PictureSize = avpicture_get_size (PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); 
buf = (uint8_t*)av_malloc(PictureSize); 
 
if ( buf == NULL ) 

printf( "av malloc failed!\n"); 
exit(1); 

avpicture_fill ( (AVPicture *)pFrameRGB, buf, PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); 
 
//设置图像转换上下文
pSwsCtx = sws_getContext (pCodecCtx->width, 
pCodecCtx->height, 
pCodecCtx->pix_fmt, 
pCodecCtx->width, 
pCodecCtx->height, 
PIX_FMT_BGR24, 
SWS_BICUBIC, 
NULL, NULL, NULL); 
i = 0; 


while(av_read_frame(pFormatCtx, &packet) >= 0) 

if(packet.stream_index==videoStream) 

  avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);//解码一帧视频数据
  
  if(frameFinished) 
  {    
//反转图像 ,否则生成的图像是上下调到的
pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height - 1); 
pFrame->linesize[0] *= -1; 
pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height / 2 - 1); 
pFrame->linesize[1] *= -1; 
pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height / 2 - 1); 
pFrame->linesize[2] *= -1; 
//转换图像格式,将解压出来的YUV420P的图像转换为BRG24的图像
sws_scale (pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); 



//printf("save ------------------------------ = %d\n",i);
//getchar();
if(flag != 0)
{
//QueryPerformanceCounter(&l_lgint_end);
//double dTmpRT=double(l_lgint_end.QuadPart-l_lgint_start.QuadPart)/double(l_lgint_freq.QuadPart);
//printf("save ------------------------------dTmpRT = %lf\n",dTmpRT);
SaveAsBMP (pFrameRGB, pCodecCtx->width, pCodecCtx->height, i++, 24);
flag = 0;
}
//break;

  }     

av_free_packet(&packet); 

 




sws_freeContext (pSwsCtx); 
av_free (pFrame); 
av_free (pFrameRGB); 
avcodec_close (pCodecCtx); 
av_close_input_file (pFormatCtx); 
return 0; 



int _tmain(int argc, _TCHAR* argv[])
{
HANDLE  ThreadHandle = CreateThread(NULL,0,rtsp2bmp,NULL,0,NULL);


while(1)
{
scanf("%d",&flag);
printf("\n $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ %d\n",flag);
}

}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值