如何在Android用FFmpeg+SDL20解码声音
如何在Android用FFmpeg+SDL2.0解码声音
一、创建一个VideoPicture结构体用来保存解码出来的图像;
如何在Android用FFmpeg+SDL20解码声音
如何在Android用FFmpeg+SDL20解码声音
如何在Android用FFmpeg+SDL20解码声音
二、添加数据队列的初始化、添加以及读取的函数;
三、audio_decode_frame():解码音频;
四、audio_callback(): 回调函数,向SDL缓冲区填充数据;
五、创建刷新相关的函数;
六、添加显示函数;
七、分配显示输出内存空间;
八、解码线程,将,建立音频线,保存重要信息到数据结构中;
九、编写Main函数用来调用解码线程。
知识点延伸:
FFmpeg是一个开源跨的和音频流方案,属于自由,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音的完整解决方案。它包含了非常先进的音频/编解码库libcodec,为了保证高可移植性和编解码质量,libcodec里很多codec都是从头开发的。FFmpeg在Linux下开发,但它同样也可以在其它作系统环境中编译运行。
SDL2.0(Simple DirectMedia Layer)是一套开放源代码的跨多媒体开发库,使用C语言写成。SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。SDL内置了调用OpenGL的函数。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个(Linux、Windows、Mac OS X等)的应用。
音视频编解码 原理
这个原理很复杂的。而且音频和视频的原理别很大,音视频不同标准之间的原理也有很多的别。不过基本上都是通过各种变换和模型来去除冗余,去除冗余的方法优劣决定了编码算法的好坏,不同的算法的计算复杂度也不同,很多音视频编解码都是压缩效果和当前条件实际可行性的某种折衷。
ffmpeg4,编码解码硬加速的实现
步骤基本上从网上抄袭就行。主要是3安装nv-codec-headers的版本,需要跟自己的驱动一致。我由于没有一致,安装cuda,安装其他的什么都没搞定,其中安装驱动还导致重装系统了,血的教训。
如何在Android用FFmpeg解码图像
这涉及到两个问题,一个是解码,另一个是显示,解码问题要先交叉编译ffmpeg,然后参考下面的解码流程
codec_register_all();
/
########################################
[1]
########################################
/
_register_all();
/
// Open video file
########################################
[2]
########################################
/
pFormatCtx = format_alloc_context();
if(format_open_input(&pFormatCtx, filename, NULL, NULL)!=0)
return -1; // Couldn't open file
// Retri stream rmation
/
########################################
[3]
########################################
/
if(format_find_stream_(pFormatCtx,NULL)<0)
return -1; // Couldn't find stream rmation
// Dump rmation about file onto standard error
// dump_format(pFormatCtx, 0, argv[1], 0);
// Find the first video stream
videoStream=-1;
for(i=0; i
nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}if(videoStream==-1)
return -1; // Didn't find a video stream
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
// Find the decoder for the video stream
pCodec=codec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL) {
fprintf(stderr, "Unsupported codec!n");
return -1; // Codec not found
}// Open codec
if(codec_open2(pCodecCtx, pCodec,NULL)<0)
pFrame=codec_alloc_frame();
// Allocate an picture structure
picture_alloc(&picture, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
// Determine required buffer size and allocate buffer
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
if(img_convert_ctx == NULL)
{fprintf(stderr, "Cannot initialize the conversion context!n");
exit(1);
}// Read frames and se first five frames to disk
/
########################################
[4]
########################################
/
i=0;
dirtyRegion.set(android::Rect(0x3FFF, 0x3FFF));
while(_read_frame(pFormatCtx, &packet)>=0) {
// Is this a packet from the video stream?
if(packet.stream_index==videoStream) {
// Decode video frame
codec_decode_video2(pCodecCtx, pFrame, &frameFinished,
&packet);
// Did we get a video frame?
if(frameFinished) {
// Convert the image from its native format to RGB
sws_scale(img_convert_ctx,
pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
picture.data, picture.linesize);
}}
// Free the packet that was allocated by _read_frame
_free_packet(&packet);
}pFrame为解码后的数据,将它显示在画布上,就完成了FFMEPG解码
Android视频播放器07-检测视频是否可以被硬解码
1、解码流程:
根据FFmpeg中视频的名称找到对应手机硬,如果存在则可以硬解码,
走硬解码流程;不存在就只能走软解码流程。
2、硬解码:
使用MediaCodec直接解码AVpacket,此时需要对AVPacket进行格式过滤,然后
MediaCodec解码后的数据用OpenGL ES渲染出来。
3、软解码:
直接用OpenGL ES 渲染YUV数据。
MediaCodecList.getCodecCount()支持的的SDK版本是16,buile.gradle中改 minSdkVersion 16
宏定义硬解码、软解码
iOS利用FFmpeg解码音频数据并播放
利用FFmepg解析并解码音频流数据,然后将解码后的音频数据送给Audio Queue以实现播放.
利用FFmpeg解析音频数据流, 利用FFmpeg解码音频数据为PCM格式. 利用Audio Queue Player实现音频数据播放.
本例以一个苹果原生相机录制的.MOV文件为例, 将该文件使用FFmpeg解析并解码,将解码后的数据放入传输队列中,然后开启audio queue player, 播放器在回调函数中轮循取出队列中的数据实现播放.
FFmpeg parse流程
FFmpeg解码流程
为了每次能够重新播放,这里需要标记当前是否为解码的帧数据,以重新启动播放器. 另一点是使用NSTimer等待音频数据放入队列再开始播放,因为audio queue是驱动播放模式,所以必须等音频数据放入传输队列再开始播放.
从Parse模块中可以获取当前文件对应FFmepg的上下文对象 AVFormatContext .因此音频流信息可以直接获取.
AVFrame 作为解码后原始的音视频数据的容器.AVFrame通常被分配一次然后多次重复(例如,单个AVFrame以保持从接收的帧)。在这种情况下,_frame_unref()将释放框架所持有的任何引用,并在再次重用之前将其重置为其原始的清理状态。
调用codec_send_packet将压缩数据发送给.后利用循环接收codec_receive_frame解码后的音视频数据.
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系 836084111@qq.com 删除。