Android音视频API - MediaCodec/MediaMuxer/MediaStore/MediaController等

AudioTrack播放音频PCM。[Android] 混音器AudioMixer。
MediaPlayer/MediaRecorder, AudioTrack/AudioRecorder, MediaCodec。

-- 使用MediaCodec和MediaMuxer的过程中遇到的问题,总结下需要注意主要有以下几点:
 1.MediaCodec是Android4.1新增API,MediaMuxer是Android4.3新增API。
 2.颜色空间。按照Android本身的意思,COLOR_FormatYUV420Planar应该是所有硬件平台都支持的。但是实际上并不是这样。所以在设置颜色空间时,应该获取硬件平台所支持的颜色空间,确保它是支持你打算使用的颜色空间,不支持的话应该启用备用方案(使用其他当前硬件支持的颜色空间)。
 3.视频尺寸,在一些手机上,视频录制的尺寸可以是任意的。但是有些手机,不支持的尺寸设置会导致录制的视频现错乱。博主在使用Oppo R7测试,360*640的视频,单独录制视频没问题,音视频混合后,出现了颜色错乱的情况,而在360F4手机上,却都是没问题的。将视频宽高都设置为16的倍数,可以解决这个问题。
 4.编码器格式设置,诸如音频编码的采样率、比特率等,取值也需要结合硬件平台来设置,否则也会导致崩溃或其他问题。这个其实和颜色空间的选择一样。
 5.网上看到许多queueInputBuffer中设置presentationTimeUs为System.nanoTime()/1000,这样做会导致编码出来的音视频,在播放时,总时长显示的是错误的。应该记录开始时候的nanoTime,然后设置presentationTimeUs为(System.nanoTime()-nanoTime)/1000。
 6.录制结束时,应该发送结束标志MediaCodec.BUFFER_FLAG_END_OF_STREAM,在编码后区获得这个标志时再终止循环,而不是直接终止循环。

-- 音视频API架构
 android-java层:camera相关(视频)、AudioRecord(音频)相关、MediaCodec相关(音视频编码)。

 android-native层(c++):h264、h265等编码库的调用;各种音频编码库的使用(aac、amr、mp3、g711等);容器封装技术(音视频封装ts、ps等);
媒体协议(hls、rtsp、rtmp等);socket编程;android-ndk编译so技术;jni技术等。

-- 音频通过G711u,视频通过H264。
  利用Android4.1增加的API MediaCodec和Android 4.3增加的API MediaMuxer进行Mp4视频的录制。
  冗余消除:时域冗余,空域冗余,统计冗余,视觉冗余。时域冗余就是时域上帧与帧之间的相关性。采用运动补偿就可以实现消除冗余。空域冗余就是空间上,比如我们描述蓝天,其实一片蓝天有很多相似的元素。这时候就提出了一种方法就叫做帧内预测。统计冗余可以理解为进行比如熵编码的时候,我们要是对每一个编码都进行等长编码的话,那么就有大量冗余,毕竟不同元素出现的概率不一样。所以呢就提出了哈夫曼编码,量化。视觉冗余呢就是针对人眼特性对视频进行适当处理。现在有一个很火的东西就是感兴趣编码(ROI)。

Video   Render: OpenGL ES,MediaCodec;
Audio   Render: OpenSL ES,Audio Track;
HardWare Codec: Media Codec 。

--  MediaExtractor用于音视频分路,和MediaMuxer正好是反过程。MediaFormat用于描写叙述多媒体数据的格式。MediaRecorder用于录像+压缩编码。生成编码好的文件如mp4, 3gpp,视频主要是用于录制Camera preview。MediaPlayer用于播放压缩编码后的音视频文件。
  AudioRecord用于录制PCM数据。AudioTrack用于播放PCM数据。PCM即原始音频採样数据。能够用如vlc播放器播放。

1. 在AndroidManifest.xml里加上录音权限,否则创建AudioRecord对象时铁定失败:
 <uses-permission android:name="android.permission.RECORD_AUDIO"/>
2. 音视频通过PTS同步,两个的单位要一致。
3. MediaMuxer的使用要依照Constructor -> addTrack -> start -> writeSampleData -> stop 的顺序。假设既有音频又有视频,在stop前两个都要writeSampleData()过。

-- 视频的分离合成我主要用到了MediaExtractor和MediaMuxer两个类: 
 MediaExtractor是用于提取多路的、通常编码的视频资源的,通过它我们可以选择音频或者视频轨,然后分别对它们进行操作等; 
 MediaMuxer是用于复用基本流的,用它可以将音频和视频合成,目前支持输出MP4,Webm和3GP格式的视频,在Android7.0以后支持多路复用帧的MP4。 
 MediaFormat封装了描述媒体数据格式的信息,如音频或视频,通过它我们可以取出音频或者视频。

音视频采集、美颜/滤镜/特效处理、编码、封包、推流、转码、分发、解码/渲染/播放等。

-- Android提供的MediaCodec及其相关类为我们提供了所需的方法,这些类主要包括:MediaCodec、MediaExtractor、MediaMuxer、MediaFormat。
 1.MediaCodec用于创建视音频编解码器,通过它可以对视音频数据进行编解码操作,它是编解码功能的核心类。
 2.MediaExtractor相当于一个reader,它用于读取媒体文件,并提取出其中的视音频数据。
 3.MediaMuxer相当于一个writer,它用于将内存中的视音频数据写到文件中。
 4.MediaFormat即媒体格式类,它用于描述媒体的格式参数,如视频帧率、音频采样率等。

-- Android5.0 MediaProjection可运用到小型会议PPT演示、手游直播等行业。使用摄像头采集视频数据,并通过MediaCodec进行H264编码,之后打包成RTSP格式并上传的。
  TextuewView也提供了一个setTransform方法,该方法接收一个matrix参数,使用该参数对当前的渲染内容进行转换.
Android MediaMuxer录像(支持G711音频)- https://blog.csdn.net/jyt0551/article/details/72787095
 Android平台的MediaMuxer是个非常好的录像库,它能将H.264视频+AAC音频存储成.mp4格式的文件,而且稳定性、同步效果都非常好。 Android MediaMuxer过程:创建对象、添加音视频轨道、开始、持续写入音视频数据、关闭这样一个过程。MediaMuxer并不支持对除AAC以外的音频编码格式的封装,然而在安防行业里G711音频格式的数据是大多数设备的默认编码格式。如何支持G711格式的数据呢?其实换种思路就会豁然开朗,我们可以先把G711数据解码成PCM,再用MediaCodec编码成AAC,这样曲线存储。不光是G711,所有的音频编码格式都可以这样做哈哈。。

  基于其更高的压缩比,H.265适用于安防行业再合适不过了!因为安防行业每天都有着海量的视频数据在产生,同时需要实时传输、分析、存储…在带宽和存储成本依然昂贵的今天,我们极度需要更低的码率!更低的码率就等同于更低的成本,因此今天各个安防厂商已经逐渐将视频设备由264转移到265了,这同时对于265编码也有着积极的推动作用.
  不是所有的安卓机都支持H.265的硬解码,对于这些不支持硬解码的,使用ffmpeg进行软解即可,这方面资料也不在少数。
  流媒体协议,RTSP协议,也包括hTTP\RTSP\RTMP\HLS\FILE等格式都支持.

-- AudioTrack,mediaplay
1、android提供的音视频编码只有 AMR-NB(nb是窄频)和H.263
2、android虽然支持gif的解码,只能用mediaplay来播放,但是效果不好
3、android不支持flv的解码
4、AudioTrack只能播放pcm编码的数据,MediaPlayer可以播放MP3,AAC,WAV,OGG,MIDI等
  事实上,两种本质上是没啥区别的,MediaPlayer在播放音频时,在framework层还是会创建AudioTrack,把解码后的PCM数据传递给AudioTrack,最后由AudioFlinger进行混音,传递音频给硬件播放出来。利用AudioTrack播放只是跳过 Mediaplayer的解码部分而已。Mediaplayer的解码核心部分是基于OpenCORE 来实现的,支持通用的音视频和图像格式,codec使用的是OpenMAX接口来进行扩展。因此使用audiotrack播放mp3文件的话,要自己加入 一个音频解码器,如libmad。否则只能播放PCM数据,如大多数WAV格式的音频文件。

-- MediaCodec 是 API 16 之后 Google 推出的用于音视频编解码的一套偏底层的 API,可以直接利用硬件加速进行视频的编解码。调用的时候需要先初始化 MediaCodec 作为视频的编码器,然后只需要不停传入原始的 YUV 数据进入编码器就可以直接输出编码好的 H.264 流,整个 API 设计模型同时包含了输入端和输出端的两条队列。
 一般来说,起码在 4.4+ 的系统上,这两种格式在大部分机器上都有支持:
  MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar;
  MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
 除了使用 MediaCodec 进行编码之外,另外一种比较流行的方案就是使用 FFmpeg + x264/OpenH264 进行软编码,FFmpeg 适用于一些视频帧的预处理。这里主要是使用 x264/OpenH264 作为视频的编码器。
  x264 基本上被认为是当今市面上最快的商用视频编码器,而且基本上所有 H264 的特性都支持,通过合理配置各种参数还是能够得到较好的压缩率和编码速度的。
  OpenH264 则是由思科开源的另外一个 H264 编码器,项目在 2013 年开源,对比起 x264 来说略显年轻,不过由于思科支付买了 H.264 的年度专利费,所以对于外部用户来说,相当于可以直接免费使用了。另外,firefox 直接内置了 OpenH264,作为其在 WebRTC 中的视频编解码器使用。
  https://chromium.googlesource.com/libyuv/libyuv/ Google 开源的一个 YUV 处理库,上面只针对 1080p->540p 视频帧缩放的算法,而对于通用的压缩处理,可以直接使用这里的实现,对比起 FFmpeg 的速度快上不少。

> MediaCodec编码解码视频H.264,学习 MediaCodec API,完成视频 H.264 的硬编、硬解
  在Android里,最常用的视频编码解码用的API就是mediacodec了,可以进行多种格式的硬解码,也能和mediamuxer一起使用实现音视频文件的编辑(结合MediaExtractor),用OpenGL绘制Surface并生成mp4文件,屏幕录像以及类似Camera app里的录像功能(虽然这个用MediaRecorder更合适)等
  MediaExtractor用于音视频分路,和MediaMuxer正好是反过程。MediaFormat用于描述多媒体数据的格式。MediaRecorder用于录像+压缩编码,生成编码好的文件如mp4, 3gpp,视频主要是用于录制Camera preview。MediaPlayer用于播放压缩编码后的音视频文件。AudioRecord用于录制PCM数据。AudioTrack用于播放PCM数据。PCM即原始音频采样数据,可以用如vlc播放器播放。

MediaCodec硬解码实现RTSP+H264实时视频播放完整功能可以参考:https://github.com/ldm520/ANDROID_MEDIACODEC_RTSP_H264
【Android 多媒体应用】使用MediaCodec将摄像头采集的视频编码为h264- https://www.cnblogs.com/CoderTian/p/6224605.html
android编码h264(二):MediaCodec 硬编码 h264(硬编码)- https://blog.csdn.net/ss182172633/article/details/50256733  https://github.com/sszhangpengfei/MediaCodecEncodeH264

  IDR帧:IDR帧属于I 帧。解码器收到IDR frame时,将所有的参考帧队列丢弃 ,这点是所有I 帧共有的特性,但是收到IDR帧时,解码器另外需要做的工作就是:把所有的PPS和SPS参数进行更新。由此可见,在编码器端,每发一个 IDR,就相应地发一个 PPS&SPS_nal_unit
  I帧:帧内编码帧是一种自带全部信息的独立帧,无需参考其它图像便可独立进行解码,视频序列中的第一个帧始终都是I帧。
  P帧:前向预测编码帧
  B帧:双向预测内插编码帧

> 如果是mp4parser支持的格式就好办,若不支持就用ffmpeg
使用Android原生的MediaExtractor和MediaMuxer可以实现音视频的合成。不过有几个缺点:

1.MediaMuxer是在4.3(API18)中新增的类,无法兼容低版本;

2.音频如果是MP3的话需要使用MediaCodec重新编码,因此建议直接使用m4a的音频文件,可以直接合成;

3.音视频长度不同时的处理措施。

-- 将H264转为MP4
 mp4parser- https://github.com/sannies/mp4parser/releases

> 视频分离和合成(MediaMuxer和MediaExtractor)

Android 视频分离和合成(MediaMuxer和MediaExtractor)-
https://github.com/RrtoyewxXu/AndroidLiveRecord/tree/master/mediaexactorandmediamuxerdemo
AndroidLiveRecord视频分离和合成,MediaExtractor和MediaMuxer的Demo- https://github.com/RrtoyewxXu/AndroidLiveRecord/tree/master/mediaexactorandmediamuxerdemo
  在Android的多媒体类中,MediaMuxer和MediaCodec算是比较年轻的,它们是JB 4.1和JB 4.3才引入的。前者用于将音频和视频进行混合生成多媒体文件。缺点是目前只能支持一个
audio track和一个video track,而且仅支持mp4输出。不过既然是新生事物,相信之后的版本应该会有大的改进。MediaCodec用于将音视频进行压缩编码,它有个比较牛X的地方是可
以对Surface内容进行编码,如KK 4.4中屏幕录像功能就是用它实现的。
  MediaExtractor用于音视频分路,和MediaMuxer正好是反过程。MediaFormat用于描述多媒体数据的格式。MediaRecorder用于录像+压缩编码,生成编码好的文件如mp4, 3gpp,视频
主要是用于录制Camera preview。MediaPlayer用于播放压缩编码后的音视频文件。AudioRecord用于录制PCM数据。AudioTrack用于播放PCM数据。PCM即原始音频采样数据,可以用如
vlc播放器播放。
  MediaExtractor类,可以用来分离容器中的视频track和音频track.

> MediaStore
-- MediaStore.ACTION的意图集合,拍照(图片),拍音视频
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg")));
              startActivityForResult(intent, PHOTOHRAPH);

-- 获取该图片的其他信息,比如ID等
String[] projection = {
            MediaStore.MediaColumns._ID,
            MediaStore.Images.ImageColumns.ORIENTATION,
            MediaStore.Images.Media.DATA
            };
Cursor c = getContentResolver().query(mPhotoUri, projection, null, null, null);
c.moveToFirst();

Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);  
intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraVideoURI);  
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, MAXIMUM_VIDEO_SIZE);               
startActivityForResult(intent, CAPTURE_VIDEO_INTENT);

String[] projection ={ MediaStore.Video.Media.DATA, MediaStore.Video.Media.SIZE }; 
Cursor cursor = managedQuery(cameraVideoURI, projection, null, null, null); 
int column_index_data =cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA); 
int column_index_size =cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE); 
cursor.moveToFirst(); 
String recordedVideoFilePath = cursor.getString(column_index_data);
int recordedVideoFileSize = cursor.getInt(column_index_size);

> VideoView与MediaController播放视频
通过VideoView+MediaController实现视频播放- https://blog.csdn.net/qq_34078119/article/details/56560571
VideoView+MediaController自定义seekbar和全屏切换功能
定制VideoView,自定义MediaController- https://blog.csdn.net/jason_xnxm/article/details/31398939

> MediaPlayer与MediaController播放视频(有Bug),这个需要MediaPlayer+seekBar来播放视频
Android中使用SurfaceView+MediaPlayer+自定义的MediaController实现自定义的视屏播放器- https://www.cnblogs.com/wjtaigwh/p/4960301.html
MediaPlayer MediaController- https://blog.csdn.net/guchuanhang/article/details/50754623

> MediaInfo
  MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码)。他除了提供DLL之外,本身也提供GUI工具用于查看视频信息。新版本的MediaInfo支持HEVC。MediaInfo中解码JPEG信息。

 -- 使用MediaInfo可以获得多媒体文件的哪些信息?
  内容信息:标题,作者,专辑名,音轨号,日期,总时间……
  视频:编码器,长宽比,帧频率,比特率……
  音频:编码器,采样率,声道数,语言,比特率……
  文本:语言和字幕
  段落:段落数,列表

 -- MediaInfo支持哪些文件格式?
  视频:MKV, OGM, AVI, DivX, WMV, QuickTime, Real, MPEG-1, MPEG-2, MPEG-4, DVD (VOB)...
  (编码器:DivX, XviD, MSMPEG4, ASP, H.264, AVC...)
  音频:OGG, MP3, WAV, RA, AC3, DTS, AAC, M4A, AU, AIFF...
  字幕:SRT, SSA, ASS, SAMI...

 -- MediaInfo的主要功能特点:
  支持众多视频和音频文件格式
  多种查看方式:文本,表格,树形图,网页……
  自定义查看方式
  信息导出:文本,CSV,HTML……
  三种发布版本:图形界面,命令行,DLL(动态链接库)
  与Windows资源管理器整合:拖放,右键菜单

国际化:有多种界面语言供选择.
MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码)。

  SDL库的作用是封装了复杂的视音频底层操作,简化了视音频处理的难度。SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

  3D视觉原理之深度暗示(即立体感)主要有两种:心理深度暗示和生理深度暗示。心理深度暗示主要由平时的经验积累获得。即使用单眼观看也会使人有3D效果。生理深度暗示包括单眼立体视觉暗示和双眼立体视觉暗示。 单眼立体视觉暗示包括有两种:焦点调节和单眼移动视差。双眼立体视觉暗示主要利用的是人的两眼在观察同一物体的时候成像的不同来获得物体的前后关系。由于左眼看到物体的左边多一点,右眼看到的物体右边多一点,因而形成了视觉上的差异,即双目视差(如图所示)。双目视差是获得深度信息的生理基础。当前的3D系统基本上采用的都是该原理进行成像。换句话说,就是分别让左眼和右眼在同一时间看到不同的图像。
  3D显示技术:分别让左眼和右眼在同一时间看到不同的图像。红蓝3D。偏振光3D。快门3D。

> 视频编解码
-- 压缩视频:FFmpeg 和 libx264,libx264 是一个开源的H.264编码器。视频压缩编码和音频压缩编码。
编码器(encoder):x264(视频编码) 和 aac(音频编码)
解码器:播放器

-- 最常见的MPEG4P2编码器有divx和xvid(开源),最常见的AVC编码器是x264(开源);
比较流行的几种适合网络传输的视频编码有:MPEG4、H263、H264;

  MediaExtractor:可用于分离视频文件的音轨和视频轨道,如果你只想要视频,那么用selectTrack方法选中视频轨道,然后用readSampleData读出数据,这样你就得到了一个没有声音的视频。此处我们传入的是一个音频文件(mp3),所以也就只有一个轨道,音频轨道。
Android用MediaRecorder实现MPEG4视频监控- http://tuojian-tj.iteye.com/blog/973995
文章【Android 的视频编码 H263 MP4V H264】的代码实现- http://blog.csdn.net/zblue78/article/details/6083374
直接传视频流,MPEG4或者H.264格式。视频的录制和压缩上传等;android目前解决视频的剪切和压缩的话好像就只能是用FFMEG。

> 视频压缩与分析
视频的采集,视频的编辑,视频的截图,视频的水印等
网络自适应动态视频解码技术,基于Android的视频流自适应算法设计,mpeg4压缩协议。
视频压缩编码和音频压缩编码的基本原理- http://blog.csdn.net/mabeijianxi/article/details/72933910
Android 视频压缩等- http://androidwarzone.blogspot.jp/2011/12/ffmpeg4android.html 
利用FFmpeg玩转Android视频录制与压缩(二)<转>- https://www.cnblogs.com/wainiwann/p/7222672.html

> 多媒体流的几个环节:采集,编码,推流,转码,分发,拉流,解码和渲染。
  
> 音视频的录制、播放、编码、上传、下载、观看等,视频编解码,音频编解码,线音频播放 音视频同步等,软硬编码解码
仿网易云音乐 安卓版-- https://github.com/aa112901/remusic
Android本地视频播放器开发- http://blog.csdn.net/jwzhangjie/article/category/953509
Android本地视频播放器开发--NDK编译FFmpeg- http://blog.csdn.net/jwzhangjie/article/details/9038111
视频播放Demo -http://blog.csdn.net/itachi85/article/details/7216962 ,http://blog.csdn.net/x605940745/article/details/18302111

> 视频实时上传
  现在有个场景是录制视频是一直在录的,有个拍照的功能,怎么取到实时预览的那一帧呢?Camera有previewlistener,设置监听器,在onFrame中可以接受到每一帧的数据。
Android 实时视频采集/编码/传输/解码/播放—方案调研-http://blog.csdn.net/sinat_35845281/article/details/52794344
android 在线视频边下边播-http://download.csdn.net/download/lin415005334/8855367
android 视频播放(一)利用android原生的videoview- http://blog.csdn.net/shenxiaolei507/article/details/41046345
android视频播放(二) 利用android原生的MediaPlayer+SurfaceView- http://blog.csdn.net/shenxiaolei507/article/details/41349295
Android使用SurfaceView播放视频时横竖屏的调整 - http://blog.chinaunix.net/uid-20771867-id-4171565.h
屏的调整 -https://github.com/Chaoba/BlueVideoPlayer
支持横竖屏切换的视频播放器demo(IOS)- http://download.csdn.net/download/yqxh_wang/8950747
android_横竖屏切换demo- http://download.csdn.net/download/agan75/6033923
android 视频播放 点击横竖屏切换 自动旋转横竖屏切换 冲突- http://download.csdn.net/download/liubo080852/8446445
Android网页播放视频(含横竖屏切换)DEMO(实测有效)- http://download.csdn.net/detail/nuobabijie730/9780160
Android实现实时视频通话- http://blog.csdn.net/wintersweetforever/article/details/78478939
Android实现实时视频通话- https://github.com/LinHuanTanLy/JustTalkMaster
通过 H264编解码,rtp协议传输 实现内网之间点对点实时视频通信- https://github.com/592713711/Android-VideoChat

  Android实现视频播放的话,有2中方式,第一种是MediaPlayer+surfaceView实现,第二种是直接用VideoView来实现,当然市面上也有一些主流的视频能播放的框架,像Vitamio,ExoPlayer等。
Android三种播放视频的方式- http://blog.csdn.net/itachi85/article/details/7216962
Android 利用发送Intent播放本地视频和网络视频- http://blog.csdn.net/dj0379/article/details/50915770

> 短视频,,视频的采集,视频的编辑,视频的截图,视频的水印等
利用FFmpeg视频录制微信小视频与其压缩处理- https://github.com/mabeijianxi/small-video-record
“抖音”式的酷炫短视频开发进阶- http://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/79124926
基于VCamera,仿微信录制短视频- https://github.com/maimingliang/WxRecoderVideo
Android仿微信朋友圈10s视频编辑- http://blog.csdn.net/qq_28284547/article/details/78295362

> 实时视频通话 ;实时视频聊天 ;实时音视频聊天
1.android使用socket实现实时视频?
2.用MediaRecorder对yuv420进行H264硬编码后发送?
3.调用本地H264编码库(JNI)对一帧YUV420数据编码后发送?
4.对SIP协议、H.264视频编解码、RTC/RTCP网络传输等关键技术进行研究?

> 音视频边下边播
不管是Google的 ExoPlayer、B站的 ijkplayer
mediaplayer便实现了边下边播的功能- https://github.com/Clearlee/PlayWhileDownloadMusic
通常实现流媒体的方法大致有三种:
 一,讲音视频文件拆分成若干多个小文件,在播放时,逐个下载,然后播放。也叫伪流媒体。
 二,将视频通过转换软件,在服务器端转换成流媒体格式文件,然后客户端进行播放。
 三,在本地录制视频的过程中,直接编解码为流媒体格式文件。

-- 用MediaMuxer与AudioRecord与MediaCodec及Surface进行屏幕录制成gif。
MediaProjection实现手机截屏(无须root),可以通过MediaProjection+VirturalDisplay+MediaProjectionManager来实现截屏。
一个音视频文件是由音频和视频组成的;我们可以通过MediaExtractor、MediaMuxer把音频或视频给单独抽取出来;抽取出来的音频和视频能单独播放;音轨
Android获取视频音频的时长的方法- http://blog.csdn.net/cwg19910909/article/details/50482807
实现把一个音频文件的视频抽取出来- http://blog.csdn.net/zhang_jun_ling/article/details/52770532
Java JAVE处理视频 、音频文件(读取视频时长等) - http://blog.csdn.net/jerome_s/article/details/54348124
利用Android SDK提供的MediaExtractor和MediaMuxer类来完成mp4文件的提取和生成 https://github.com/Jhuster/Android/tree/master/MediaDemo

发布了148 篇原创文章 · 获赞 179 · 访问量 155万+
展开阅读全文

android上使用mp4v2合成h264+aac,写入音频数据后打不开视频文件

11-04

我在android上写了一个视频录制程序,录制时把视频、音频数据放在两个队列里,并开启两个线程去读取数据,写到sd卡中。现在的问题是,如果只写入h264,则视频播放正常(使用videoView,虽然没有声音);但如果同时写入了音频数据,则打不开视频文件。请问可能是什么原因才会造成这种结果呢? 打包h264+aac的代码如下: ``` //写视频数据 BOOL WriteVideoData(RECORD_PARAM *struRecordParam, char* pVideoData, int nSize, int iFrameRate, int iType, long lTimestemp){ BOOL bResult = FALSE; if(struRecordParam==NULL || struRecordParam->mp4FileHandle<=0 || struRecordParam->isOpen==FALSE) return FALSE; if (nSize==0) {//写空帧 if (!MP4WriteSample(struRecordParam->mp4FileHandle, struRecordParam->videoId, (const uint8_t*)pVideoData, nSize, lTimestemp, 0, true)) { return FALSE; } return TRUE; } if ((pVideoData[4]&0x1f) == 7) { NSLOGE("writeVideoFrame: if 7"); if (struRecordParam->hasSPS) { return FALSE; } NSLOGE("to MP4AddH264VideoTrack "); struRecordParam->videoId = MP4AddH264VideoTrack(struRecordParam->mp4FileHandle, struRecordParam->nVideoTimeScale, (struRecordParam->nVideoTimeScale/struRecordParam->nVideoFrameRate), struRecordParam->nVideoWidth, struRecordParam->nVideoHeight, pVideoData[5], pVideoData[6], pVideoData[7], 3); if (struRecordParam->videoId == MP4_INVALID_TRACK_ID) { return FALSE; } MP4SetVideoProfileLevel(struRecordParam->mp4FileHandle, 0x7F); MP4AddH264SequenceParameterSet(struRecordParam->mp4FileHandle, struRecordParam->videoId, (const uint8_t*)(pVideoData+4), nSize-4); struRecordParam->hasSPS = TRUE; NSLOGE("MP4AddH264VideoTrack ok"); } else if ((pVideoData[4]&0x1f) == 8) { NSLOGE("writeVideoFrame: if 8"); if (struRecordParam->hasPPS) { return FALSE; } MP4AddH264PictureParameterSet(struRecordParam->mp4FileHandle, struRecordParam->videoId, (const uint8_t*)(pVideoData+4), nSize-4); struRecordParam->hasPPS = TRUE; } else { NSLOGE("writeVideoFrame: if else"); pVideoData[0] = (nSize-4) >> 24; pVideoData[1] = (nSize-4) >> 16; pVideoData[2] = (nSize-4) >> 8; pVideoData[3] = (nSize-4) & 0xff; if (!MP4WriteSample(struRecordParam->mp4FileHandle, struRecordParam->videoId, (const uint8_t*)(pVideoData), nSize, MP4_INVALID_DURATION, 0, true)) { return FALSE; } } return TRUE; } //写音频数据 BOOL WriteAudioData(RECORD_PARAM *struRecordParam, char* pAudioData, int nSize, long lTimestemp){ if(struRecordParam==NULL || struRecordParam->mp4FileHandle<=0 || struRecordParam->isOpen==FALSE) return FALSE; BOOL bResult = FALSE; if (struRecordParam->audioId == MP4_INVALID_TRACK_ID) { //添加aac音频 NSLOGE("MP4AddAudioTrack"); struRecordParam->audioId = MP4AddAudioTrack(struRecordParam->mp4FileHandle, 48000, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE); if (struRecordParam->audioId == MP4_INVALID_TRACK_ID) { return bResult; } NSLOGE("MP4SetAudioProfileLevel"); MP4SetAudioProfileLevel(struRecordParam->mp4FileHandle, 0x2); NSLOGE("MP4SetTrackESConfiguration"); MP4SetTrackESConfiguration(struRecordParam->mp4FileHandle, struRecordParam->audioId, pAudioData, nSize); } if (struRecordParam->audioId != MP4_INVALID_TRACK_ID) { if (!MP4WriteSample(struRecordParam->mp4FileHandle, struRecordParam->audioId,(const uint8_t*)(pAudioData+7), nSize-7, lTimestemp, 0, true)) { NSLOGE("MP4WriteSample audio failed"); return FALSE; } NSLOGE("MP4WriteSample audio failed"); } bResult = TRUE; return bResult; } ``` 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览