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

PDuce PDuce 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
因工作要求我将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;
}
...全文

相关推荐

Android 倒计时(时间戳转换天、小时、分钟、秒)

文章地址:https://blog.csdn.net/lou_liang/article/details/124021482?spm=1001.2014.3001.5502 倒计时 = 从后台获取到当前时间的时间戳 - 商品的截止时间 (备注:如果当前时间的时间戳获取手机本地的会出问题,因为调整本地时间后就造成的时间错误,所以线上环境每次取从后台获取到当前时间的时间戳)

亮亮在江湖

如何用JS/HTML将时间戳转换为“xx天前”的形式

如果我们有一份过去时间戳,如何使用JS/HTML将时间戳转换为“xx天前”的形式呢,以下是完整代码 当然,只在同一时区时适用。 你也可以通过Date类将具体时间转换为时间戳。 &lt;!DOCTYPE html> &lt;html&gt; &lt;head&gt; < http equiv=Content-Type content=text/html; charset=utf-8/> < src> &lt;/ > &lt; > $(document).ready(function() { v

weixin_38684743

PHP实现数据库统计时间戳按天分组输出数据的方法

主要介绍了PHP实现数据库统计时间戳按天分组输出数据的方法,涉及php基于时间的运算与数据库查询相关操作技巧,需要的朋友可以参考下

weixin_38515270

【java】如何获取当前时间的时间戳及时间戳转换问题

一、时间戳定义(摘自百度百科) 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。 它的提出主要是为用户提供一份电子证据, 以证明用户的某些数据的产生时间。 在实际应用上, 它可以使用在包括电子商务、 金融活动的各个方面, 尤其可以用来支撑公开密钥基础设施的 “不可否认” 服务。 二、获取当前时间戳的几种方法 方法一:通过System的currentTimeMillis()方法 System.out.println(Syst

weixin_38502693

时间戳转换分天月

根据时间戳转换为多少天月之类的

qq_32000703
评论 7
收藏 已收藏
分享
返回顶部
PDuce
多媒体/流媒体开发 2,554 成员 20,277 内容