使用ffmpeg封装ts流的问题

sghcpt 2012-04-27 03:35:53
各位好,我的问题是这样的。我有一个 h264编码的ES流视频文件,我想用ffmpeg来把视频文件封装成TS流。代码如下(部分代码来自网上,谢谢共享这份代码的网友)
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#ifdef __cplusplus
extern "C"{
#endif

#include "libavformat\avformat.h"
#include "libavcodec\avcodec.h"
#include "libavutil\avutil.h"
#include "libavutil\rational.h"
#include "libavdevice\avdevice.h"
#include "libavutil/mathematics.h"
#include "libswscale/swscale.h"

#ifdef __cplusplus
}
#endif //__cplusplus


static AVStream* add_output_stream(AVFormatContext* output_format_context, AVStream* input_stream)
{
AVCodecContext* input_codec_context = NULL;
AVCodecContext* output_codec_context = NULL;

AVStream* output_stream = NULL;
output_stream = av_new_stream(output_format_context, 0);
if (!output_stream)
{
printf("Call av_new_stream function failed\n");
return NULL;
}

input_codec_context = input_stream->codec;
output_codec_context = output_stream->codec;

output_codec_context->codec_id = input_codec_context->codec_id;
output_codec_context->codec_type = input_codec_context->codec_type;
output_codec_context->codec_tag = input_codec_context->codec_tag;
output_codec_context->bit_rate = input_codec_context->bit_rate;
output_codec_context->extradata = input_codec_context->extradata;
output_codec_context->extradata_size = input_codec_context->extradata_size;

if (av_q2d(input_codec_context->time_base) * input_codec_context->ticks_per_frame > av_q2d(input_stream->time_base) && av_q2d(input_stream->time_base) < 1.0 / 1000)
{
output_codec_context->time_base = input_codec_context->time_base;
output_codec_context->time_base.num *= input_codec_context->ticks_per_frame;
}
else
{
output_codec_context->time_base = input_stream->time_base;
}
switch (input_codec_context->codec_type)
{
case AVMEDIA_TYPE_AUDIO:
output_codec_context->channel_layout = input_codec_context->channel_layout;
output_codec_context->sample_rate = input_codec_context->sample_rate;
output_codec_context->channels = input_codec_context->channels;
output_codec_context->frame_size = input_codec_context->frame_size;
if ((input_codec_context->block_align == 1 && input_codec_context->codec_id == CODEC_ID_MP3) || input_codec_context->codec_id == CODEC_ID_AC3)
{
output_codec_context->block_align = 0;
}
else
{
output_codec_context->block_align = input_codec_context->block_align;
}
break;
case AVMEDIA_TYPE_VIDEO:
output_codec_context->pix_fmt = input_codec_context->pix_fmt;
output_codec_context->width = input_codec_context->width;
output_codec_context->height = input_codec_context->height;
output_codec_context->has_b_frames = input_codec_context->has_b_frames;
if (output_format_context->oformat->flags & AVFMT_GLOBALHEADER)
{
output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
break;
default:
break;
}

return output_stream;
}

int _tmain(int argc, _TCHAR* argv[])
{

const char* input = "F:\\VideoPlayer\\debug\\StreamTotal.h264";
const char* output_prefix = NULL;
char* segment_duration_check = 0;
const char* index = NULL;
char* tmp_index = NULL;
const char* http_prefix = NULL;
long max_tsfiles = NULL;
double prev_segment_time = 0;
double segment_duration = 0;

AVInputFormat* ifmt = NULL;
AVOutputFormat* ofmt = NULL;
AVFormatContext* ic = NULL;
AVFormatContext* oc = NULL;
AVStream* video_st = NULL;
AVStream* audio_st = NULL;
AVCodec* codec = NULL;
AVDictionary* pAVDictionary = NULL;

av_register_all();

char szError[256] = {0};
int nRet = avformat_open_input(&ic, input, ifmt, &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(ic) < 0)
{
printf("Call av_find_stream_info function failed!\n");
return 0;
}

ofmt = av_guess_format("mpegts", NULL, NULL);
if (!ofmt)
{
printf("Call av_guess_format function failed!\n");
return 0;
}

oc = avformat_alloc_context();
if (!oc)
{
printf("Call av_guess_format function failed!\n");
return 0;
}
oc->oformat = ofmt;

int video_index = -1, audio_index = -1;
for (unsigned int i = 0; i < ic->nb_streams && (video_index < 0 || audio_index < 0); i++)
{
switch (ic->streams[i]->codec->codec_type)
{
case AVMEDIA_TYPE_VIDEO:
video_index = i;
ic->streams[i]->discard = AVDISCARD_NONE;
video_st = add_output_stream(oc, ic->streams[i]);
break;
case AVMEDIA_TYPE_AUDIO:
audio_index = i;
ic->streams[i]->discard = AVDISCARD_NONE;
audio_st = add_output_stream(oc, ic->streams[i]);
break;
default:
ic->streams[i]->discard = AVDISCARD_ALL;
break;
}
}
codec = avcodec_find_decoder(video_st->codec->codec_id);
if (codec == NULL)
{
printf("Call avcodec_find_decoder function failed!\n");
return 0;
}

if (avcodec_open(video_st->codec, codec) < 0)
{
printf("Call avcodec_open function failed !\n");
return 0;
}

if (avio_open(&oc->pb, "F:\\VideoPlayer\\debug\\264.ts", AVIO_FLAG_WRITE) < 0)
{
return 0;
}

if (avformat_write_header(oc, &pAVDictionary))
{
printf("Call avformat_write_header function failed.\n");
return 0;
}

int decode_done = 0;
do
{
double segment_time = 0;
AVPacket packet;
decode_done = av_read_frame(ic, &packet);
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 && (packet.flags & AV_PKT_FLAG_KEY))
{
segment_time = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
}
else if (packet.stream_index == audio_index) {
segment_time = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
}
else {
segment_time = prev_segment_time;
}
nRet = av_interleaved_write_frame(oc, &packet);
if (nRet < 0)
{
printf("Call av_interleaved_write_frame function failed\n");
}
else if (nRet > 0)
{
printf("End of stream requested\n");
av_free_packet(&packet);
break;
}
av_free_packet(&packet);
}while(!decode_done);

av_write_trailer(oc);

av_bitstream_filter_close(bsfc);
avcodec_close(video_st->codec);
for(unsigned int k = 0; k < oc->nb_streams; k++)
{
av_freep(&oc->streams[k]->codec);
av_freep(&oc->streams[k]);
}
av_free(oc);
getchar();
return 0;
}

但在上面的处理中, avformat_open_input函数就返回错误,显示错误信息为“发现无效的数据当处理输入时”,请问各位有没有遇到这样的情况,应该是由什么问题引起的了?谢谢了。
...全文
2498 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
funphchen 2014-07-29
  • 打赏
  • 举报
回复
出现“发现无效的数据当处理输入时”可能是你全部复制代码运行造成了,我用vs2003,全部复制代码也出现这个问题,一个函数一个函数地敲上去就没这个问题了。可能编译器问题。
busybeeCS 2013-01-09
  • 打赏
  • 举报
回复
[quote=引用 楼主 sghcpt 的回复:] 各位好,我的问题是这样的。我有一个 h264编码的ES流视频文件,我想用ffmpeg来把视频文件封装成TS流。代码如下(部分代码来自网上,谢谢共享这份代码的网友) [quote] 请问一下你是怎么解决这个问题的啊
mj5lucky 2012-05-09
  • 打赏
  • 举报
回复
楼主,可能是你的文件路径没有对,所以会造成打开文件失败,我已经使用你这份代码实现了你说的功能,只是PCR抖动很大,播放速度也不对,只要是因为没有给出PTS,他是按码率来估算的。
wsxzx1989 2012-05-07
  • 打赏
  • 举报
回复
请问楼主问题解决了吗?我也遇到和你一样的问题。。解决方法是怎么样?
sghcpt 2012-04-28
  • 打赏
  • 举报
回复
To rightorwrong
谢谢你的回答。对于avformat_open_input函数,当我只改变传进的文件格式,如*.mpg或者.mp4格式的文件的时候,它是调用成功的。它传进的ifmt也是NULL值的呀。
rightorwrong 2012-04-28
  • 打赏
  • 举报
回复
肯定的是你avformat_open_input参数错误,从ffmpeg 中找个这个函数使用方法的demo,对比下
AVInputFormat* ifmt = NULL没有赋值啊
sghcpt 2012-04-27
  • 打赏
  • 举报
回复
To yubo198
谢谢你的回答。请问一下,你上面所说的“自带的ffmpeg应用程序来尝试”是什么意思了?
yubo198 2012-04-27
  • 打赏
  • 举报
回复
没有遇到过此问题,但是建议你先用其自带的ffmpeg应用程序来尝试,如果也有问题那就麻烦些,否则就说明你的代码或者ES流存在问题。

2,542

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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