zoukankan      html  css  js  c++  java
  • 基于FFMPEG封装aac及h264为FargmentMP4

    FargmentMP4是一种特殊的MP4,这边他的特点及格式,不再详细说明 ,网上资料不少可以进行参考。

    这边说下基于FFMPEG封装aac及h264为FargmentMP4的步骤:

    1.  
      关键代码:
    2.  
      1、创建两个输入对象和一个输出对象并打开。
    3.  
      AVFormatContext *ifmt_ctx_v = NULL, *ifmt_ctx_a = NULL, *ofmt_ctx = NULL;
    4.  
      if ((ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, NULL, NULL)) < 0) {
    5.  
      printf("Could not open input file.");
    6.  
      goto end;
    7.  
      }
    8.  
      // printf("=====2========RET:%d ",ret);
    9.  
      if ((ret = avformat_find_stream_info(ifmt_ctx_a, 0)) < 0) {
    10.  
      printf("Failed to retrieve input stream information");
    11.  
      if (acc_length > 0)
    12.  
      goto end;
    13.  
      }
    14.  
       
    15.  
      if ((ret = avformat_open_input(&ifmt_ctx_v, in_filename_v, NULL, NULL)) < 0) {
    16.  
      printf("Could not open input file:%d ", ret);
    17.  
      goto end;
    18.  
      }
    19.  
      if ((ret = avformat_find_stream_info(ifmt_ctx_v, 0)) < 0) {
    20.  
      printf("Failed to retrieve input stream information");
    21.  
      goto end;
    22.  
      }
    23.  
      avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
    24.  
      if (!ofmt_ctx) {
    25.  
      printf("Could not create output context ");
    26.  
      ret = AVERROR_UNKNOWN;
    27.  
      goto end;
    28.  
      }
    29.  
      ofmt = ofmt_ctx->oformat;
    30.  
       
    31.  
      2、初始化过滤器 因为aac打包到mp4需要去掉adts头。
    32.  
      const AVBitStreamFilter *absFilter = av_bsf_get_by_name("aac_adtstoasc");
    33.  
      AVBSFContext *absCtx = NULL;
    34.  
      av_bsf_alloc(absFilter, &absCtx);
    35.  
       
    36.  
      3、获取视频流信息并拷贝相应编码格式
    37.  
      for (i = 0; i < ifmt_ctx_v->nb_streams; i++) {
    38.  
      //Create output AVStream according to input AVStream
    39.  
      if (ifmt_ctx_v->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
    40.  
      AVStream *in_stream = ifmt_ctx_v->streams[i];
    41.  
      AVCodec *avcodec = avcodec_find_decoder(in_stream->codecpar->codec_id);
    42.  
      AVStream *out_stream = avformat_new_stream(ofmt_ctx, avcodec);
    43.  
      videoindex_v = i;
    44.  
      if (!out_stream) {
    45.  
      printf("Failed allocating output stream ");
    46.  
      ret = AVERROR_UNKNOWN;
    47.  
      goto end;
    48.  
      }
    49.  
      videoindex_out = out_stream->index;
    50.  
      AVCodecContext *codec_ctx = avcodec_alloc_context3(avcodec);
    51.  
      ret = avcodec_parameters_to_context(codec_ctx, in_stream->codecpar);
    52.  
      if (ret < 0) {
    53.  
      printf("Failed to copy context from input to output stream codec context ");
    54.  
      goto end;
    55.  
      }
    56.  
      codec_ctx->codec_tag = 0;
    57.  
      if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
    58.  
      codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    59.  
       
    60.  
      ret = avcodec_parameters_from_context(out_stream->codecpar, codec_ctx);
    61.  
      int q = 0;
    62.  
      }
    63.  
      }
    64.  
       
    65.  
      4、获取音频流信息并拷贝相应编码格式
    66.  
      for (i = 0; i < ifmt_ctx_a->nb_streams; i++) {
    67.  
      if (ifmt_ctx_a->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
    68.  
      AVStream *in_stream = ifmt_ctx_a->streams[i];
    69.  
      AVCodec *avcodec = avcodec_find_decoder(in_stream->codecpar->codec_id);
    70.  
      AVStream *out_stream = avformat_new_stream(ofmt_ctx, avcodec);
    71.  
      audioindex_a = i;
    72.  
      if (!out_stream) {
    73.  
      printf("Failed allocating output stream ");
    74.  
      ret = AVERROR_UNKNOWN;
    75.  
      goto end;
    76.  
      }
    77.  
      audioindex_out = out_stream->index;
    78.  
      avcodec = avcodec_find_decoder(in_stream->codecpar->codec_id);
    79.  
       
    80.  
      avcodec_parameters_copy(absCtx->par_in, in_stream->codecpar);
    81.  
      av_bsf_init(absCtx);
    82.  
       
    83.  
      AVCodecContext *codec_ctx = avcodec_alloc_context3(avcodec);
    84.  
      ret = avcodec_parameters_to_context(codec_ctx, in_stream->codecpar);
    85.  
      if (ret < 0) {
    86.  
      printf("Failed to copy context from input to output stream codec context ");
    87.  
      goto end;
    88.  
      }
    89.  
      codec_ctx->codec_tag = 0;
    90.  
      if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
    91.  
      codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    92.  
       
    93.  
      ret = avcodec_parameters_from_context(out_stream->codecpar, codec_ctx);
    94.  
      out_stream->codecpar->extradata = (uint8_t*)av_malloc(2);
    95.  
      out_stream->codecpar->extradata_size = 2;
    96.  
      unsigned char dsi1[2];
    97.  
      unsigned int sampling_frequency_index = (unsigned int)get_sr_index(8000);
    98.  
      make_dsi(sampling_frequency_index, 1, dsi1);
    99.  
      memcpy(out_stream->codecpar->extradata, dsi1, 2);
    100.  
       
    101.  
      break;
    102.  
      }
    103.  
      }
    104.  
      5、打开MP4文件
    105.  
      if (!(ofmt->flags & AVFMT_NOFILE)) {
    106.  
      if (avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE) < 0) {
    107.  
      printf("Could not open output file '%s'", out_filename);
    108.  
      goto end;
    109.  
      }
    110.  
      }
    111.  
      6、设置字典fmp4的关键
    112.  
      AVDictionary *movflags = nullptr;
    113.  
      const bool low_delay = true;
    114.  
      if (low_delay) {
    115.  
      // In case of low delay, set fragment duration to 200 ms.
    116.  
      av_dict_set(&movflags, "movflags", "empty_moov+default_base_moof", 0);
    117.  
      av_dict_set_int(&movflags, "frag_duration", 200 * 1000, 0);
    118.  
      }
    119.  
      else {
    120.  
      // Only produce fragment until we have next key frame.
    121.  
      av_dict_set(&movflags, "movflags", "empty_moov+default_base_moof+frag_keyframe", 0);
    122.  
      }
    123.  
      //avformat_open_input(&addofmt_ctx, addinputAacFileName, 0, &movflags);
    124.  
      ret = avformat_write_header(ofmt_ctx, &movflags);
    125.  
      if (ret < 0) {
    126.  
      fprintf(stderr, "Error occurred when opening output file ");
    127.  
      goto end;
    128.  
      }
    129.  
      7、打包
    130.  
       
    131.  
      if ((ret = av_interleaved_write_frame(ofmt_ctx, &pkt)) < 0) {
    132.  
      printf("Error muxing packet ");
    133.  
      break;
    134.  
      }

    具体工程参考:https://download.csdn.net/download/venice0708/11434379

  • 相关阅读:
    爱你就是我的幸福
    科学加艺术 85句管理名言
    转:IPV6及在UBUNTU和windows下的安装
    JXSE是否可以实现非阻塞IO?
    Transmitting and Receiving RTP over Custom Transport Layer
    多显示器
    可靠的双向管道和不可靠的双向管道
    the source for JMStudio
    转:浅析 Java Thread.join()
    Building Scalable and High Efficient Java Multimedia Collaboration
  • 原文地址:https://www.cnblogs.com/lidabo/p/14434470.html
Copyright © 2011-2022 走看看