muxing.c 解读

muxing.c 解读
------------------------------------------------------------
很好的演示代码,生成媒体文件.是音频编码,视频编码,复用的组合体.
代码略有名称修改,方面阅读
1. 首先,创建一个avf_ctx,
  avformat_alloc_output_context2(&avf_ctx, NULL, NULL, filename);
  关联了filename.
 于是可得到它的输出格式AVOutputFormat* o_fmt;
   o_fmt = avf_ctx->oformat;
2. 添加一个视频流, 音频流
   add_stream(&video_st, avf_ctx, &video_codec, o_fmt->video_codec);

   这个add_stream 是自定义函数, 输入avf_ctx, o_fmt->video_codec为codec_id
   输出:video_st, 自定义结构, 将一些指针收集起来方便使用.
   输出:video_codec, AVCodec 结构

    具体创建过程可继续分解为:
    //创建一个stream
    ost->st = avformat_new_stream(avf_ctx, NULL);
    ost->st->id = avf_ctx->nb_streams-1; // stream->id
    //由codec_id 可以找到codec
    codec = avcodec_find_encoder(codec_id);
    //由codec 可创建codec_ctx    
    c = avcodec_alloc_context3(codec);
    //context 保存
    ost->enc = c;
    //对codec_ctx 进行初始化,进行填充,例如对于视频
        c->codec_id = codec_id;
        c->bit_rate = 400000;
        c->width    = 352;
        c->height   = 288;
        /* timebase: This is the fundamental unit of time (in seconds) in terms
         * of which frame timestamps are represented. For fixed-fps content,
         * timebase should be 1/framerate and timestamp increments should be
         * identical to 1. */
        ost->st->time_base = (AVRational){ 1, 25 }; //25帧
        c->time_base       = ost->st->time_base;
        c->gop_size      = 12; /* emit one intra frame every twelve frames at most */
        c->pix_fmt       = AV_PIX_FMT_YUV420P ;
    //对于音频,进行另外的一套初始化, 简化一下写法,
        c->bit_rate    = 64000;
        c->sample_fmt  =  AV_SAMPLE_FMT_FLTP;
        c->sample_rate = 44100;
        c->channel_layout = AV_CH_LAYOUT_STEREO;
        c->channels        = av_get_channel_layout_nb_channels(c->channel_layout);
        ost->st->time_base = (AVRational){ 1, c->sample_rate };

    //填充stream 的codepar
    ret = avcodec_parameters_from_context(ost->st->codecpar, c);

    音频考虑上重采样,还有
    ost->swr_ctx = swr_alloc(); , av_opt_set, swr_init(ost->swr_ctx)
    这样初始化过后, 就算打开了video 及 audio

3.    然后可以打印一下状态:
    av_dump_format(avf_ctx, 0, filename, 1);

4.  如果需要,打开输出文件, 有可能已经自动打开了.
    /* open the output file, if needed */
    if (!(o_fmt->flags & AVFMT_NOFILE)) {
        ret = avio_open(&avf_ctx->pb, filename, AVIO_FLAG_WRITE);
    }
    /* Write the stream header, if any. 一些选项就在这里设定了 */
    ret = avformat_write_header(avf_ctx, &opt);
5. 根据pts, 开始编码视频frame, 音频frame
5.1: 比较pts,
    int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
    其意义是 ts_a * tb_a.num/tb_a.den 数值与 ts_b *tb_b.num/db_b.den 数值比较
    就是演播时间的比较, 当然计算上会有一些优化.

    (gdb) info args
      ts_a = 1            // 视频时间戳
      tb_a = {
        num = 1,         // 视频时基
        den = 25
      }
      ts_b = 1152        // 音频时间戳
      tb_b = {
        num = 1,
        den = 44100        // 音频时基
      }

    下一个视频是1/25=0.04, 下一个音频是1152/44100=0.026, 音频小,先编音频.
5.2: get_frame,  (video_frame or audio_frame)
    get_video_frame, 实际是:
        fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height);
    get_audio_frame 实际是:
        int16_t *q = (int16_t*)frame->data[0];
        for (j = 0; j <frame->nb_samples; j++) { // 填充1152个数据.
            v = (int)(sin(ost->t) * 10000);
            for (i = 0; i < ost->enc->channels; i++)
                *q++ = v;
            ost->t     += ost->tincr;
            ost->tincr += ost->tincr2;
        }
        frame->pts = ost->next_pts;
        ost->next_pts  += frame->nb_samples;
5.3: write_frame
    ret = avcodec_send_frame(c, frame);
    ret = avcodec_receive_packet(c, &pkt); // 完成数据压缩

    av_packet_rescale_ts(&pkt, c->time_base, st->time_base); //调整一下时间戳
    pkt.stream_index = st->index;

    /* Write the compressed frame to the media file. */
    ret = av_interleaved_write_frame(fmt_ctx, &pkt);  //写到输出文件

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值