忘性較大。記錄:
////add video and audio stream.
AVStream * add_video_stream(AVFormatContext *oc, int codec_id, int width, int height, int fps, int bit_rate)
{
AVCodecContext *c;
AVStream *st;
st = av_new_stream(oc, 0);
if (!st) {
return 0;
}
st->pts.val = 0;
st->pts.num = 1;
st->pts.den = fps;
st->time_base.num = 1;
st->time_base.den = fps;
st->sample_aspect_ratio.num = 10;
st->sample_aspect_ratio.den = 10;
st->codec->codec_id = (CodecID)codec_id;
st->codec->codec_type = CODEC_TYPE_VIDEO;
st->codec->bit_rate = bit_rate;
st->codec->width = width;
st->codec->height = height;
st->codec->gop_size = 25;
st->codec->time_base.num = 1;
st->codec->time_base.den = fps;
st->codec->pix_fmt = PIX_FMT_YUV420P;
st->codec->has_b_frames = 0;
st->codec->sample_aspect_ratio.num = 10;
st->codec->sample_aspect_ratio.den = 10;
if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
return st;
}
void make_dsi( unsigned int sampling_frequency_index, unsigned int channel_configuration, unsigned char* dsi )
{
unsigned int object_type = 2; // AAC LC by default
dsi[0] = (object_type<<3) | (sampling_frequency_index>>1);
dsi[1] = ((sampling_frequency_index&1)<<7) | (channel_configuration<<3);
}
int get_sr_index(unsigned int sampling_frequency)
{
switch (sampling_frequency) {
case 96000: return 0;
case 88200: return 1;
case 64000: return 2;
case 48000: return 3;
case 44100: return 4;
case 32000: return 5;
case 24000: return 6;
case 22050: return 7;
case 16000: return 8;
case 12000: return 9;
case 11025: return 10;
case 8000: return 11;
case 7350: return 12;
default: return 0;
}
}
AVStream * add_audio_stream(AVFormatContext *oc, int codec_id, int samples, int channels, int bit_rate )
{
AVStream *st;
st = av_new_stream(oc, 1);
if (!st) {
return 0;
}
st->pts.val = 0;
st->pts.num = 1;
st->pts.den = samples;
st->time_base.num = 1;
st->time_base.den = samples;
st->sample_aspect_ratio.num = 1;
st->sample_aspect_ratio.den = 1;
st->discard = AVDISCARD_NONE;
st->codec->codec_type = CODEC_TYPE_AUDIO;
st->codec->sample_fmt = SAMPLE_FMT_S16;
st->codec->codec_id = (CodecID)codec_id;
st->codec->bit_rate = bit_rate;
st->codec->sample_rate = samples;
st->codec->channels = channels;
st->codec->frame_size = (codec_id == CODEC_ID_AAC) ? 1024 : 1;
st->codec->block_align = 1;
st->codec->time_base.num = 1;
st->codec->time_base.den = samples;
if( codec_id == CODEC_ID_AAC )
{
unsigned char dsi1[2];
make_dsi( (unsigned int)get_sr_index( (unsigned int)samples ), (unsigned int)channels, dsi1 );
st->codec->extradata_size = 2;
st->codec->extradata = (uint8_t*)av_malloc( 2 );
memcpy( st->codec->extradata, dsi1, 2 );
}
if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
return st;
}
////write video and audio:
int write_video(unsigned char* pBuffer, size_t iBufSize, int key, unsigned long long ts){
if( 0 == m_FormatContext ) return 1;
if(m_first_ts == 0){
m_first_ts = ts;
}
AVPacket pkt;
av_init_packet(&pkt);
AVRational av_time_base_q;
av_time_base_q.num = 1;
av_time_base_q.den = 1000000;
unsigned long long new_ts = 0;
//new_ts = av_rescale_q(ts - m_first_ts, m_VideoStream->codec->time_base, m_VideoStream->time_base);
new_ts = av_rescale_q( ts, av_time_base_q, m_VideoStream->time_base );
pkt.pts = new_ts;
pkt.dts = pkt.pts;
if(m_last_dts >= pkt.pts){
pkt.pts = m_last_dts + 1;
pkt.dts = pkt.pts;
}
m_last_dts = pkt.dts;
if(key){
pkt.flags |= PKT_FLAG_KEY;
}
pkt.stream_index = m_VideoStream->index;
pkt.data = (unsigned char *)av_malloc(iBufSize);
pkt.size = iBufSize;
memcpy(pkt.data, pBuffer, iBufSize);
int ret = av_write_frame(m_FormatContext, &pkt);
av_free(pkt.data);
_ASSERT(ret == 0);
return 0;
}
int write_audio_ts(unsigned char* pBuffer, size_t iBufSize, unsigned long long ts){
if( 0 == m_FormatContext ) return 1;
if(!m_has_audio)return 0;
if(m_first_ts == 0)return 0;
AVPacket pkt;
av_init_packet(&pkt);
AVRational av_time_base_q;
av_time_base_q.num = 1;
av_time_base_q.den = 1000000;
unsigned long long new_ts = 0;
//new_ts = av_rescale_q(ts - m_first_ts, m_AudioStream->codec->time_base, m_AudioStream->time_base);
new_ts = av_rescale_q( ts, av_time_base_q, m_AudioStream->time_base );
pkt.pts = new_ts;
pkt.dts = pkt.pts;
if(audio_pts >= pkt.pts){
pkt.pts = audio_pts + iBufSize / 2;
pkt.dts = pkt.pts;
}
audio_pts = pkt.dts;
pkt.flags |= PKT_FLAG_KEY;
pkt.stream_index = m_AudioStream->index;
pkt.data = (unsigned char *)av_malloc(iBufSize);
pkt.size = iBufSize;
memcpy(pkt.data, pBuffer, iBufSize);
int ret = av_write_frame(m_FormatContext, &pkt);
av_free(pkt.data);
return 0;
}