MeasureHelper.java 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (C) 2015 Bilibili
  3. * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.edufound.reader.ijkplayer.media;
  18. import android.view.View;
  19. import java.lang.ref.WeakReference;
  20. public final class MeasureHelper {
  21. private WeakReference<View> mWeakView;
  22. private int mVideoWidth;
  23. private int mVideoHeight;
  24. private int mVideoSarNum;
  25. private int mVideoSarDen;
  26. private int mVideoRotationDegree;
  27. private int mMeasuredWidth;
  28. private int mMeasuredHeight;
  29. private int mCurrentAspectRatio = IRenderView.AR_ASPECT_FIT_PARENT;
  30. public MeasureHelper(View view) {
  31. mWeakView = new WeakReference<View>(view);
  32. }
  33. public View getView() {
  34. if (mWeakView == null)
  35. return null;
  36. return mWeakView.get();
  37. }
  38. public void setVideoSize(int videoWidth, int videoHeight) {
  39. mVideoWidth = videoWidth;
  40. mVideoHeight = videoHeight;
  41. }
  42. public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
  43. mVideoSarNum = videoSarNum;
  44. mVideoSarDen = videoSarDen;
  45. }
  46. public void setVideoRotation(int videoRotationDegree) {
  47. mVideoRotationDegree = videoRotationDegree;
  48. }
  49. /**
  50. * Must be called by View.onMeasure(int, int)
  51. *
  52. * @param widthMeasureSpec
  53. * @param heightMeasureSpec
  54. */
  55. public void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  56. //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
  57. // + MeasureSpec.toString(heightMeasureSpec) + ")");
  58. if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
  59. int tempSpec = widthMeasureSpec;
  60. widthMeasureSpec = heightMeasureSpec;
  61. heightMeasureSpec = tempSpec;
  62. }
  63. int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec);
  64. int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec);
  65. if (mCurrentAspectRatio == IRenderView.AR_MATCH_PARENT) {
  66. width = widthMeasureSpec;
  67. height = heightMeasureSpec;
  68. } else if (mVideoWidth > 0 && mVideoHeight > 0) {
  69. int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
  70. int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
  71. int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
  72. int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
  73. if (widthSpecMode == View.MeasureSpec.AT_MOST && heightSpecMode == View.MeasureSpec.AT_MOST) {
  74. float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize;
  75. float displayAspectRatio;
  76. switch (mCurrentAspectRatio) {
  77. case IRenderView.AR_16_9_FIT_PARENT:
  78. displayAspectRatio = 16.0f / 9.0f;
  79. if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
  80. displayAspectRatio = 1.0f / displayAspectRatio;
  81. break;
  82. case IRenderView.AR_4_3_FIT_PARENT:
  83. displayAspectRatio = 4.0f / 3.0f;
  84. if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
  85. displayAspectRatio = 1.0f / displayAspectRatio;
  86. break;
  87. case IRenderView.AR_ASPECT_FIT_PARENT:
  88. case IRenderView.AR_ASPECT_FILL_PARENT:
  89. case IRenderView.AR_ASPECT_WRAP_CONTENT:
  90. default:
  91. displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;
  92. if (mVideoSarNum > 0 && mVideoSarDen > 0)
  93. displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen;
  94. break;
  95. }
  96. boolean shouldBeWider = displayAspectRatio > specAspectRatio;
  97. switch (mCurrentAspectRatio) {
  98. case IRenderView.AR_ASPECT_FIT_PARENT:
  99. case IRenderView.AR_16_9_FIT_PARENT:
  100. case IRenderView.AR_4_3_FIT_PARENT:
  101. if (shouldBeWider) {
  102. // too wide, fix width
  103. width = widthSpecSize;
  104. height = (int) (width / displayAspectRatio);
  105. } else {
  106. // too high, fix height
  107. height = heightSpecSize;
  108. width = (int) (height * displayAspectRatio);
  109. }
  110. break;
  111. case IRenderView.AR_ASPECT_FILL_PARENT:
  112. if (shouldBeWider) {
  113. // not high enough, fix height
  114. height = heightSpecSize;
  115. width = (int) (height * displayAspectRatio);
  116. } else {
  117. // not wide enough, fix width
  118. width = widthSpecSize;
  119. height = (int) (width / displayAspectRatio);
  120. }
  121. break;
  122. case IRenderView.AR_ASPECT_WRAP_CONTENT:
  123. default:
  124. if (shouldBeWider) {
  125. // too wide, fix width
  126. width = Math.min(mVideoWidth, widthSpecSize);
  127. height = (int) (width / displayAspectRatio);
  128. } else {
  129. // too high, fix height
  130. height = Math.min(mVideoHeight, heightSpecSize);
  131. width = (int) (height * displayAspectRatio);
  132. }
  133. break;
  134. }
  135. } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) {
  136. // the size is fixed
  137. width = widthSpecSize;
  138. height = heightSpecSize;
  139. // for compatibility, we adjust size based on aspect ratio
  140. if (mVideoWidth * height < width * mVideoHeight) {
  141. //Log.i("@@@", "image too wide, correcting");
  142. width = height * mVideoWidth / mVideoHeight;
  143. } else if (mVideoWidth * height > width * mVideoHeight) {
  144. //Log.i("@@@", "image too tall, correcting");
  145. height = width * mVideoHeight / mVideoWidth;
  146. }
  147. } else if (widthSpecMode == View.MeasureSpec.EXACTLY) {
  148. // only the width is fixed, adjust the height to match aspect ratio if possible
  149. width = widthSpecSize;
  150. height = width * mVideoHeight / mVideoWidth;
  151. if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
  152. // couldn't match aspect ratio within the constraints
  153. height = heightSpecSize;
  154. }
  155. } else if (heightSpecMode == View.MeasureSpec.EXACTLY) {
  156. // only the height is fixed, adjust the width to match aspect ratio if possible
  157. height = heightSpecSize;
  158. width = height * mVideoWidth / mVideoHeight;
  159. if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
  160. // couldn't match aspect ratio within the constraints
  161. width = widthSpecSize;
  162. }
  163. } else {
  164. // neither the width nor the height are fixed, try to use actual video size
  165. width = mVideoWidth;
  166. height = mVideoHeight;
  167. if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
  168. // too tall, decrease both width and height
  169. height = heightSpecSize;
  170. width = height * mVideoWidth / mVideoHeight;
  171. }
  172. if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
  173. // too wide, decrease both width and height
  174. width = widthSpecSize;
  175. height = width * mVideoHeight / mVideoWidth;
  176. }
  177. }
  178. } else {
  179. // no size yet, just adopt the given spec sizes
  180. }
  181. mMeasuredWidth = width;
  182. mMeasuredHeight = height;
  183. }
  184. public int getMeasuredWidth() {
  185. return mMeasuredWidth;
  186. }
  187. public int getMeasuredHeight() {
  188. return mMeasuredHeight;
  189. }
  190. public void setAspectRatio(int aspectRatio) {
  191. mCurrentAspectRatio = aspectRatio;
  192. }
  193. }