赞
踩
分配视频文件上下文
int Init(const char *url);
创建流,赋值给视频的音频流和视频流
int AddStream(AVCodecContext *codec_ctx);
写视频流的head
int SendHeader();
写视频流的packet,需要转换packet的pts和dts , 值为 原有pts * 编码时间基/ 视频流的时间基
int SendPacket(AVPacket *packet)
写视频流的trail
int SendTrailer();
释放资源
void DeInit();
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const
// 时间基转换函数 , 计算结果为 a * bq / cq
#ifndef MUXER_H #define MUXER_H #include <iostream> extern "C" { #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" } class Muxer { public: Muxer(); ~Muxer(); // 输出文件 返回<0值异常 // 初始化 int Init(const char *url); // 资源释放 void DeInit(); // 创建流 int AddStream(AVCodecContext *codec_ctx); // 写流 int SendHeader(); int SendPacket(AVPacket *packet); int SendTrailer(); int Open(); // avio open private: AVFormatContext *fmt_ctx_ = NULL; std::string url_ = ""; // 编码器上下文 AVCodecContext *aud_codec_ctx_= NULL; AVStream *aud_stream_ = NULL; AVCodecContext *vid_codec_ctx_= NULL; AVStream *vid_stream_ = NULL; int audio_index_ = -1; int video_index_ = -1; }; #endif // MUXER_H
#include "muxer.h" Muxer::Muxer() { } Muxer::~Muxer() { } int Muxer::Init(const char *url) { int ret = avformat_alloc_output_context2(&fmt_ctx_, NULL, NULL,url); if(ret != 0) { char errbuf[1024] = {0}; av_strerror(ret, errbuf, sizeof(errbuf) - 1); printf("avformat_alloc_output_context2 failed:%s\n", ret); return -1; } url_ = url; return 0; } void Muxer::DeInit() { if(fmt_ctx_) { avformat_close_input(&fmt_ctx_); } url_ = ""; aud_codec_ctx_ = NULL; aud_stream_ = NULL; audio_index_ = -1; vid_codec_ctx_ = NULL; vid_stream_ = NULL; video_index_ = -1; } int Muxer::AddStream(AVCodecContext *codec_ctx) { if(!fmt_ctx_) { printf("fmt ctx is NULL\n"); return -1; } if(!codec_ctx) { printf("codec ctx is NULL\n"); return -1; } AVStream *st = avformat_new_stream(fmt_ctx_, NULL); if(!st) { printf("avformat_new_stream failed\n"); return -1; } // st->codecpar->codec_tag = 0; // 从编码器上下文复制, 根据提供的编解码器的值填充参数结构 avcodec_parameters_from_context(st->codecpar, codec_ctx); av_dump_format(fmt_ctx_, 0, url_.c_str(), 1); // 判断当前的是视频流还是音频流 if(codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { aud_codec_ctx_ = codec_ctx; aud_stream_ = st; audio_index_ = st->index; } else if(codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { vid_codec_ctx_ = codec_ctx; vid_stream_ = st; video_index_ = st->index; } return 0; } int Muxer::SendHeader() { if(!fmt_ctx_) { printf("fmt ctx is NULL\n"); return -1; } int ret = avformat_write_header(fmt_ctx_, NULL); if(ret != 0) { char errbuf[1024] = {0}; av_strerror(ret, errbuf, sizeof(errbuf) - 1); printf("avformat_write_header failed:%s\n", ret); return -1; } return 0; } int Muxer::SendPacket(AVPacket *packet) { int stream_index = packet->stream_index; if(!packet || packet->size <= 0 || !packet->data) { printf("packet is null\n"); if(packet) av_packet_free(&packet); return -1; } AVRational src_time_base; // 编码后的包 AVRational dst_time_base; // mp4输出文件对应流的time_base if(vid_stream_ && vid_codec_ctx_ && stream_index == video_index_) { src_time_base = vid_codec_ctx_->time_base; dst_time_base = vid_stream_->time_base; } else if(aud_stream_ && aud_codec_ctx_ && stream_index == audio_index_) { src_time_base = aud_codec_ctx_->time_base; dst_time_base = aud_stream_->time_base; } // 时间基转换 // int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; // 时间基转换函数 a * bq / cq packet->pts = av_rescale_q(packet->pts, src_time_base, dst_time_base); packet->dts = av_rescale_q(packet->dts, src_time_base, dst_time_base); packet->duration = av_rescale_q(packet->duration, src_time_base, dst_time_base); int ret = 0; //写packet ret = av_interleaved_write_frame(fmt_ctx_, packet); // 不是立即写入文件,内部缓存,主要是对pts进行排序 // ret = av_write_frame(fmt_ctx_, packet); av_packet_free(&packet); if(ret == 0) { return 0; } else { char errbuf[1024] = {0}; av_strerror(ret, errbuf, sizeof(errbuf) - 1); printf("avformat_write_header failed:%s\n", ret); return -1; } } int Muxer::SendTrailer() { if(!fmt_ctx_) { printf("fmt ctx is NULL\n"); return -1; } int ret = av_write_trailer(fmt_ctx_); if(ret != 0) { char errbuf[1024] = {0}; av_strerror(ret, errbuf, sizeof(errbuf) - 1); printf("av_write_trailer failed:%s\n", ret); return -1; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。