OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2013 Google Inc. | 3 * Copyright 2013 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
11 * this list of conditions and the following disclaimer in the documentation | 11 * this list of conditions and the following disclaimer in the documentation |
12 * and/or other materials provided with the distribution. | 12 * and/or other materials provided with the distribution. |
13 * 3. The name of the author may not be used to endorse or promote products | 13 * 3. The name of the author may not be used to endorse or promote products |
14 * derived from this software without specific prior written permission. | 14 * derived from this software without specific prior written permission. |
15 * | 15 * |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 | |
29 package org.webrtc; | 28 package org.webrtc; |
30 | 29 |
31 import android.media.MediaCodec; | 30 import android.media.MediaCodec; |
32 import android.media.MediaCodecInfo.CodecCapabilities; | 31 import android.media.MediaCodecInfo.CodecCapabilities; |
33 import android.media.MediaCodecInfo; | 32 import android.media.MediaCodecInfo; |
34 import android.media.MediaCodecList; | 33 import android.media.MediaCodecList; |
35 import android.media.MediaFormat; | 34 import android.media.MediaFormat; |
36 import android.os.Build; | 35 import android.os.Build; |
37 import android.os.Bundle; | 36 import android.os.Bundle; |
38 | 37 |
(...skipping 16 matching lines...) Expand all Loading... |
55 private static final String TAG = "MediaCodecVideoEncoder"; | 54 private static final String TAG = "MediaCodecVideoEncoder"; |
56 | 55 |
57 // Tracks webrtc::VideoCodecType. | 56 // Tracks webrtc::VideoCodecType. |
58 public enum VideoCodecType { | 57 public enum VideoCodecType { |
59 VIDEO_CODEC_VP8, | 58 VIDEO_CODEC_VP8, |
60 VIDEO_CODEC_VP9, | 59 VIDEO_CODEC_VP9, |
61 VIDEO_CODEC_H264 | 60 VIDEO_CODEC_H264 |
62 } | 61 } |
63 | 62 |
64 private static final int DEQUEUE_TIMEOUT = 0; // Non-blocking, no wait. | 63 private static final int DEQUEUE_TIMEOUT = 0; // Non-blocking, no wait. |
| 64 private static MediaCodecVideoEncoder instance = null; |
65 private Thread mediaCodecThread; | 65 private Thread mediaCodecThread; |
66 private MediaCodec mediaCodec; | 66 private MediaCodec mediaCodec; |
67 private ByteBuffer[] outputBuffers; | 67 private ByteBuffer[] outputBuffers; |
68 private static final String VP8_MIME_TYPE = "video/x-vnd.on2.vp8"; | 68 private static final String VP8_MIME_TYPE = "video/x-vnd.on2.vp8"; |
69 private static final String H264_MIME_TYPE = "video/avc"; | 69 private static final String H264_MIME_TYPE = "video/avc"; |
70 // List of supported HW VP8 codecs. | 70 // List of supported HW VP8 codecs. |
71 private static final String[] supportedVp8HwCodecPrefixes = | 71 private static final String[] supportedVp8HwCodecPrefixes = |
72 {"OMX.qcom.", "OMX.Intel." }; | 72 {"OMX.qcom.", "OMX.Intel." }; |
73 // List of supported HW H.264 codecs. | 73 // List of supported HW H.264 codecs. |
74 private static final String[] supportedH264HwCodecPrefixes = | 74 private static final String[] supportedH264HwCodecPrefixes = |
(...skipping 21 matching lines...) Expand all Loading... |
96 CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, | 96 CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, |
97 COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m | 97 COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m |
98 }; | 98 }; |
99 private VideoCodecType type; | 99 private VideoCodecType type; |
100 private int colorFormat; // Used by native code. | 100 private int colorFormat; // Used by native code. |
101 | 101 |
102 // SPS and PPS NALs (Config frame) for H.264. | 102 // SPS and PPS NALs (Config frame) for H.264. |
103 private ByteBuffer configData = null; | 103 private ByteBuffer configData = null; |
104 | 104 |
105 MediaCodecVideoEncoder() { | 105 MediaCodecVideoEncoder() { |
106 mediaCodecThread = null; | 106 instance = this; |
107 } | 107 } |
108 | 108 |
109 // Helper struct for findHwEncoder() below. | 109 // Helper struct for findHwEncoder() below. |
110 private static class EncoderProperties { | 110 private static class EncoderProperties { |
111 public EncoderProperties(String codecName, int colorFormat) { | 111 public EncoderProperties(String codecName, int colorFormat) { |
112 this.codecName = codecName; | 112 this.codecName = codecName; |
113 this.colorFormat = colorFormat; | 113 this.colorFormat = colorFormat; |
114 } | 114 } |
115 public final String codecName; // OpenMax component name for HW codec. | 115 public final String codecName; // OpenMax component name for HW codec. |
116 public final int colorFormat; // Color format supported by codec. | 116 public final int colorFormat; // Color format supported by codec. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 192 } |
193 | 193 |
194 private void checkOnMediaCodecThread() { | 194 private void checkOnMediaCodecThread() { |
195 if (mediaCodecThread.getId() != Thread.currentThread().getId()) { | 195 if (mediaCodecThread.getId() != Thread.currentThread().getId()) { |
196 throw new RuntimeException( | 196 throw new RuntimeException( |
197 "MediaCodecVideoEncoder previously operated on " + mediaCodecThread + | 197 "MediaCodecVideoEncoder previously operated on " + mediaCodecThread + |
198 " but is now called on " + Thread.currentThread()); | 198 " but is now called on " + Thread.currentThread()); |
199 } | 199 } |
200 } | 200 } |
201 | 201 |
| 202 public static void printStackTrace() { |
| 203 if (instance != null && instance.mediaCodecThread != null) { |
| 204 StackTraceElement[] mediaCodecStackTraces = instance.mediaCodecThread.getS
tackTrace(); |
| 205 if (mediaCodecStackTraces.length > 0) { |
| 206 Logging.d(TAG, "MediaCodecVideoEncoder stacks trace:"); |
| 207 for (StackTraceElement stackTrace : mediaCodecStackTraces) { |
| 208 Logging.d(TAG, stackTrace.toString()); |
| 209 } |
| 210 } |
| 211 } |
| 212 } |
| 213 |
202 static MediaCodec createByCodecName(String codecName) { | 214 static MediaCodec createByCodecName(String codecName) { |
203 try { | 215 try { |
204 // In the L-SDK this call can throw IOException so in order to work in | 216 // In the L-SDK this call can throw IOException so in order to work in |
205 // both cases catch an exception. | 217 // both cases catch an exception. |
206 return MediaCodec.createByCodecName(codecName); | 218 return MediaCodec.createByCodecName(codecName); |
207 } catch (Exception e) { | 219 } catch (Exception e) { |
208 return null; | 220 return null; |
209 } | 221 } |
210 } | 222 } |
211 | 223 |
(...skipping 26 matching lines...) Expand all Loading... |
238 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); | 250 MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); |
239 format.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * kbps); | 251 format.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * kbps); |
240 format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); | 252 format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); |
241 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat); | 253 format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat); |
242 format.setInteger(MediaFormat.KEY_FRAME_RATE, fps); | 254 format.setInteger(MediaFormat.KEY_FRAME_RATE, fps); |
243 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec); | 255 format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec); |
244 Logging.d(TAG, " Format: " + format); | 256 Logging.d(TAG, " Format: " + format); |
245 mediaCodec = createByCodecName(properties.codecName); | 257 mediaCodec = createByCodecName(properties.codecName); |
246 this.type = type; | 258 this.type = type; |
247 if (mediaCodec == null) { | 259 if (mediaCodec == null) { |
| 260 Logging.e(TAG, "Can not create media encoder"); |
248 return false; | 261 return false; |
249 } | 262 } |
250 mediaCodec.configure( | 263 mediaCodec.configure( |
251 format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); | 264 format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); |
252 | 265 |
253 mediaCodec.start(); | 266 mediaCodec.start(); |
254 outputBuffers = mediaCodec.getOutputBuffers(); | 267 outputBuffers = mediaCodec.getOutputBuffers(); |
255 | 268 |
256 } catch (IllegalStateException e) { | 269 } catch (IllegalStateException e) { |
257 Logging.e(TAG, "initEncode failed", e); | 270 Logging.e(TAG, "initEncode failed", e); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 Logging.d(TAG, "Java releaseEncoder"); | 308 Logging.d(TAG, "Java releaseEncoder"); |
296 checkOnMediaCodecThread(); | 309 checkOnMediaCodecThread(); |
297 try { | 310 try { |
298 mediaCodec.stop(); | 311 mediaCodec.stop(); |
299 mediaCodec.release(); | 312 mediaCodec.release(); |
300 } catch (IllegalStateException e) { | 313 } catch (IllegalStateException e) { |
301 Logging.e(TAG, "release failed", e); | 314 Logging.e(TAG, "release failed", e); |
302 } | 315 } |
303 mediaCodec = null; | 316 mediaCodec = null; |
304 mediaCodecThread = null; | 317 mediaCodecThread = null; |
| 318 instance = null; |
| 319 Logging.d(TAG, "Java releaseEncoder done"); |
305 } | 320 } |
306 | 321 |
307 private boolean setRates(int kbps, int frameRateIgnored) { | 322 private boolean setRates(int kbps, int frameRateIgnored) { |
308 // frameRate argument is ignored - HW encoder is supposed to use | 323 // frameRate argument is ignored - HW encoder is supposed to use |
309 // video frame timestamps for bit allocation. | 324 // video frame timestamps for bit allocation. |
310 checkOnMediaCodecThread(); | 325 checkOnMediaCodecThread(); |
311 Logging.v(TAG, "setRates: " + kbps + " kbps. Fps: " + frameRateIgnored); | 326 Logging.v(TAG, "setRates: " + kbps + " kbps. Fps: " + frameRateIgnored); |
312 try { | 327 try { |
313 Bundle params = new Bundle(); | 328 Bundle params = new Bundle(); |
314 params.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, 1000 * kbps); | 329 params.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, 1000 * kbps); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 checkOnMediaCodecThread(); | 439 checkOnMediaCodecThread(); |
425 try { | 440 try { |
426 mediaCodec.releaseOutputBuffer(index, false); | 441 mediaCodec.releaseOutputBuffer(index, false); |
427 return true; | 442 return true; |
428 } catch (IllegalStateException e) { | 443 } catch (IllegalStateException e) { |
429 Logging.e(TAG, "releaseOutputBuffer failed", e); | 444 Logging.e(TAG, "releaseOutputBuffer failed", e); |
430 return false; | 445 return false; |
431 } | 446 } |
432 } | 447 } |
433 } | 448 } |
OLD | NEW |