提取视频第一帧保存为图片

来源:互联网 发布:越南工业知乎 编辑:程序博客网 时间:2024/05/17 08:22
extern "C"{#include "include/avformat.h"#include "include/libswscale/swscale.h"#include "include/libavcodec/avcodec.h"#include "include/avio.h"}#pragma comment (lib,"lib/avcodec.lib")#pragma comment (lib,"lib/swscale.lib")#pragma comment (lib,"lib/avutil.lib")#pragma comment (lib,"lib/avformat.lib")
void CtestDlg::OnBnClickedButton1(){// TODO:  在此添加控件通知处理程序代码getViewImage("C:\\1.avi","C:\\1.bmp",300,300);}//构建BMP位图文件头  void ContructBhh(int nWidth, int nHeight, BITMAPFILEHEADER& bhh) //add 2010-9-04  {//24位真彩色,24位表示一个像素,3个字节表示一个像素int widthStep = (nWidth * 3 + 3) & ~3; //每行字节数是4的倍数bhh.bfType = ((WORD)('M' << 8) | 'B');  //'BM'  bhh.bfSize = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+nWidth * nHeight;//该bmp文件总的字节数bhh.bfReserved1 = 0;bhh.bfReserved2 = 0;//bmp文件由三块构成,位图文件头,位图信息头以及DIB像素数据bhh.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER);//从文件头到实际的位图数据的偏移字节数,除去文件头和位图信息的字节数//bhh.bfOffBits = 54;}//构建BMP文件信息头  void ConstructBih(int nWidth, int nHeight, BITMAPINFOHEADER& bih){//24位真彩色,24位表示一个像素,3个字节表示一个像素int widthStep = (nWidth * 4 + 3) & ~3; //每行字节数是4的倍数bih.biSize = sizeof(BITMAPINFOHEADER);       // header size  文件信息头的大小,固定为40bih.biWidth = nWidth;  //图像的宽度bih.biHeight = nHeight;// 图像的高度bih.biPlanes = 1;bih.biBitCount = 24;     // 24位表示一个像素bih.biCompression = BI_RGB;   // no compression 非压缩  //bih.biSizeImage=widthStep*nHeight*4;//整个文件的字节数  bih.biSizeImage = 0;bih.biXPelsPerMeter = 0;bih.biYPelsPerMeter = 0;bih.biClrUsed = 0;bih.biClrImportant = 0;}BOOL SaveBitmap(char * BMPFileName, char * data, int render_width, int render_height){BITMAPINFOHEADER bih;ConstructBih(render_width, render_height, bih);BITMAPFILEHEADER bhh;ContructBhh(render_width, render_height, bhh);//24位真彩色,24位表示一个像素,3个字节表示一个像素int widthStep = (render_width * 4 + 3) & ~3; //每行字节数是4的倍数int DIBSize = render_width * render_height * 3;  //buffer的大小 (字节为单位)  CFile file;if (file.Open(BMPFileName, CFile::modeWrite | CFile::modeCreate)){file.Write((LPSTR)&bhh, sizeof(BITMAPFILEHEADER));file.Write((LPSTR)&bih, sizeof(BITMAPINFOHEADER));file.Write(data, DIBSize);//file.Write(render_bitmap_surface,render_bitmap.header.biSizeImage);file.Close();}return 0;}bool getViewImage(char *  readfile, char * savefile, int width, int height){AVFormatContext*pFormatCtx;inti, videoindex;AVCodecContext*pCodecCtx;AVCodec*pCodec;uint8_t *out_buffer;AVPacket *packet;int y_size;int ret, got_picture;struct SwsContext *img_convert_ctx;tagBITMAPINFO tagbit;tagbit.bmiHeader.biBitCount = 24;tagbit.bmiHeader.biSize = sizeof(tagBITMAPINFO);tagbit.bmiHeader.biPlanes = 1;tagbit.bmiHeader.biCompression = BI_RGB;AVFrame*pFrame, *pFrameRGB;avcodec_init();av_register_all();pFormatCtx = av_alloc_format_context();//获取format 描述 if (av_open_input_file(&pFormatCtx, readfile, NULL, 0, NULL) == 0){//打开输入 if (av_find_stream_info(pFormatCtx) < 0){ //获取对应的信息av_close_input_file(pFormatCtx);return false;}videoindex = -1;for (i = 0; i < pFormatCtx->nb_streams; i++){if (pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO){//视频流 videoindex = i;break;}}if (videoindex == -1){return false;}pCodecCtx = pFormatCtx->streams[videoindex]->codec; //获取描述 pCodec = avcodec_find_decoder(pCodecCtx->codec_id);//查找对应解码器if (pCodec == NULL){return false;}if (avcodec_open(pCodecCtx, pCodec) < 0){return false;}pFrameRGB = avcodec_alloc_frame();//解码后的rgb数据out_buffer = (unsigned char *)av_malloc(avpicture_get_size(PIX_FMT_BGR24, width, height));avpicture_fill((AVPicture *)pFrameRGB, out_buffer, PIX_FMT_BGR24,width, height);img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,width, height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);int size = 0;packet = (AVPacket *)av_malloc(sizeof(AVPacket));pFrame = avcodec_alloc_frame();//解码后的数据while (av_read_frame(pFormatCtx, packet) >= 0){if (packet->stream_index == videoindex){ret = avcodec_decode_video(pCodecCtx, pFrame, &got_picture, packet->data, packet->size);//将packet 的数据解码到 pFrameif (ret < 0){return false;}if (got_picture){size++;//翻转图片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;sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height,pFrameRGB->data, pFrameRGB->linesize);//saveYuvToJpg(savefile,pFrameYUV,width,height);int outsize = width  * height * 3;memcpy(tempbuffer, pFrameRGB->data[0], outsize);  //为什么要拷贝 到临时内存 我也搞不清楚 直接传递 data[0]指针进去 写文件的时候 报错误 SaveBitmap(savefile, (char *)tempbuffer, width, height);break;#if 0HWND hwnd = FindWindowA(NULL, "Form1");if (hwnd > 0){//int outsize = pCodecCtx->width * pCodecCtx->height * 3;  //memcpy(outbuf, pFrameRGB->data[0],outsize);  HDC dc = ::GetDC((HWND)hwnd);tagbit.bmiHeader.biWidth = pCodecCtx->width;tagbit.bmiHeader.biHeight = pCodecCtx->height;::RECT rect;::GetWindowRect((HWND)hwnd, &rect);//SetStretchBltMode(dc,STRETCH_HALFTONE);SetStretchBltMode(dc, STRETCH_DELETESCANS);StretchDIBits(dc, 0, 0,rect.right - rect.left, rect.bottom - rect.top,0, 0,pCodecCtx->width, pCodecCtx->height,pFrameRGB->data[0], &tagbit, DIB_RGB_COLORS, SRCCOPY);ReleaseDC(hwnd, dc);Sleep(25);}#endif}}}sws_freeContext(img_convert_ctx);av_free(pFrameRGB);av_close_input_file(pFormatCtx);av_free(pFrame);av_free(packet);//printf("转换ok\n");}return true;}





原创粉丝点击