被时间戳的问题卡了好几天了.

PDuce 2014-04-03 02:49:43
因工作要求我将h264编码的流封装成mp4,刚接触多媒体处理,在网上搜了个源码改了下,发现能成功封装成功,但是封装出来的mp4文件的播放总秒数少了几十秒,貌似应该是时间戳的问题,下面贴出源码,忘高手能帮忙看下,从内存中读出来的NAL怎么获取时间戳呢? 我是在WriteFrameFromData里用av_rescale_q处理的。。这问题卡好几天了,都没找到一个答案!!!!



main.cpp
#include "Mp4Muxer.h"

static int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
int info;
int i;

info = 1;
for (i = 0; i < zeros_in_startcode; i++)
{
if(Buf[i] != 0)
info = 0;
}

if(Buf[i] != 1)
info = 0;
return info;
}

static bool Check_StartCode(unsigned char *Buf, int pos)
{
int info3 = 0;

info3 = FindStartCode(&Buf[pos-4], 3);
return info3 == 1;

}

static int getNextNal(FILE* inpf, unsigned char* Buf)
{
int pos = 0;
int StartCodeFound = 0;
int info2 = 0;
int info3 = 0;

int nCount = 0;
while(!feof(inpf) && ++nCount <= 4)
{
Buf[pos++]=fgetc(inpf);
}

if(!Check_StartCode(Buf, pos))
{
return 0;
}


while(!feof(inpf) && (Buf[pos++]=fgetc(inpf))==0);

while (!StartCodeFound)
{
if (feof (inpf))
{
return pos-1;
}

Buf[pos++] = fgetc (inpf);

StartCodeFound = Check_StartCode(Buf, pos);
}

fseek(inpf, -4, SEEK_CUR);
return pos - 4;
}

int main()
{
CMp4Muxer mp4("1.mp4");

unsigned char *p_In_Frame = new unsigned char[1280 * 720 * 3/2];
FILE *pFile = NULL;
pFile = fopen("1.h264", "rb");

while(!feof(pFile))
{
int nCount = getNextNal(pFile, p_In_Frame);

if(nCount == 0)
{
continue;
}

mp4.Start_Pack_Video((char *)p_In_Frame, nCount);
}

mp4.Finish_Pack_Video();

delete[] p_In_Frame;
return 1;
}


Mp4Muxer.h
#pragma once

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>

#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
};

#include <string>
using namespace std;

class CMp4Muxer
{
public:
CMp4Muxer(const char *pstrFileName = NULL,
AVCodecID type = AV_CODEC_ID_H264,
const int nWidth = 1280,
const int nHeight= 720
);
~CMp4Muxer(void);

public:
int AddStreamToVideo();

int PrePackVideo();

int Start_Pack_Video(const char *pVideoData, int nDataSize);
void Finish_Pack_Video();
int MuxingVideo();

private:
AVFormatContext *m_pFormatCtx;
AVOutputFormat *m_pOutputFormat;

AVCodecContext *m_pOutputCodecCtx;
AVStream *m_pOutputStream;
AVCodec *m_pOutputCodec;



public:
int m_nFrameCount;
string m_strOutputFileName;


private:
int m_nWidth;
int m_nHeight;

AVCodecID m_codecType;

bool m_bMuxing;
bool m_bPrepared;
bool m_bWritedHeader;
bool m_bStreamAdded;

uint8_t *m_pInputVideoData;
int m_nInputVideoSize;
uint8_t *m_pInputAudioData;
int m_nInputAudioSize;

};


Mp4Muxer.cpp
#include "Mp4Muxer.h"
#include <afx.h>

int CMp4Muxer::Start_Pack_Video(const char *pVideoData, int nDataSize)
{
if(!pVideoData || IsBadReadPtr(pVideoData, nDataSize) || nDataSize < 1)
{
return 0;
}

m_nInputVideoSize = nDataSize;
m_pInputVideoData = (uint8_t *)pVideoData;

if(0 > PrePackVideo())
{
return -1;
}

if(0 > AddStreamToVideo())
{
return -2;
}

if(0 > MuxingVideo())
{
return -3;
}

return 1;
}

void CMp4Muxer::Finish_Pack_Video()
{
av_write_trailer(m_pFormatCtx);
}

int CMp4Muxer::PrePackVideo()
{
if(m_bPrepared)
{
return 1;
}

if(m_strOutputFileName.empty())
{
return -1;
}

int nRet = 0;
nRet = avformat_alloc_output_context2(&m_pFormatCtx, NULL, NULL, m_strOutputFileName.c_str());

if(nRet < 0 || !m_pFormatCtx)
{
av_free(m_pFormatCtx);
return -2;
}

m_pFormatCtx->oformat->video_codec = GetCodecType();
m_pOutputFormat = m_pFormatCtx->oformat;
av_dump_format(m_pFormatCtx, 0, m_strOutputFileName.c_str(), 1);


m_bPrepared = true;

return 1;
}

int CMp4Muxer::AddStreamToVideo()
{
if(m_bStreamAdded)
{
return 1;
}

m_pOutputCodec = avcodec_find_decoder(GetCodecType());
if(!m_pOutputCodec)
{
return -2;
}

m_pOutputStream = avformat_new_stream(m_pFormatCtx, m_pOutputCodec);

if(!m_pOutputStream)
{
return -1;
}

m_pOutputStream->id = m_pFormatCtx->nb_streams - 1;
m_pOutputCodecCtx = m_pOutputStream->codec;

m_pOutputCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
m_pOutputCodecCtx->codec_id = GetCodecType();
m_pOutputCodecCtx->time_base.den= 25;
m_pOutputCodecCtx->time_base.num= 1;
m_pOutputCodecCtx->width = m_nWidth;
m_pOutputCodecCtx->height = m_nHeight;

if(m_pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
m_pOutputCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}

int nRet = 0;
nRet = avcodec_open2(m_pOutputCodecCtx, m_pOutputCodec, NULL);

if(nRet < 0)
{
return -3;
}

if(!(m_pOutputFormat->flags & AVFMT_NOFILE))
{
nRet = avio_open(&m_pFormatCtx->pb, m_strOutputFileName.c_str(), AVIO_FLAG_READ_WRITE);
if(nRet < 0)
{
return -4;
}
}

m_bStreamAdded = true;
return 1;
}

int CMp4Muxer::MuxingVideo()
{
if(!m_bWritedHeader)
{
avformat_write_header(m_pFormatCtx, NULL);
m_bWritedHeader = true;
}

if(!WriteFrameFromData())
{
return -1;
}

return 1;
}

int CMp4Muxer::WriteFrameFromData()
{
AVPacket h264Pkt;
av_init_packet(&h264Pkt);

AVRational base1 = {1, 25};
AVRational base2 = {1, 12800};

h264Pkt.dts = av_rescale_q(m_nFrameCount, m_pOutputCodecCtx->time_base, m_pOutputStream->time_base);
h264Pkt.pts = h264Pkt.dts;

h264Pkt.flags |= AV_PKT_FLAG_KEY;

h264Pkt.stream_index = m_pOutputStream->index;
h264Pkt.data = m_pInputVideoData;
h264Pkt.size = m_nInputVideoSize;

double dTime = h264Pkt.pts * av_q2d(m_pOutputStream->time_base);

m_nFrameCount++;
int nRet = 0;
nRet = av_interleaved_write_frame(m_pFormatCtx, &h264Pkt);
if(nRet < 0)
{
return -1;
}

avio_flush(m_pFormatCtx->pb);
av_free_packet(&h264Pkt);

return 1;
}
...全文
954 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
huyilover 2016-10-10
  • 打赏
  • 举报
回复
求rtsp拉视频流的时间戳如何设定
keepingstudying 2014-05-21
  • 打赏
  • 举报
回复
本人最近也在做相关的事情,能否发一份代码参考下。谢谢。 454716553@qq.com
PDuce 2014-04-03
  • 打赏
  • 举报
回复
额,好吧,多谢!
__cc__ 2014-04-03
  • 打赏
  • 举报
回复
引用 3 楼 u010492861 的回复:
因为我读的是人家给我传的char *的指针,也就是指向"00 00 00 01“这样开头的h264 nal单元,我应该怎么样去计算这个时间戳呢?
你只能解析一下nal,找到pts了。
PDuce 2014-04-03
  • 打赏
  • 举报
回复
因为我读的是人家给我传的char *的指针,也就是指向"00 00 00 01“这样开头的h264 nal单元,我应该怎么样去计算这个时间戳呢?
PDuce 2014-04-03
  • 打赏
  • 举报
回复
还真不等于。。。。那应该怎么计算呢?
__cc__ 2014-04-03
  • 打赏
  • 举报
回复
引用 楼主 u010492861 的回复:
NALU和帧不等价吧,你使用m_nFrameCount计算的,每得到一个NALU,帧数加一,这里应该有问题。你调试一下看看这个m_nFrameCount是否等于原始数据流的帧数。

2,543

社区成员

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

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