【FFmpeg4.1.4】音视频分离器

一、MP4提取H265裸流无效

FFmpeg解封装得到的AVPacket只包含了视频压缩数据,没有相关的参数集信息(比如:h265的vps头信息,h264的sps、pps头信息,AAC的adts头信息),不能初始化解码器。

二、添加头信息

StartCodePrefix的两种方式: Annex B和HVCC。

  1. Annex B:在NALU前加0x000001或者0x00000001 ;
  2. HVCC:在NALU前加上指示其长度的前缀。

MP4编码方式,Nalu开始四个字节表示数据长度。在FFmpeg中,这些头信息(VPS、SPS、PPS)是保存在解码器上下文(AVCodecContext)的extradata中的,所以我们需要为每一种格式的视频添加相应的解码头信息,这样解码器(MediaCodec)才能正确解析每一个AVPacket里的视频数据。FFmpeg提供了AVBitStreamFilter类实现头信息添加的功能。

三、音视频分离步骤

  1. 获取AVPacket
av_read_frame(fmt_ctx, &pkt)
  1. 添加头信息
if (av_bsf_send_packet(bsf_ctx, &pkt) < 0) {
   
	std::cerr << "failed to push" << std::endl;
	exit(1);
}			
while (av_bsf_receive_packet(bsf_ctx, &pkt) == 0);

1、简单版本(不支持音频AAC)

#include <iostream>
#include <string>
#ifdef __cplusplus
extern "C" {
   
#endif // __cplusplus

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>

#ifdef __cplusplus
}
#endif // __cplusplus

int demux(std::string mediafile) {
   
	const AVBitStreamFilter *filter = NULL;
	AVFormatContext *fmt_ctx = NULL;
	AVBSFContext *bsf_ctx;
	AVPacket pkt;
	AVStream* videostream = NULL;
	AVStream* audiostream = NULL;
	AVCodecID video_codec_id;
	AVCodecID audio_codec_id;
	FILE *fp_vides = NULL, *fp_audes = NULL;
	int i, vid_idx, aud_idx;

	std::string videofile;
	std::string audiofile;

	if (avformat_open_input(&fmt_ctx, mediafile.c_str(), NULL, NULL) != 0) {
   
		av_log(NULL, AV_LOG_ERROR, "Could not open input file");
		exit(1);
	}
	av_dump_format(fmt_ctx, 0, mediafile.c_str(), 0);

	if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
   
		avformat_free_context(fmt_ctx);
		av_log(NULL, AV_LOG_ERROR, "Failed to retrieve input stream information");
		exit(1);
	}
	
	for (i = 0; i<fmt_ctx->nb_streams; i++)
	{
   
		//vidoe
		if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
   
			vid_idx = i;
			videostream = fmt_ctx->streams[vid_idx];
			video_codec_id = videostream->codecpar->codec_id;
		}
		//audio
		else if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
   
			aud_idx = i;
			audiostream = fmt_ctx->streams[aud_idx];
			audio_codec_id = audiostream->codecpar->codec_id;
		}
		//such as subtitile
		else {
   
			//To DO
		}
	}
	
	if (videostream) {
   
		switch (video_codec_id) {
   
		case AV_CODEC_ID_H264:
			filter = av_bsf_get_by_name("h264_mp4toannexb");
			videofile = "video_es.h264";
			break;
		case AV_CODEC_ID_HEVC:
			filter = av_bsf_get_by_name("hevc_mp4toannexb");
			videofile = "video_es.h265";
			break;
		default:
			av_log(NULL, AV_LOG_ERROR, "Unkonw Video AVCodecID");
			exit(1);
		}
		fp_vides = fopen(videofile.c_str(), "wb");
		if (!fp_vides) {
   
			std::cerr << "Could not open file" << videofile.c_str() << std::endl;
			exit(
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值