android: низкоуровневые мультимедиа api и их применение в...
TRANSCRIPT
Android: низкоуровневые мультимедиа API
И их применение в реальной жизни
Григорий Клюшников Android-разработчик ВКонтакте vk.com/grishka Telegram: @grishka
Как это работает: медиаплеер(простой случай: локальный аудиофайл)
Файл Парсер Кодек
Как это работает: медиаплеер(случай сложнее: локальное видео)
Файл Парсер
Кодек
Кодек
Как это работает: медиаплеер(потоковое видео)
Буфер Парсер
Кодек
Кодек
android.media.MediaPlayer
MediaPlayer player = new MediaPlayer(); player.setDataSource("http://example.com/song.mp3"); player.prepare(); // blocking player.start(); // Не забудьте освободить ресурсы!
Суровая реальность: кэш
Буфер Парсер Кодек
Суровая реальность: кэш
Буфер Парсер Кодек
Суровая реальность: кэш
Буфер Парсер Кодек
Суровая реальность: кэш
Буфер Парсер Кодек
Суровая реальность: кэш
Буфер Парсер Кодек
HTTP-прокси
Суровая реальность: кэш
Буфер Парсер Кодек
HTTP-прокси Файл
Суровая реальность: кэш
https://psv4.vk.me/c422431/u67616085/audios/37c79c8bdcd…
http://127.0.0.1:5483/?https%3A%2F%2Fpsv4.vk.me%2Fc4224…
Суровая реальность: сеть
LTE
Суровая реальность: сеть
LTE
Суровая реальность: сеть
LTE
Суровая реальность: сеть
3G
Суровая реальность: сеть
E
Суровая реальность: сеть
E
Суровая реальность: сеть
E
Суровая реальность: сеть
Суровая реальность: сеть
При воспроизведении произошла ошибка
Суровая реальность: сеть
LTE
ExoPlayer
ExoPlayer
ExoPlayer
MediaPlayer
Логика плеера
Сеть Буферизация Разделение Распаковка Вывод
ExoPlayer
MediaExtractor
Сеть Буферизация Разделение Распаковка Вывод
Логика плеера
MediaCodec AudioTrack
Плеер уровня приложения
ExoPlayer
ExoPlayer
E
ExoPlayer
E
DIY
Своя реализация
Сеть Буферизация Разделение
Распаковка Вывод
Логика плеера
MediaCodec AudioTrack
Плеер уровня приложения
Буферизация и кэширование одновременно: почему бы и нет?
1708231_352255247.part
Буферизация и кэширование одновременно: почему бы и нет?
1708231_352255247.part
ID3
Буферизация и кэширование одновременно: почему бы и нет?
1708231_352255247.part
ID3
Буферизация и кэширование одновременно: почему бы и нет?
1708231_352255247.part
ID3 Сжатые данные (в виде фреймов)
Буферизация и кэширование одновременно: почему бы и нет?
Буферизация и кэширование одновременно: почему бы и нет?• OkHttp
Буферизация и кэширование одновременно: почему бы и нет?• OkHttp
• Докачка
Буферизация и кэширование одновременно: почему бы и нет?• OkHttp
• Докачка
• Предсказуемая буферизация
Буферизация и кэширование одновременно: почему бы и нет?• OkHttp
• Докачка
• Предсказуемая буферизация
• Переполучение ссылок при смене IP
Буферизация и кэширование одновременно: почему бы и нет?• OkHttp
• Докачка
• Предсказуемая буферизация
• Переполучение ссылок при смене IP
• Отлично работает в метро (я проверял)
MediaCodec codec = MediaCodec.createDecoderByType("audio/mpeg"); MediaFormat format = MediaFormat.createAudioFormat("audio/mpeg", sampleRate, isMono ? 1 : 2); MediaCodec.BufferInfo info=new MediaCodec.BufferInfo(); codec.configure(format, null, null, 0); codec.start(); ByteBuffer[] in=codec.getInputBuffers(); ByteBuffer[] out=codec.getOutputBuffers(); !AudioTrack track=new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, isMono ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, 10240*4, AudioTrack.MODE_STREAM); track.play();
while (!endOfStream) { int inIndex = codec.dequeueInputBuffer(-1); if (inIndex >= 0) { in[inIndex].clear(); in[inIndex].position(0); in[inIndex].put(frameData, 0, frameSize); codec.queueInputBuffer(inIndex, 0, frameSize, sampleTime, 0); } int outIndex = codec.dequeueOutputBuffer(info, 1000); if (outIndex >= 0) { out[outIndex].position(info.offset); out[outIndex].get(codecBuffer, 0, info.size); track.write(codecBuffer, 0, info.size); codec.releaseOutputBuffer(outIndex, false); } }
Видео
Видео(всё очень плохо)
Видео(всё очень плохо)
(раньше было ещё хуже)
Приложение AskVideoAnswer
Приложение AskVideoAnswer• Использует
недокументированное API Ask.fm
Приложение AskVideoAnswer• Использует
недокументированное API Ask.fm
• Сжимает видео перед отправкой
Приложение AskVideoAnswer• Использует
недокументированное API Ask.fm
• Сжимает видео перед отправкой
• Сделано в стиле Material Design
Приложение AskVideoAnswer• Использует
недокументированное API Ask.fm
• Сжимает видео перед отправкой
• Сделано в стиле Material Design
• Позволяет доминировать над пользователями iOS
Что такое видеофайл?З
агол
овок
AVI = Audio/Video Interleaved(но мы будем говорить про mp4)
MediaExtractor
MediaMuxer
4.3+API level 18
Файл MediaExtractor
MediaCodec decoder
MediaCodec decoder
Уменьшение размера кадра
MediaCodec encoder
MediaCodec encoder
ФайлMediaMuxer
Цветовое пространство YUV
Цветовое пространство YUV
Цветовое пространство YUV
Y U V
Уменьшаем кадры правильно
private static void resizeYuvFrame(byte[] from, byte[] to, int w, int h, int sample){ int tw = w / sample; int th = h / sample; // Y for(int y = 0; y < th; y++) { for(int x = 0; x < tw; x++) { to[y*tw+x] = from[y * sample * w + x * sample]; } } // UV int offset = tw * th; for(int y = 0; y < th / 2; y++) { for(int x = 0; x < tw / 2; x++) { int uIndex = y * sample * w + x * sample * 2; to[offset] = from[w * h + uIndex]; // u to[offset + 1] = from[w * h + uIndex + 1]; // v offset += 2; } } }
Фрагментация
Кадр здорового человекаКадр курильщика
Qualcomm
/* get frame tile coordinate. XXX: nothing to be understood here, don't try. */
— исходный код VLC
Приложение-пример
Q & AСсылка на приложение-пример на GitHub
Григорий Клюшников vk.com/grishka Telegram: @grishka