开源音视频播放器
非音视频相关知识点
音视频相关知识点
<br>
getLatency得到的ms值,就是AudioTrack.write写入的byte总量对应的'播放时长',和人耳实际听到的'当前播放时间'的差值.
```
public static int getLatencyByReflect() {
//set default:80ms
int latencys = 80
if(mAudioTrack != null ) {
try {
Class<?> classAudioTrack = mAudioTrack.getClass()
Method getLatencyMethod = classAudioTrack.getDeclaredMethod("getLatency")
getLatencyMethod.setAccessible(true)
latencys = (int) getLatencyMethod.invoke(mAudioTrack)
latencys = Math.max(latencys, 80)
} catch (Exception ex) {
ex.printStackTrace()
}
}
return latencys
}
```

```
String title = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.TITLE));
String singer = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String album = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM));
long size = cursor.getLong(cursor
.getColumnIndex(MediaStore.Audio.Media.SIZE));
int duration = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.DURATION));
String url = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA));
String _display_name = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
```

8. AnliaLee
- [Android 媒体播放框架MediaSession分析与实践](https://juejin.cn/post/6844903575814930439)
- [Android 解读开源项目UniversalMusicPlayer(播放控制层)](https://juejin.cn/post/6844903583557615629)
- [Android 解读开源项目UniversalMusicPlayer(数据管理)](https://juejin.cn/post/6844903586392981518)
- [UniversalMusicPlayer](https://github.com/android/uamp)
9. 多声道/立体声
- [Android立体声pcm的数据结构,左右声道拆分、左右声道反转](https://blog.csdn.net/hi_ugly/article/details/80977850)
- [Android 分离PCM中每个Channel的数据](https://blog.csdn.net/zchy198799/article/details/98882894)
- [使用Java分离音频左右声道](https://www.jianshu.com/p/cc9e0ee2661d)
- [视音频数据处理入门:PCM音频采样数据处理](https://blog.csdn.net/leixiaohua1020/article/details/50534316)
10. AudioTrack创建失败
public @NonNull AudioTrack build() throws UnsupportedOperationException {
if (mAttributes == null) {
mAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.build();
}
switch (mPerformanceMode) {
case PERFORMANCE_MODE_LOW_LATENCY:
mAttributes = new AudioAttributes.Builder(mAttributes)
.replaceFlags((mAttributes.getAllFlags()
| AudioAttributes.FLAG_LOW_LATENCY)
& ~AudioAttributes.FLAG_DEEP_BUFFER)
.build();
break;
case PERFORMANCE_MODE_NONE:
if (!shouldEnablePowerSaving(mAttributes, mFormat, mBufferSizeInBytes, mMode)) {
break;
}
case PERFORMANCE_MODE_POWER_SAVING:
mAttributes = new AudioAttributes.Builder(mAttributes)
.replaceFlags((mAttributes.getAllFlags()
| AudioAttributes.FLAG_DEEP_BUFFER)
& ~AudioAttributes.FLAG_LOW_LATENCY)
.build();
break;
}
if (mFormat == null) {
mFormat = new AudioFormat.Builder()
.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
.setEncoding(AudioFormat.ENCODING_DEFAULT)
.build();
}
if (mOffload) {
if (mPerformanceMode == PERFORMANCE_MODE_LOW_LATENCY) {
throw new UnsupportedOperationException(
"Offload and low latency modes are incompatible");
}
if (!AudioSystem.isOffloadSupported(mFormat, mAttributes)) {
throw new UnsupportedOperationException(
"Cannot create AudioTrack, offload format / attributes not supported");
}
}
try {
if (mMode == MODE_STREAM && mBufferSizeInBytes == 0) {
mBufferSizeInBytes = mFormat.getChannelCount()
* mFormat.getBytesPerSample(mFormat.getEncoding());
}
final AudioTrack track = new AudioTrack(
mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload,
mEncapsulationMode, mTunerConfiguration);
if (track.getState() == STATE_UNINITIALIZED) {
throw new UnsupportedOperationException("Cannot create AudioTrack");
}
return track;
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException(e.getMessage());
}
}
}
- 其中一种创建失败,抛出异常: throw new UnsupportedOperationException("Cannot create AudioTrack");