1. #include <windows.h>
2. #include <stdio.h>
3. #include <stdlib.h>
4. #include <string.h>
5. #pragma once
6.
7. #ifdef __cplusplus
8. extern "C"
9. #endif
10. #include <libavcodec/avcodec.h>
11. #include <libavformat/avformat.h>
12. #include <libswscale/swscale.h>
13.
14.
15. #ifdef __cplusplus
16. }
17. #endif
18.
19. //定义BMP文件头
20. #ifndef _WINGDI_
21. #define _WINGDI_
22. typedef struct
23. WORD
24. DWORD
25. WORD
26. WORD
27. DWORD
28. } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
29.
30. typedef struct
31. DWORD
32. LONG
33. LONG
34. WORD
35. WORD
36. DWORD
37. DWORD
38. LONG
39. LONG
40. DWORD
41. DWORD
42. } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
43.
44. #endif
45.
46. //保存BMP文件的函数
47. void SaveAsBMP (AVFrame *pFrameRGB, int width, int height, int index, int
48. {
49. char
50. BITMAPFILEHEADER bmpheader;
51. BITMAPINFOHEADER bmpinfo;
52. FILE
53.
54. char *filename = new char[255];
55. //文件存放路径,根据自己的修改
56. "%s%d.bmp","D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/test",index);
57. if ( (fp=fopen(filename,"wb+")) == NULL )
58. {
59. "open file failed!\n");
60. return;
61. }
62.
63. bmpheader.bfType = 0x4d42;
64. bmpheader.bfReserved1 = 0;
65. bmpheader.bfReserved2 = 0;
66. sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
67. bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp/8;
68.
69. sizeof(BITMAPINFOHEADER);
70. bmpinfo.biWidth = width;
71. bmpinfo.biHeight = height;
72. bmpinfo.biPlanes = 1;
73. bmpinfo.biBitCount = bpp;
74. bmpinfo.biCompression = BI_RGB;
75. bmpinfo.biSizeImage = (width*bpp+31)/32*4*height;
76. bmpinfo.biXPelsPerMeter = 100;
77. bmpinfo.biYPelsPerMeter = 100;
78. bmpinfo.biClrUsed = 0;
79. bmpinfo.biClrImportant = 0;
80.
81. sizeof(bmpheader), 1, fp);
82. sizeof(bmpinfo), 1, fp);
83. fwrite (pFrameRGB->data[0], width*height*bpp/8, 1, fp);
84.
85. fclose(fp);
86. }
87.
88. //主函数
89. int main (void)
90. {
91. int
92. AVCodecContext *pCodecCtx;
93. AVFormatContext *pFormatCtx;
94. AVCodec *pCodec;
95. AVFrame *pFrame, *pFrameRGB;
96. struct
97. const char *filename = "D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/DELTA.MPG";
98. AVPacket packet;
99. int
100. int
101. uint8_t *buf;
102. //注册编解码器
103. av_register_all();
104. //打开视频文件
105. if
106. {
107. "av open input file failed!\n");
108. exit (1);
109. }
110. //获取流信息
111. if
112. {
113. "av find stream info failed!\n");
114. exit (1);
115. }
116. //获取视频流
117. for
118. if
119. {
120. videoStream = i;
121. break;
122. }
123.
124. if
125. {
126. "find video stream failed!\n");
127. exit (1);
128. }
129.
130. pCodecCtx = pFormatCtx->streams[videoStream]->codec;
131.
132. pCodec = avcodec_find_decoder (pCodecCtx->codec_id);
133.
134. if
135. {
136. "avcode find decoder failed!\n");
137. exit (1);
138. }
139. //打开解码器
140. if
141. {
142. "avcode open failed!\n");
143. exit (1);
144. }
145.
146. //为每帧图像分配内存
147. pFrame = avcodec_alloc_frame();
148. pFrameRGB = avcodec_alloc_frame();
149.
150. if
151. {
152. "avcodec alloc frame failed!\n");
153. exit (1);
154. }
155.
156. PictureSize = avpicture_get_size (PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);
157. buf = (uint8_t*)av_malloc(PictureSize);
158.
159. if
160. {
161. "av malloc failed!\n");
162. exit(1);
163. }
164. avpicture_fill ( (AVPicture *)pFrameRGB, buf, PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);
165.
166. //设置图像转换上下文
167. pSwsCtx = sws_getContext (pCodecCtx->width,
168. pCodecCtx->height,
169. pCodecCtx->pix_fmt,
170. pCodecCtx->width,
171. pCodecCtx->height,
172. PIX_FMT_BGR24,
173. SWS_BICUBIC,
174. NULL, NULL, NULL);
175. i = 0;
176. while(av_read_frame(pFormatCtx, &packet) >= 0)
177. {
178. if(packet.stream_index==videoStream)
179. {
180. avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
181. packet.data, packet.size);
182.
183. if(frameFinished)
184. {
185. //反转图像 ,否则生成的图像是上下调到的
186. pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height - 1);
187. pFrame->linesize[0] *= -1;
188. pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height / 2 - 1);
189. pFrame->linesize[1] *= -1;
190. pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height / 2 - 1);
191. pFrame->linesize[2] *= -1;
192. //转换图像格式,将解压出来的YUV420P的图像转换为BRG24的图像
193. sws_scale (pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
194. SaveAsBMP (pFrameRGB, pCodecCtx->width, pCodecCtx->height, i++, 24);
195. }
196. }
197. av_free_packet(&packet);
198. }
199.
200. sws_freeContext (pSwsCtx);
201. av_free (pFrame);
202. av_free (pFrameRGB);
203. avcodec_close (pCodecCtx);
204. av_close_input_file (pFormatCtx);
205.
206. return
207. }

#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

//保存BMP文件的函数
void SaveAsBMP (AVFrame *pFrameRGB, int width, int height, int index, int bpp)
{
char buf[5] = {0};
BITMAPFILEHEADER bmpheader;
BITMAPINFOHEADER bmpinfo;
FILE *fp;

char *filename = new char[255];
//文件存放路径,根据自己的修改
sprintf_s(filename,255,"%s%d.bmp","D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/test",index);
if ( (fp=fopen(filename,"wb+")) == NULL )
{
printf ("open file failed!\n");
return;
}

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

//主函数
int main (void)
{
unsigned int i = 0, videoStream = -1;
AVCodecContext *pCodecCtx;
AVFormatContext *pFormatCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameRGB;
struct SwsContext *pSwsCtx;
const char *filename = "D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/DELTA.MPG";
AVPacket packet;
int frameFinished;
int PictureSize;
uint8_t *buf;
//注册编解码器
av_register_all();
//打开视频文件
if ( av_open_input_file(&pFormatCtx, filename, NULL, 0, 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 == CODEC_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_open(pCodecCtx, pCodec)<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_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);

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);
SaveAsBMP (pFrameRGB, pCodecCtx->width, pCodecCtx->height, i++, 24);
}
}
av_free_packet(&packet);
}

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

return 0;
}