ffmpeg一直更新所以运行时有些方法和库对应不上,我用的是http://ffmpeg.zeranoe.com/builds/中:ffmpeg-20140305-git-d08bb06-win32-shared和ffmpeg-20140305-git-d08bb06-win32-dev;直接上代码了
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef __cplusplus
extern "C"{
#include "libavformat\avformat.h"
#include "libavcodec\avcodec.h"
#include "libavutil\avutil.h"
}
#endif //__cplusplus
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
int _tmain(int argc, _TCHAR* argv[])
{
const char* input = "";
AVInputFormat* pInForCtx = NULL;
AVFormatContext* pFormatCtx = NULL;
AVCodecContext *vpCodecCtx= NULL;
AVCodecContext *apCodecCtx= NULL;
AVCodec* video_codec = NULL;
AVCodec* audio_codec = NULL;
AVDictionary* pAVDictionary = NULL;
AVFrame *pFrame = NULL;
AVFrame *pFrameRGB = NULL;
struct SwsContext *img_convert_ctx;
int numBytes = 0;
//uint8_t *buffer;
int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
uint8_t * inbuf = (uint8_t *)malloc(out_size);
unsigned vframecount = 0;
av_register_all();
avformat_network_init();
char szError[256] = {0};
CVCamSDKImpl* pVCam = NULL;
pVCam = new CVCamSDKImpl();
//input可以是url
int nRet = avformat_open_input(&pFormatCtx, input, pInForCtx, &pAVDictionary);
if (nRet != 0)
{
av_strerror(nRet, szError, 256);
printf(szError);
printf("\n");
printf("Call avformat_open_input function failed!\n");
return 0;
}
if (av_find_stream_info(pFormatCtx) < 0)
{
printf("Call av_find_stream_info function failed!\n");
return 0;
}
int video_index = -1, audio_index = -1;
for (unsigned int i = 0; i < pFormatCtx->nb_streams && (video_index < 0 || audio_index < 0); i++)
{
switch (pFormatCtx->streams[i]->codec->codec_type)
{
case AVMEDIA_TYPE_VIDEO:
video_index = i;
pFormatCtx->streams[i]->discard = AVDISCARD_NONE;
break;
case AVMEDIA_TYPE_AUDIO:
audio_index = i;
pFormatCtx->streams[i]->discard = AVDISCARD_NONE;
break;
default:
pFormatCtx->streams[i]->discard = AVDISCARD_ALL;
break;
}
}
//视频解码准备部分
if(video_index != -1){
vpCodecCtx = pFormatCtx->streams[video_index]->codec;
video_codec = avcodec_find_decoder(vpCodecCtx->codec_id);
if (video_codec == NULL)
{
printf("Call avcodec_find_decoder function failed!\n");
return 0;
}
if (avcodec_open2(vpCodecCtx, video_codec, &pAVDictionary) < 0)
{
printf("Call avcodec_open function failed !\n");
return 0;
}
pFrame= avcodec_alloc_frame();
pFrameRGB = avcodec_alloc_frame();
}
if(audio_index != -1){
apCodecCtx = pFormatCtx->streams[audio_index]->codec;
audio_codec = avcodec_find_decoder(apCodecCtx->codec_id);
if (audio_codec == NULL)
{
printf("Call avcodec_find_decoder function failed!\n");
return 0;
}
if (avcodec_open2(apCodecCtx, audio_codec, &pAVDictionary) < 0)
{
printf("Call avcodec_open function failed !\n");
return 0;
}
}
AVBitStreamFilterContext* bsfc = av_bitstream_filter_init("h264_mp4toannexb");
if(bsfc == NULL)
{
return -1;
}
int decode_done = 0;
int len = 0;
uint8_t *buffer = NULL;
do
{
double segment_time = 0;
AVPacket packet;
decode_done = av_read_frame(pFormatCtx, &packet);//Returns the next frame of a stream.
if (decode_done < 0)
break;
if (av_dup_packet(&packet) < 0)
{
printf("Call av_dup_packet function failed\n");
av_free_packet(&packet);
break;
}
if (packet.stream_index == video_index)
{
len = avcodec_decode_video2(vpCodecCtx, pFrame, &numBytes, &packet);
if (numBytes != 0 )
{
if(vframecount == 0)
{
numBytes=avpicture_get_size(PIX_FMT_RGB24, vpCodecCtx->width, vpCodecCtx->height);
buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); // buffer = new uint8_t[numBytes];
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24, vpCodecCtx->width, vpCodecCtx->height);
img_convert_ctx = sws_getContext(vpCodecCtx->width, vpCodecCtx->height, vpCodecCtx->pix_fmt,
vpCodecCtx->width, vpCodecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
if(img_convert_ctx == NULL)
{
}
++vframecount;
}
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, vpCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
/*交换上下内存*/
for(;;){
int bytes_line = vpCodecCtx->width * 3;
int rows = vpCodecCtx->height/2;
int it=0;
unsigned char* tmp = (unsigned char*)malloc(bytes_line);
while(it<rows){
memcpy(tmp, pFrameRGB->data[0] + bytes_line*it, bytes_line);
memcpy(pFrameRGB->data[0] + bytes_line*it, pFrameRGB->data[0] + (vpCodecCtx->height-1-it)*bytes_line, bytes_line);
memcpy(pFrameRGB->data[0] + (vpCodecCtx->height-1-it)*bytes_line, tmp, bytes_line);
it++;
}
free(tmp);
break;
}
//然后就可以写文件或者用作其他
}
}else
if (packet.stream_index == audio_index)//音频这块我没有测试,不知道有没有问题,等测试了在更新
len = avcodec_decode_audio3(apCodecCtx, (short*)inbuf, &out_size, &packet);
av_free_packet(&packet);
}while(!decode_done);
avcodec_free_frame(&pFrame);
avcodec_free_frame(&pFrameRGB);
av_bitstream_filter_close(bsfc);
sws_freeContext(img_convert_ctx);
if (pVCam != NULL)
delete pVCam;
free(inbuf);
getchar();
return 0;
}
我也是初学,参考的很多,接收网络数据看这http://blog.sina.com.cn/s/blog_4c2bf01a01014ivr.html
音视频解码看这个:http://blog.csdn.net/yang_xian521/article/details/7699620(音频的解码,编码)
http://blog.csdn.net/yang_xian521/article/details/7699144(视频的解码,编码)