使用ffmpeg库将h264转成mp4的问题

走走刀口 2011-11-15 10:07:16
我使用ffmpeg库将h264格式的转成了mp4格式的视频文件,系统自带的Windows Media Player放不了我转换后的mp4文件,而使用ffmpeg.exe来转的这个h264文件的话,Windows Media Player播放器却能播放,但如果使用暴风影音来播放的话,就能播放出我自己转的mp4文件,请问这个是什么问题?望各位指教,谢谢!

// input file info
AVFormatContext* ic;
AVStream* ist;

// output file info
AVFormatContext* oc;
AVStream* ost;

int m_nBufferSize;
BYTE* m_byBuffer;
// 初始化
nt CConvertManager::Init()
{
avcodec_register_all();
avdevice_register_all();
avfilter_register_all();
av_register_all();
return 0;
}
// 处理输入文件
int CConvertManager::AnalyzeInputFile(const char* fileName)
{
AVInputFormat* iFormat = NULL;
AVFormatParameters params, *ap = ¶ms;
AVCodecContext* icc = NULL;
AVCodec* codec = NULL;
int ret;

ic = avformat_alloc_context();
if (!ic)
{
return -1;
}

memset(ap, 0, sizeof(AVFormatParameters));
ap->prealloced_context = 1;

// open input file with generic libav function
ret = av_open_input_file(&ic, fileName, NULL, 0, NULL);
if (ret < 0)
{
return -1;
}

// decode the first frames to get the stream parameters
ret = av_find_stream_info(ic);
if (ret < 0)
{
av_close_input_file(ic);
return -1;
}

videoIndex = -1;
for (int i = 0; i < ic->nb_streams; i++)
{
if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoIndex = i;
}
}
if (videoIndex == -1)
{
return -1;
}

ist = ic->streams[videoIndex];
icc = ist->codec;
// find the video encoder
codec = avcodec_find_decoder(icc->codec_id);

// open codec
if (avcodec_open(icc, codec) < 0)
{
return -1;
}

return 0;
}


// 处理输部门文件
int CConvertManager::AnalyzeOutputFile(const char* fileName)
{
AVOutputFormat* oFormat = NULL;
AVFormatParameters params, *ap = ¶ms;
AVCodecContext* occ = NULL;
enum CodecID codec_id = CODEC_ID_NONE;
AVCodec* codec = NULL;
int ret;

oFormat = av_guess_format(NULL, fileName, NULL);
if (!oFormat)
{
return -1;
}
oc = avformat_alloc_context();
if (!oc)
{
return -1;
}
oc->oformat = oFormat;
strcpy_s(oc->filename, fileName);

// create video stream
ost = av_new_stream(oc, 0);
// guess codec
codec_id = av_guess_codec(oFormat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
codec = avcodec_find_encoder(codec_id);

occ = avcodec_alloc_context();
av_dict_copy(&ost->metadata, ist->metadata, AV_DICT_DONT_OVERWRITE);
av_dict_copy(&oc->metadata, ic->metadata, AV_DICT_DONT_OVERWRITE);
occ = ost->codec;
occ->codec_id = codec_id;
occ->codec_type = AVMEDIA_TYPE_VIDEO;
occ->width = ist->codec->width;
occ->height = ist->codec->height;
AVRational rational;
if (ist->r_frame_rate.num)
{
rational.den = ist->r_frame_rate.num;
rational.num = ist->r_frame_rate.den;
}
else
{
rational.den = 1;
rational.num = 25;
}
occ->time_base = rational;
occ->gop_size = ist->codec->gop_size;
occ->pix_fmt = ist->codec->pix_fmt;
occ->max_b_frames = ist->codec->max_b_frames;
occ->bits_per_raw_sample = ist->codec->bits_per_raw_sample;
occ->chroma_sample_location = ist->codec->chroma_sample_location;
ost->r_frame_rate = ist->r_frame_rate;
ost->disposition = ist->disposition;


// open the file
ret = avio_open(&oc->pb, fileName, AVIO_FLAG_WRITE);
if (ret < 0)
{
return -1;
}

memset(ap, 0, sizeof(AVFormatParameters));
if (av_set_parameters(oc, NULL) < 0)
{
return -1;
}

if (avcodec_open(occ, codec)<0)
{
return -1;
}

return 0;
}


// 格式转换
int CConvertManager::Convert(const char* srcFile, const char* destFile, float rate)
{
AnalyzeInputFile(srcFile);
AnalyzeOutputFile(destFile);

AVFrame *picture = NULL;
int ret = 0;

if (ost->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
int size = ost->codec->width * ost->codec->height;
m_nBufferSize = FFMAX(BUFFER_SIZE, 7*size + 10000);
}

if (!m_byBuffer)
{
m_byBuffer = (BYTE*)av_malloc(m_nBufferSize);
}
if (!m_byBuffer)
{
return -1;
}

picture = avcodec_alloc_frame();

// open files and write file headers
if (av_write_header(oc) < 0)
{
return -1;
}

int frameIndex = 0;
while (ret >= 0)
{
memset(m_byBuffer, 0, m_nBufferSize);
AVPacket packet;
ret = av_read_frame(ic, &packet);
if (ret == AVERROR(EAGAIN))
{
break;
}
if (ret < 0)
{
break;
}
// is the video stream
if (packet.stream_index == videoIndex)
{
int got_output = 0;
ret = avcodec_decode_video2(ist->codec, picture, &got_output, &packet);
if (got_output)
{
picture->pts = av_rescale(frameIndex, AV_TIME_BASE*(int64_t)ost->codec->time_base.num, ost->codec->time_base.den);
picture->pict_type = AV_PICTURE_TYPE_NONE;
int outSize = avcodec_encode_video(ost->codec, m_byBuffer, m_nBufferSize, picture);
if (outSize > 0)
{
AVPacket pkt;
av_init_packet(&pkt);
if (ost->codec->coded_frame && ost->codec->coded_frame->key_frame)
{
pkt.flags |= AV_PKT_FLAG_KEY;
}
pkt.stream_index = ost->index;
pkt.data = m_byBuffer;
pkt.size = outSize;
ret = av_write_frame(oc, &pkt);
}
}
else
{
av_write_frame(oc, &packet);
}
}

frameIndex++;
}

// write the trailer
av_write_trailer(oc);

return 0;
}
...全文
867 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
liangxuanggui 2011-11-22
  • 打赏
  • 举报
回复
我现在也遇到这个问题,解决不了,我发现用mpeg4和h263都没问题,就是用h264有问题
zhangsongcui 2011-11-21
  • 打赏
  • 举报
回复
现在MP4多见H264+AAC的,也有xvid+AAC、mp3的,不知道LZ用的是哪种
PS:WMP自身提供的解码器即为有限,不如打包wmv格式
hacqing 2011-11-21
  • 打赏
  • 举报
回复
windows下文件很大的特点就是通过后缀来识别文件, 还有就是通过文件头来识别.
我估计是你的mp4文件头出问题了吧. 因为音视频数据能够通过暴风播出来, 音视
频数据是没问题的, 文件头吧. 我只是猜测, 嘿嘿, 我对这个没多少了解, 过段时间
也应该会做这方面的事情了.
走走刀口 2011-11-21
  • 打赏
  • 举报
回复
看来没人回答了,虽然问题还没解决,但还是感谢上面几位的热心回答。
走走刀口 2011-11-17
  • 打赏
  • 举报
回复
求高人解答!
ryfdizuo 2011-11-15
  • 打赏
  • 举报
回复
不太懂视频压缩,
ffmpeg.exe工程的源码 可以下载来看看。
走走刀口 2011-11-15
  • 打赏
  • 举报
回复
我想调用ffmpeg的库,而不是用ffmpeg.exe,ffmpeg.exe转出来的视频可以用系统自带的播放!而我使用上述代码转换出来的视频却不能用系统自带的播放器播放,故在此寻求原因。
zzcmx2008 2011-11-15
  • 打赏
  • 举报
回复
这个真不了解
wgm001 2011-11-15
  • 打赏
  • 举报
回复
直接使用ffmpeg.exe
执行:
ffmpeg.exe -i <输入视频文件名> <输出视频文件名.mp4>

ctreewang 2011-11-15
  • 打赏
  • 举报
回复
楼主 我是过来帮顶的,你这方面我真的是不会,也不懂啊~~~~真的太不好意思啊~~~~~~~~~~~


只是过来给接分啊 @@@@@@@
科比布莱恩特 2011-11-15
  • 打赏
  • 举报
回复
这个需要ddshow吧,比较复杂,视频的资料比较少的哦。难。

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧