ffmpeg hevc_ffmpeg视频解码

ffmpeg hevc_ffmpeg视频解码本次目标:1)将容器中的音频码流和视频码流分离出来。2)针对mp4文件中的码流情况进行修复。解封装的基本过程:#include<stdio.h>#include”libavcodec/avcodec.h”#include”libavformat/avformat.h”//MPEG-TS文件解封装得到的码流可播放,MP4解封装得到的码流不可播放;//这与容器的封装方式有关。voiddemuxer(constchar*url){//初始化格式上下文

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

本次目标:

1)将容器中的音频码流和视频码流分离出来。

2)针对mp4文件中的码流情况进行修复。

解封装的基本过程:

#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"

// MPEG-TS文件解封装得到的码流可直接播放
// MP4/FLV/MKV解封装得到的码流不可播放;
// 这与容器的封装方式有关。
void demuxer(const char *url) {
    // 初始化格式上下文
    AVFormatContext *fmt_ctx = avformat_alloc_context();
    if (fmt_ctx == NULL) {
        printf("failed to alloc format context\n");
        goto _Error;
    }

    // 打开输入流
    if (avformat_open_input(&fmt_ctx, url, NULL, NULL) < 0) {
        printf("failed to open input url\n");
        goto _Error;
    }

    // 读取媒体文件信息
    if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
        printf("failed to find stream\n");
        goto _Error;
    }
    av_dump_format(fmt_ctx, 0, url, 0);


    // 寻找音频流和视频流下标
    int video_index = -1, audio_index = -1;
    for (int i = 0; i < fmt_ctx->nb_streams; i++) {
        if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_index = i;
        } else if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audio_index = i;
        }
    }
    if (video_index < 0 || audio_index < 0) {
        printf("failed to find stream index\n");
        goto _Error;
    }

    // 由打印的视频文件信息确定码流类型
    char audiofile[128], videofile[128];
    printf("type the name of output audiofile:");
    scanf("%s", audiofile);
    printf("\ntype the name of output videofile:");
    scanf("%s", videofile);
    FILE *faudio = fopen(audiofile, "w+");
    FILE *fvideo = fopen(videofile, "w+");
    AVPacket *packet = av_packet_alloc();

    while (av_read_frame(fmt_ctx, packet) == 0) {

        if (packet->stream_index == audio_index) {
            fwrite(packet->data, 1, packet->size, faudio);
        }
        else if (packet->stream_index == video_index) {
            fwrite(packet->data, 1, packet->size, fvideo);
        }
        av_packet_unref(packet);
    }

_Error:
    if (fmt_ctx) avformat_close_input(&fmt_ctx);
    if (faudio)  fclose(faudio);
    if (fvideo)  fclose(fvideo);
    if (packet)  av_packet_free(&packet);
}


int main(int argc, char const* argv[])
{
    demuxer(argv[1]);
    return 0;
}

编译测试:得到视频信息后,根据文件中的编码信息(mp3或aac,h264或mpeg4,mpeg4码流文件后辍为.m4v),命名解封装的码流文件。
image-20210514113830833

mp4文件解封装得到的h264码流和aac码流都不能解码播放!

1、mp4文件中的码流有什么不同

	Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 
	640x352, 748 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
	
	Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 
	44100 Hz, stereo, fltp, 128 kb/s (default)

MP4封装格式是基于QuickTime容器格式定义,媒体描述与媒体数据分开。从MP4得到的H264和AAC码流是ES流,它们缺失解码时必要的起始码/SPS/PPSadts头

我们常规的H264帧数据保存格式是annexb,是具有起始码0x000001或0x00000001;mpeg-ts文件中保存的是视频码流是存在起始码的,而在mp4文件中没有起始码。

H.264视频编码格式主要分为两种形式,即带起始码的H.264码流不带起始码的H.264码流,其中,前者就是我们比较熟悉的H264、X264;后者就是指AVC1

More:MP4中的H264和AAC

2、怎么修复MP4中的码流?

AAC码流(mp4a):保存一帧码流数据前,补充相应的adts头;

H264码流(avc1):使用h264_mp4toannexb过滤器,对视频码流进行处理。

①每一帧前补充ADTS头

// 生成7字节的ADTS头
char *adts_header_gen(int len) {
    static char header[7];

    int profile = 2;    // AAC LC
    int freqidx = 4;    // 3 - 48k, 4 - 44.1k 
    int chncfg  = 2;    // 声道数量 

    header[0] = 0xFF;
    header[1] = 0xF1;
    header[2] = ((profile-1) << 6) | (freqidx << 2) | (chncfg >> 2);
    header[3] = ((chncfg & 3) << 6)| (len >> 11);
    header[4] = (len & 0x7FF) >> 3;
    header[5] = ((len & 0x7) << 5) | 0x1F;
    header[6] = 0xFC;
    return header;
}
if (packet->stream_index == audio_index) {
	// packet->size是adts中数据块的长度
	fwrite(adts_header_gen(packet->size+7), 1, 7, faudio);
	fwrite(packet->data, 1, packet->size, faudio);
}

More:AAC音频码流解析

②使用h264_mp4toannexb过滤器处理h264码流

// 初始化过滤器
const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
if (bsf == NULL) {
	printf("failed to find stream filter\n");
	goto _Error;
}
AVBSFContext *bsf_ctx;
av_bsf_alloc(bsf, &bsf_ctx);
avcodec_parameters_copy(bsf_ctx->par_in, fmt_ctx->streams[video_index]->codecpar);
av_bsf_init(bsf_ctx);
else if (packet->stream_index == video_index) {
    if (av_bsf_send_packet(bsf_ctx, packet) == 0) {
        while (av_bsf_receive_packet(bsf_ctx, packet) == 0) {
            fwrite(packet->data, 1, packet->size, fvideo);
        }
    }
}

经过比特流过滤器的处理,每个AVPacket的data添加了H.264的NALU的起始码{0,0,0,1};每个IDR帧数据前面添加了SPS和PPS。

More:解析h264视频码流

视频播放效果:

原mp4文件:
image-20210514112106240

out.h264码流文件:
image-20210514112149236

out.aac文件:
image-20210514112333031

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/181225.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 决策树模型参数释义「建议收藏」

    决策树模型参数释义「建议收藏」转自https://blog.csdn.net/qq_16000815/article/details/80954039”’scikit-learn中有两类决策树,它们均采用优化的CART决策树算法。”’fromsklearn.treeimportDecisionTreeRegressor”’回归决策树”’DecisionTreeRegressor(criterio…

    2022年10月8日
    3
  • 分析函数 ExecuteSQL

    分析函数 ExecuteSQL
    在学生管理系统中,执行sql语句时,我们用到这个函数,当时有几点不明,现在说说我的理解。
     
    PublicFunctionExecuteSQL(ByValSQLAsString,MsgStringAsString)AsRecordset
      ……
      sTokens=Split(SQL)
    ‘Split返回一个下标从0开始的一维数组,包含指定数目的子字符串。”Select”+”*”+”from”+”user_Info”+

    2022年5月11日
    40
  • SQL中字符串截取函数(SUBSTRING)

    SQL中字符串截取函数(SUBSTRING)1、left(name,4)截取左边的4个字符列:SELECTLEFT(201809,4)年结果:20182、right(name,2)截取右边的2个字符SELECTRIGHT(201809,2)月份结果:093、SUBSTRING(name,5,3)截取name这个字段从第五个字符开始只截取之后的3个字符SELECTSUBSTRING(‘成都融资事…

    2022年5月24日
    82
  • mysql导入数据库_只用frm向mysql导入表结构

    网上一个连接mysql的jsp代码段,给了数据库的备份文件,但是只有frm,查了下资料,原来只有frm也能导入。 过程如下:1.在mysql目录下的data目录中,找到要导入表所在的数据库的名称,把frm文件放进去,比如我这里是offer.frm,数据库名称是netshop,放到数据库netshop目录下之后,在mysql中show tables显示如下在这里table是显示的,但是desc of

    2022年3月11日
    48
  • 【2010年就业考虑】- 阿朗,华为,中兴,大唐,爱立信,诺西,鼎桥,普天思科MOTO等…

    【2010年就业考虑】- 阿朗,华为,中兴,大唐,爱立信,诺西,鼎桥,普天思科MOTO等…

    2021年8月7日
    145
  • elasticsearch集群搭建对服务器硬件_elasticsearch集群搭建

    elasticsearch集群搭建对服务器硬件_elasticsearch集群搭建一、ElasticSearch集群1.1搭建集群Elasticsearch如果做集群的话Master节点至少三台服务器或者三个Master实例加入相同集群,三个Master节点最多只能故障一台Master节点,如果故障两个Master节点,Elasticsearch将无法组成集群.会报错,Kibana也无法启动,因为Kibana无法获取集群中的节点信息。由于,我们使用只有一台虚拟机,所以我们在虚拟机中安装三个ES实例,搭建伪集群,而ES启动比较耗内存,所以先设置虚拟机的内存3G和CPU个数4个

    2022年10月10日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号