ffmpeg转封装文件
图示
封装步骤
- avformat_open_input 打开输入文件,初始化AVFormatContext结构体
- avformat_find_stream_info 查找流信息
- avformat_alloc_output_context2 申请输出容器上下文
- avcodec_parameters_to_context / avcodec_parameters_from_context 拷贝输入容器中流的参数到输出容器中
- avio_open 打开输出IO上下文
- avformat_write_header 写输出的文件头
- av_read_frame / av_interleaved_write_frame 从输入读取帧,优化时间戳,写入到输出
- 结束,释放
代码
#include <stdio.h> #include <error_code.h> extern "C"{ #include <libavformat/avformat.h> #include <libavutil/log.h> }; int transcode(const char* input , const char* output){ int ret = ERROR_SUCCESS; //av_register_all(); // for aac AVBSFContext *avbsf_ctx = NULL; const AVBitStreamFilter* av_bsf = av_bsf_get_by_name("aac_adtstoasc"); ret = av_bsf_alloc(av_bsf , &avbsf_ctx); if(ret != 0){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to alloc bsf\n"); return ERROR_ALLOC_BSF; } //av_bsf_init(avbsf_ctx); AVFormatContext *ifmt_ctx = NULL; AVFormatContext *ofmt_ctx; AVOutputFormat *ofmt = NULL; ret = avformat_open_input(&ifmt_ctx , input , NULL , NULL); if(ret != 0){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to open the input file\n" , ret); return ERROR_OPEN_INPUT; } ret = avformat_find_stream_info(ifmt_ctx , NULL); if(ret < 0){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to find the input file stream info\n" , ret); return ERROR_FIND_STREAM; } av_dump_format(ifmt_ctx , 0 , input , 0); ret = avformat_alloc_output_context2(&ofmt_ctx , NULL , NULL , output); if(ret < 0){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to alloc output format context\n" , ret); return ERROR_ALLOC_OUTPUT; } ofmt = ofmt_ctx->oformat; for(int i = 0 ; i < ifmt_ctx->nb_streams ; i++){ AVStream *in_stream = ifmt_ctx->streams[i]; AVCodec *codec = avcodec_find_decoder(in_stream->codecpar->codec_id); AVStream *out_stream = avformat_new_stream(ofmt_ctx , codec); if(!out_stream){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to alloc new stream [%d] for output fmtctx\n" , ret, i); return ERROR_ALLOC_STREAM; } AVCodecContext *p_codec_ctx = avcodec_alloc_context3(codec); ret = avcodec_parameters_to_context(p_codec_ctx , in_stream->codecpar); if(ret < 0){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to praramters to context stream [%d] parameters to outstream\n" , ret, i); return ERROR_COPY_PARAMS; } p_codec_ctx->codec_tag = 0; if(ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER){ p_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } ret = avcodec_parameters_from_context(out_stream->codecpar , p_codec_ctx); if(ret < 0){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to paramters codec paramter \n" , ret); } } av_dump_format(ofmt_ctx , NULL , output , 1); AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; if (!(ofmt->flags & AVFMT_NOFILE)) { ret = avio_open(&ofmt_ctx->pb, output, AVIO_FLAG_WRITE); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "eno:[%d] error to open the output file to write\n", ret); return ERROR_AVIO_OPEN; } } ret = avformat_write_header(ofmt_ctx , NULL); if(ret < 0){ av_log(NULL , AV_LOG_ERROR , "eno:[%d] error to write the header for output\n" , ret); return ERROR_WRITE_HEAD; } int index = 0; while(1){ ret = av_read_frame(ifmt_ctx , &pkt); if(ret < 0){ av_log(NULL , AV_LOG_WARNING , "read frame error\n"); break; } AVStream* in_stream = ifmt_ctx->streams[pkt.stream_index]; AVStream* out_stream = ofmt_ctx->streams[pkt.stream_index]; pkt.pts = av_rescale_q_rnd(pkt.pts , in_stream->time_base , out_stream->time_base , AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); pkt.dts = av_rescale_q_rnd(pkt.dts , in_stream->time_base , out_stream->time_base , AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); pkt.duration = av_rescale_q(pkt.duration , in_stream->time_base , out_stream->time_base); pkt.pos = -1; //for aac if(pkt.stream_index == 1 ){ ret = av_bsf_send_packet(avbsf_ctx , &pkt); if(ret != 0){ av_log(NULL , AV_LOG_WARNING , "wno:[%d] filter audio error\n",ret); continue; } ret = av_bsf_receive_packet(avbsf_ctx , &pkt); } ret = av_interleaved_write_frame(ofmt_ctx , &pkt); if(ret < 0){ index++; av_packet_unref(&pkt); continue; } av_log(NULL , AV_LOG_INFO , "write frame [%d] ok\n" , index); index++; av_packet_unref(&pkt); } av_write_trailer(ofmt_ctx); avformat_close_input(&ifmt_ctx); avio_close(ofmt_ctx->pb); avformat_free_context(ofmt_ctx); return ret; } int main(int argc , char** argv) { if(argc < 2){ av_log(NULL, AV_LOG_INFO , "usage: ./ffplush input output\n"); av_log(NULL, AV_LOG_INFO , "example: ./ffplush a.ts b.mp4\n"); return -1; } int ret = transcode(argv[1] , argv[2]); return ret; }
编译(CMake)
cmake_minimum_required(VERSION 3.10) project(ffplush) set(CMAKE_CXX_STANDARD 98) include_directories(./src /opt/libs/include) link_directories(/opt/libs/lib/) set(SOURCE_FILES ./src/main.cpp) aux_source_directory(./src SOURCE_FILES) add_executable(ffplush ${SOURCE_FILES}) target_link_libraries(ffplush -lavformat) target_link_libraries(ffplush -lavcodec) target_link_libraries(ffplush -lavutil) target_link_libraries(ffplush -lswresample) target_link_libraries(ffplush -lpthread) target_link_libraries(ffplush -lz) target_link_libraries(ffplush -lm) target_link_libraries(ffplush -lbz2) target_link_libraries(ffplush -lrt)
相关推荐
dingwun 2020-11-16
wangdaren 2020-08-15
wqiaofujiang 2020-07-05
PGzxc 2020-07-04
ShoppingChen 2020-06-25
cherayliu 2020-06-17
83096129 2020-06-08
83096129 2020-06-08
PGzxc 2020-06-01
ShoppingChen 2020-05-29
cherayliu 2020-05-11
ShoppingChen 2020-05-11
83096129 2020-05-10
PGzxc 2020-05-07
cherayliu 2020-04-27
cherayliu 2020-04-11