ffmpeg, mov+aac,時間戳

 

忘性較大。記錄:

////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;
 }


發佈了136 篇原創文章 · 獲贊 5 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章