1.分享一个Android系统源码在线查看的网站
2.安利一个看 Android 源代码的网站
3.androidä¸mediamuxeråmediacodecçåºå«
分享一个Android系统源码在线查看的网站
欢迎访问在线查看Android系统源码的网站:/和aosp.opersys.com/。它们提供了在线浏览源码的功能,但各有不足。androidos.net.cn/并未提供交叉索引,手机免流源码对我用处不大;而aosp.opersys.com/虽然提供了交叉索引和变化日志,但经常宕机,创世对决源码访问速度也不理想。面对工作需求和效率问题,我决定自己开发一个网站——aospxref.com。这个网站不仅具备与androidxref.com相同的源码浏览和交叉索引功能,还有额外的优点。它为开发者提供了一个更加稳定、快速的神兽公会源码在线浏览源代码的平台。访问网站,体验革新,提升您的卡充值源码工作效率。
如果您对加入与Android相关的项目感兴趣,可以发送邮件至twsxtd@gmail.com,欢迎您的什么开源码加入!让aospxref.com成为您工作中不可或缺的工具。我们致力于提供最好的服务,期待与您共同成长。
androidä¸mediamuxeråmediacodecçåºå«
Androidä¸MediaMuxeråMediaCodecç¨ä¾
å¨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ææ¾å¨ææ¾ãå½ç¶äºï¼éééæ ·çä¹ç±»çè¦èªå·±è®¾ï¼å 为åå§éæ ·æ°æ®æ¯æ²¡ææ件头çï¼å¦ï¼
vlc --demux=rawaud --rawaud-channels 2 --rawaud-samplerate audio.pcm
åå°MediaMuxeråMediaCodecè¿ä¸¤ä¸ªç±»ï¼å®ä»¬çåèææ¡£è§/reference/android/media/MediaMuxer.htmlå/reference/android/media/MediaCodec.htmlï¼éè¾¹æ使ç¨çæ¡æ¶ãè¿ä¸ªç»åå¯ä»¥å®ç°å¾å¤åè½ï¼æ¯å¦é³è§é¢æ件çç¼è¾ï¼ç»åMediaExtractorï¼ï¼ç¨OpenGLç»å¶Surface并çæmp4æ件ï¼å±å¹å½å以å类似Camera appéçå½ååè½ï¼è½ç¶è¿ä¸ªç¨MediaRecorderæ´åéï¼çã
è¿é以ä¸ä¸ªå¾æ èçåè½ä¸ºä¾ï¼å°±æ¯å¨ä¸ä¸ªSurfaceä¸ç»å¾ç¼ç çæè§é¢ï¼åæ¶ç¨MICå½é³ç¼ç çæé³é¢ï¼ç¶åå°é³è§é¢æ··åçæmp4æ件ãç¨åºæ¬èº«æ²¡ä»ä¹ç¨ï¼ä½æ¯ç¤ºä¾äºMediaMuxeråMediaCodecçåºæ¬ç¨æ³ãæ¬ç¨åºä¸»è¦æ¯åºäºä¸¤ä¸ªæµè¯ç¨åºï¼ä¸ä¸ªæ¯Grafikaä¸çSoftInputSurfaceActivityåHWEncoderExperimentsãå®ä»¬ä¸ä¸ªæ¯çæè§é¢ï¼ä¸ä¸ªçæé³é¢ï¼è¿éæå®ä»¬ç»åä¸ä¸ï¼åæ¶çæé³é¢åè§é¢ãåºæ¬æ¡æ¶åæµç¨å¦ä¸ï¼
é¦å æ¯å½é³çº¿ç¨ï¼ä¸»è¦åèHWEncoderExperimentsãéè¿AudioRecordç±»æ¥æ¶æ¥èªéº¦å é£çéæ ·æ°æ®ï¼ç¶å丢ç»Encoderåå¤ç¼ç ï¼
AudioRecord audio_recorder;
audio_recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, buffer_size);
// ...
audio_recorder.startRecording();
while (is_recording) {
byte[] this_buffer = new byte[frame_buffer_size];
read_result = audio_recorder.read(this_buffer, 0, frame_buffer_size); // read audio raw data
// â¦
presentationTimeStamp = System.nanoTime() / ;
audioEncoder.offerAudioEncoder(this_buffer.clone(), presentationTimeStamp); // feed to audio encoder
}
è¿éä¹å¯ä»¥è®¾ç½®AudioRecordçåè°ï¼éè¿setRecordPositionUpdateListener()ï¼æ¥è§¦åé³é¢æ°æ®ç读åãofferAudioEncoder()é主è¦æ¯æaudioéæ ·æ°æ®éå ¥é³é¢MediaCodecçInputBufferè¿è¡ç¼ç ï¼
ByteBuffer[] inputBuffers = mAudioEncoder.getInputBuffers();
int inputBufferIndex = mAudioEncoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(this_buffer);
...
mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, this_buffer.length, presentationTimeStamp, 0);
}
ä¸é¢ï¼åèGrafika-SoftInputSurfaceActivityï¼å¹¶å å ¥é³é¢å¤çã主循ç¯å¤§ä½ååé¨åï¼
try {
// Part 1
prepareEncoder(outputFile);
...
// Part 2
for (int i = 0; i < NUM_FRAMES; i++) {
generateFrame(i);
drainVideoEncoder(false);
drainAudioEncoder(false);
}
// Part 3
...
drainVideoEncoder(true);
drainAudioEncoder(true);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
} finally {
// Part 4
releaseEncoder();
}
第1é¨åæ¯åå¤å·¥ä½ï¼é¤äºvideoçMediaCodecï¼è¿éè¿åå§åäºaudioçMediaCodecï¼
MediaFormat audioFormat = new MediaFormat();
audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, );
audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
...
mAudioEncoder = MediaCodec.createEncoderByType(AUDIO_MIME_TYPE);
mAudioEncoder.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mAudioEncoder.start();
第2é¨åè¿å ¥ä¸»å¾ªç¯ï¼appå¨Surfaceä¸ç´æ¥ç»å¾ï¼ç±äºè¿ä¸ªSurfaceæ¯ä»MediaCodecä¸ç¨createInputSurface()ç³è¯·æ¥çï¼æ以ç»å®åä¸ç¨æ¾å¼ç¨queueInputBuffer()交ç»EncoderãdrainVideoEncoder()ådrainAudioEncoder()åå«å°ç¼ç 好çé³è§é¢ä»bufferä¸æ¿åºæ¥ï¼éè¿dequeueOutputBuffer()ï¼ï¼ç¶å交ç±MediaMuxerè¿è¡æ··åï¼éè¿writeSampleData()ï¼ã注æé³è§é¢éè¿PTSï¼Presentation time stampï¼å³å®äºæä¸å¸§çé³è§é¢æ°æ®ä½æ¶æ¾ç¤ºæææ¾ï¼æ¥åæ¥ï¼é³é¢çtime stampéå¨AudioRecordä»MICééå°æ°æ®æ¶è·å并æ¾å°ç¸åºçbufferInfoä¸ï¼è§é¢ç±äºæ¯å¨Surfaceä¸ç»ï¼å æ¤ç´æ¥ç¨dequeueOutputBuffer()åºæ¥çbufferInfoä¸çå°±è¡ï¼æåå°ç¼ç 好çæ°æ®éå»MediaMuxerè¿è¡å¤è·¯æ··åã
注æè¿éMuxerè¦çæaudio trackåvideo tracké½å å ¥äºåå¼å§ãMediaCodecå¨ä¸å¼å§è°ç¨dequeueOutputBuffer()æ¶ä¼è¿åä¸æ¬¡INFO_OUTPUT_FORMAT_CHANGEDæ¶æ¯ãæ们åªéå¨è¿éè·å该MediaCodecçformatï¼å¹¶æ³¨åå°MediaMuxeréãæ¥çå¤æå½åaudio trackåvideo trackæ¯å¦é½å·²å°±ç»ªï¼å¦ææ¯çè¯å°±å¯å¨Muxerã
æ»ç»æ¥è¯´ï¼drainVideoEncoder()ç主é»è¾å¤§è´å¦ä¸ï¼drainAudioEncoderä¹æ¯ç±»ä¼¼çï¼åªæ¯ævideoçMediaCodecæ¢æaudioçMediaCodecå³å¯ã
while(true) {
int encoderStatus = mVideoEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
...
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
encoderOutputBuffers = mVideoEncoder.getOutputBuffers();
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = mAudioEncoder.getOutputFormat();
mAudioTrackIndex = mMuxer.addTrack(newFormat);
mNumTracksAdded++;
if (mNumTracksAdded == TOTAL_NUM_TRACKS) {
mMuxer.start();
}
} else if (encoderStatus < 0) {
...
} else {
ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
...
if (mBufferInfo.size != 0) {
mMuxer.writeSampleData(mVideoTrackIndex, encodedData, mBufferInfo);
}
mVideoEncoder.releaseOutputBuffer(encoderStatus, false);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}
}
}
第3é¨åæ¯ç»æå½å¶ï¼åéEOSä¿¡æ¯ï¼è¿æ ·å¨drainVideoEncoder()ådrainAudioEncoderä¸å°±å¯ä»¥æ ¹æ®EOSéåºå 循ç¯ã第4é¨åä¸ºæ¸ çå·¥ä½ãæaudioåvideoçMediaCodecï¼MediaCodecç¨çSurfaceåMediaMuxer对象éæ¾ã
æåå ç¹æ³¨æï¼
1. å¨AndroidManifest.xmléå ä¸å½é³æéï¼å¦åå建AudioRecord对象æ¶éå®å¤±è´¥ï¼
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
2. é³è§é¢éè¿PTSåæ¥ï¼ä¸¤ä¸ªçåä½è¦ä¸è´ã
3. MediaMuxerç使ç¨è¦æç §Constructor -> addTrack -> start -> writeSampleData -> stop ç顺åºãå¦ææ¢æé³é¢åæè§é¢ï¼å¨stopå两个é½è¦writeSampleData()è¿ã
Code referencesï¼
Grafika: /google/grafika
Bigflake: /mediacodec/
HWEncoderExperimentsï¼/OnlyInAmerica/HWEncoderExperiments/tree/audioonly/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments
Android testï¼/4.4.2_r2/xref/cts/tests/tests/media/src/android/media/cts/
/4.4.2_r2/xref/pdk/apps/TestingCamera2/src/com/android/testingcamera2/CameraRecordingStream.java