android mediacodec编码h264 怎样调节gop

android mediacodec编码h264 怎样调节gop,第1张

android mediacodec编码h264 怎样调节gop

简单地说。软解码是用软件方式进行解码,需要占用CPU资源,速度相当较慢。硬解码直接用硬件方式解决,不占用CPU资源,速度相对较快。

mov编码h264跟mp4编码h264的区别?

mov和mp4是两种不同的封装格式,里面的h.264都是一样的

H264编码 H264编码器 哪个牌子好

单位用的是视盈,几年来一直很稳定。推荐你联系视盈黄国耀。一三七,一一一四,六六九一。

MediaCodec编码可以获取到H264帧类型吗?

仅转换可以使用命令,把任一mp4转换成ts

ffmpeg -i input.mp4 -c copy -bsf h264_mp4toannexb output.ts 很高兴为您解答!

有不明白的可以追问!如果您认可我的回答。

如何实时h264编码及aac编码

1. 简单介绍

首先是捕获,这里采用了DirectShow的方式,对它进行了一定程度的封装,包括音视频。好处是直接使用native api,你可以做想做的任何修改,坏处是,不能跨平台,采集音视频这种应用,linux平台也是需要滴呀。有跨平台的做法,对视频,可以使用OpenCV,对音频,可以使用OpenAL或PortAudio等,这样就行了。

编码可以选择的余地比较大,对视频来讲,有H264, MPEG-4, WebM/VP8, Theora等,音频有Speex, AAC, Ogg/Vorbis等,它们都有相应的开源项目方案,我采用的是x264进行H264编码,libfaac进行aac编码,之后是否更改编码方案,等具体项目需求再说了。这里提一下WebM,Google牵头的项目,完全开放和自由,使用VP8和Vorbis编码,webm(mkv)封装,有多家巨头支持,目的是想要取代当前的H264视频编码,号称比后者更加优秀,我没有测试过实际效果。不过有商业公司牵头就是不一样,各项支持都很全面,有时间了关注一下。

2. 逻辑和流程

基本的思想是实现dshow ISampleGrabberCB接口,通过回调来保存每一个buffer。除了界面线程和dshow自己的线程之外,我们启动了两个线程,AudioEncoderThread和VideoEncoderThread,分别从SampleGrabber中取出数据,调用编码器进行编码,编码后的文件可以直接输出。看图:

程序是用VS2010构建的,看张工程截图:

Base下面的是对系统API的一些简单封装,主要是线程和锁。我这里简单也封装的了一下dshow的捕获过程,包括graph builder的创建,filter的连接等。directshow是出了名的难用,没办法,难用也得用。因为是VS2010,调用的Windows SDK 7.1中的dshow,没有qedit.h这个文件,而它正式定义ISampleGrabberCB的。不急,系统中还是有qedit.dll的,我们要做的就是从Windows SDK 6.0中,把它拷过来,然后在stdafx.h中加入这几行代码,就可以了

1 #pragma include_alias( "dxtrans.h", "qedit.h" )

2 #define __IDxtCompositor_INTERFACE_DEFINED__

3 #define __IDxtAlphaSetter_INTERFACE_DEFINED__

4 #define __IDxtJpeg_INTERFACE_DEFINED__

5 #define __IDxtKey_INTERFACE_DEFINED__

6 #include "qedit.h"

3. 音视频编码

相关文件:

Encoder下就是音视频编码相关的代码。X264Encoder封装了调用x264编码器的 *** 作,FAACEncoder封装了调用libfaac编码器的 *** 作,VideoEncoderThread和AudioEncoderThread负责主要的流程。下面我把关键代码贴出来,大家可以参考一下。

A. 视频编码线程

主要流程是首先初始化x264编码器,然后开始循环调用DSVideoGraph,从SampleGrabber中取出视频帧,调用x264进行编码,流程比较简单,调用的频率就是你想要获取的视频帧率。要注意的一点是,x264进行编码比较耗时,在计算线程Sleep时间时,要把这个过程消耗的时间算上,以免采集的视频帧率错误。

B. 音频编码线程

主要流程和视频编码线程相同,也是初始化FAAC编码器,然后循环调用DSAudioGraph,从SampleGrabber中取出视频帧,调用faac进行编码。和视频不同的是,音频的sample的频率是非常快的,所以几乎要不断的进行采集,但前提是SampleGrabber中捕获到新数据了才行,不然你的程序cpu就100%了,下面代码中IsBufferAvailaber()就是做这个检测的。

调用faac进行编码的时候,有点需要注意,大家特别注意下,不然编码出来的音频会很不正常,搞不好的话会很头疼的。先看下faac.h的相关接口

1 faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, unsigned int numChannels,2 unsigned long *inputSamples, unsigned long *maxOutputBytes)3 4 int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput,5 unsigned char *outputBuffer, unsigned int bufferSize)

faacEncEncode第三个参数指的是传入的sample的个数,这个值要和调用faacEncOpen返回的inputSamples相等。要做到这点,就要在dshow中设置好buffsize,公式是:

BufferSize = aac_frame_len * channels * wBytesPerSample aac_frame_len = 1024

如何让opencv支持h264编码

h.264是一种视频压缩标准了,有专门的库对它进行压缩解压的。

我对opencv还算是比较熟悉的,它没有h264之类的库

H264编码DVD能直接播放吗?

不能啊,不同格式的,H264跟DVD不一样啊

Adobe Pr的h264是啥编码器

音频编辑器

1、运行Set-up.exe,会d出“遇到了以下问题”d窗,选择忽略;

2、之后会初始化安装程序,请不要进行任何 *** 作,稍等片刻;

3、有安装和试用两种选择,请点击试用

4、安装需要Adobe ID登录验证,没有的话选择"获取Adobe ID"注册一个,只需有邮箱和密码即可(您也可以选择断开网络连接,选择“以后再登录”),同样也能继续安装;这里为您演示登陆安装。

5、接受协议后,选择安装的语言和安装的目录。

6、之后只需耐心等待,软件需要组件已自带,无需另外安装,这样就等安装完Adobe Premiere Pro CC 2015。

7、安装完毕点击立即启动,启动后不是进入软件而是试用版界面,点击开始试用;

8、打开Premiere Pro CC 2015,选择新建项目才算是进入软件。

PS:若是不事先进入一次软件直接破解会导致软件无法打开。

Premiere Pro CC 2015::3322./soft/201507311409.

mediacodec取不出h264解码后数据吗

需要调用av_parser_parse

进行帧查找分解后再送入解码器解码。

H264与MPEG中I,P,B帧编码一样吗

编码是不一样的,H.264采用的帧内编码和帧间预测编码技术 比MPEG-2的都要先进,因此压缩效率更高

//第一步:注册组件->编码器、解码器等等…

    av_register_all()

    //第二步:初始化封装格式上下文->视频编码->处理为视频压缩数据格式

    AVFormatContext *avformat_context = avformat_alloc_context()

    //注意事项:FFmepg程序推测输出文件类型->视频压缩数据格式类型

    const char *coutFilePath = [outFilePath UTF8String]

    //得到视频压缩数据格式类型(h264、h265、mpeg2等等...)

    AVOutputFormat *avoutput_format = av_guess_format(NULL, coutFilePath, NULL)

    //指定类型

    avformat_context->oformat = avoutput_format

    //第三步:打开输出文件

    //参数一:输出流

    //参数二:输出文件

    //参数三:权限->输出到文件中

    if (avio_open(&avformat_context->pb, coutFilePath, AVIO_FLAG_WRITE) <0) {

        NSLog(@"打开输出文件失败")

        return

    }

    //第四步:创建输出码流->创建了一块内存空间->并不知道他是什么类型流->希望他是视频流

    AVStream *av_video_stream = avformat_new_stream(avformat_context, NULL)

    //第五步:查找视频编码器

    //1、获取编码器上下文

    AVCodecContext *avcodec_context = av_video_stream->codec

    //2、设置编解码器上下文参数->必需设置->不可少

    //目标:设置为是一个视频编码器上下文->指定的是视频编码器

    //上下文种类:视频解码器、视频编码器、音频解码器、音频编码器

    //2.1 设置视频编码器ID

    avcodec_context->codec_id = avoutput_format->video_codec

    //2.2 设置编码器类型->视频编码器

    //视频编码器->AVMEDIA_TYPE_VIDEO

    //音频编码器->AVMEDIA_TYPE_AUDIO

    avcodec_context->codec_type = AVMEDIA_TYPE_VIDEO

    //2.3 设置读取像素数据格式->编码的是像素数据格式->视频像素数据格式->YUV420P(YUV422P、YUV444P等等...)

    //注意:这个类型是根据你解码的时候指定的解码的视频像素数据格式类型

    avcodec_context->pix_fmt = AV_PIX_FMT_YUV420P

    //2.4 设置视频宽高->视频尺寸

    avcodec_context->width = 640

    avcodec_context->height = 352

    //2.5 设置帧率->表示每秒25帧

    //视频信息->帧率 : 25.000 fps

    //f表示:帧数

    //ps表示:时间(单位:每秒)

    avcodec_context->time_base.num = 1

    avcodec_context->time_base.den = 25

    //2.6 设置码率

    //2.6.1 什么是码率?

    //含义:每秒传送的比特(bit)数单位为 bps(Bit Per Second),比特率越高,传送数据速度越快。

    //单位:bps,"b"表示数据量,"ps"表示每秒

    //目的:视频处理->视频码率

    //2.6.2 什么是视频码率?

    //含义:视频码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒

    //视频码率计算如下?

    //基本的算法是:【码率】(kbps)=【视频大小 - 音频大小】(bit位) /【时间】(秒)

    //例如:Test.mov时间 = 24,文件大小(视频+音频) = 1.73MB

    //视频大小 = 1.34MB(文件占比:77%) = 1.34MB * 1024 * 1024 * 8 = 字节大小 = 468365字节 = 468Kbps

    //音频大小 = 376KB(文件占比:21%)

    //计算出来值->码率 : 468Kbps->表示1000,b表示位(bit->位)

    //总结:码率越大,视频越大

    avcodec_context->bit_rate = 468000

    //2.7 设置GOP->影响到视频质量问题->画面组->一组连续画面

    //MPEG格式画面类型:3种类型->分为->I帧、P帧、B帧

    //I帧->内部编码帧->原始帧(原始视频数据)

    //    完整画面->关键帧(必需的有,如果没有I,那么你无法进行编码,解码)

    //    视频第1帧->视频序列中的第一个帧始终都是I帧,因为它是关键帧

    //P帧->向前预测帧->预测前面的一帧类型,处理数据(前面->I帧、B帧)

    //    P帧数据->根据前面的一帧数据->进行处理->得到了P帧

    //B帧->前后预测帧(双向预测帧)->前面一帧和后面一帧

    //    B帧压缩率高,但是对解码性能要求较高。

    //总结:I只需要考虑自己 = 1帧,P帧考虑自己+前面一帧 = 2帧,B帧考虑自己+前后帧 = 3帧

    //    说白了->P帧和B帧是对I帧压缩

    //每250帧,插入1个I帧,I帧越少,视频越小->默认值->视频不一样

    avcodec_context->gop_size = 250

    //2.8 设置量化参数->数学算法(高级算法)->不讲解了

    //总结:量化系数越小,视频越是清晰

    //一般情况下都是默认值,最小量化系数默认值是10,最大量化系数默认值是51

    avcodec_context->qmin = 10

    avcodec_context->qmax = 51

    //2.9 设置b帧最大值->设置不需要B帧

    avcodec_context->max_b_frames = 0

    //第二点:查找编码器->h264

    //找不到编码器->h264

    //重要原因是因为:编译库没有依赖x264库(默认情况下FFmpeg没有编译进行h264库)

    //第一步:编译h264库

    AVCodec *avcodec = avcodec_find_encoder(avcodec_context->codec_id)

    if (avcodec == NULL) {

        NSLog(@"找不到编码器")

        return

    }

    NSLog(@"编码器名称为:%s", avcodec->name)

    //第六步:打开h264编码器

    //缺少优化步骤?

    //编码延时问题

    //编码选项->编码设置

    AVDictionary *param = 0

    if (avcodec_context->codec_id == AV_CODEC_ID_H264) {

        //需要查看x264源码->x264.c文件

        //第一个值:预备参数

        //key: preset

        //value: slow->慢

        //value: superfast->超快

        av_dict_set(¶m, "preset", "slow", 0)

        //第二个值:调优

        //key: tune->调优

        //value: zerolatency->零延迟

        av_dict_set(¶m, "tune", "zerolatency", 0)

    }

    if (avcodec_open2(avcodec_context, avcodec, ¶m) <0) {

        NSLog(@"打开编码器失败")

        return

    }

    //第七步:写入文件头信息

    avformat_write_header(avformat_context, NULL)

    //第8步:循环编码yuv文件->视频像素数据(yuv格式)->编码->视频压缩数据(h264格式)

    //8.1 定义一个缓冲区

    //作用:缓存一帧视频像素数据

    //8.1.1 获取缓冲区大小

    int buffer_size = av_image_get_buffer_size(avcodec_context->pix_fmt,

                                               avcodec_context->width,

                                               avcodec_context->height,

                                               1)

    //8.1.2 创建一个缓冲区

    int y_size = avcodec_context->width * avcodec_context->height

    uint8_t *out_buffer = (uint8_t *) av_malloc(buffer_size)

    //8.1.3 打开输入文件

    const char *cinFilePath = [inFilePath UTF8String]

    FILE *in_file = fopen(cinFilePath, "rb")

    if (in_file == NULL) {

        NSLog(@"文件不存在")

        return

    }

    //8.2.1 开辟一块内存空间->av_frame_alloc

    //开辟了一块内存空间

    AVFrame *av_frame = av_frame_alloc()

    //8.2.2 设置缓冲区和AVFrame类型保持一直->填充数据

    av_image_fill_arrays(av_frame->data,

                         av_frame->linesize,

                         out_buffer,

                         avcodec_context->pix_fmt,

                         avcodec_context->width,

                         avcodec_context->height,

                         1)

    int i = 0

    //9.2 接收一帧视频像素数据->编码为->视频压缩数据格式

    AVPacket *av_packet = (AVPacket *) av_malloc(buffer_size)

    int result = 0

    int current_frame_index = 1

    while (true) {

        //8.1 从yuv文件里面读取缓冲区

        //读取大小:y_size * 3 / 2

        if (fread(out_buffer, 1, y_size * 3 / 2, in_file) <= 0) {

            NSLog(@"读取完毕...")

            break

        }else if (feof(in_file)) {

            break

        }

        //8.2 将缓冲区数据->转成AVFrame类型

        //给AVFrame填充数据

        //8.2.3 void * restrict->->转成->AVFrame->ffmpeg数据类型

        //Y值

        av_frame->data[0] = out_buffer

        //U值

        av_frame->data[1] = out_buffer + y_size

        //V值

        av_frame->data[2] = out_buffer + y_size * 5 / 4

        av_frame->pts = i

        //注意时间戳

        i++

        //总结:这样一来我们的AVFrame就有数据了

        //第9步:视频编码处理

        //9.1 发送一帧视频像素数据

        avcodec_send_frame(avcodec_context, av_frame)

        //9.2 接收一帧视频像素数据->编码为->视频压缩数据格式

        result =avcodec_receive_packet(avcodec_context, av_packet)

        //9.3 判定是否编码成功

        if (result == 0) {

            //编码成功

            //第10步:将视频压缩数据->写入到输出文件中->outFilePath

            av_packet->stream_index = av_video_stream->index

            result =av_write_frame(avformat_context, av_packet)

            NSLog(@"当前是第%d帧", current_frame_index)

            current_frame_index++

            //是否输出成功

            if (result <0) {

                NSLog(@"输出一帧数据失败")

                return

            }

        }

    }

    //第11步:写入剩余帧数据->可能没有

    flush_encoder(avformat_context, 0)

    //第12步:写入文件尾部信息

    av_write_trailer(avformat_context)

    //第13步:释放内存

    avcodec_close(avcodec_context)

    av_free(av_frame)

    av_free(out_buffer)

    av_packet_free(&av_packet)

    avio_close(avformat_context->pb)

    avformat_free_context(avformat_context)

    fclose(in_file)

在你的转码命令里面添加上-vf rotate=PI/2或者-vf rotate=3*PI/2,例如

ffmpeg -i E:\ffmpeg\test.mp4 -y -vf rotate=PI/2 E:\ffmpeg\dest1.mp4


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/11252642.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存