Advertisement
Guest User

Untitled

a guest
Feb 21st, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.50 KB | None | 0 0
  1. package com.github.niqdev.mjpeg;
  2.  
  3. import android.graphics.Bitmap;
  4. import android.graphics.Canvas;
  5. import android.graphics.Color;
  6. import android.graphics.Matrix;
  7. import android.graphics.Paint;
  8. import android.graphics.PixelFormat;
  9. import android.graphics.PorterDuff;
  10. import android.graphics.PorterDuffXfermode;
  11. import android.graphics.Rect;
  12. import android.graphics.Typeface;
  13. import android.util.DisplayMetrics;
  14. import android.util.Log;
  15. import android.view.SurfaceHolder;
  16. import android.view.SurfaceView;
  17.  
  18. import java.io.IOException;
  19.  
  20. /*
  21. * I don't really understand and want to know what the hell it does!
  22. * Maybe one day I will refactor it ;-)
  23. * <p/>
  24. * https://code.google.com/archive/p/android-camera-axis
  25. */
  26. public class MjpegViewDefault extends AbstractMjpegView {
  27. private static final String TAG = MjpegViewDefault.class.getSimpleName();
  28.  
  29. private SurfaceHolder.Callback mSurfaceHolderCallback;
  30. private SurfaceView mSurfaceView;
  31. private boolean transparentBackground;
  32.  
  33. private MjpegViewThread thread;
  34. private MjpegInputStreamDefault mIn = null;
  35. private boolean showFps = false;
  36. private boolean flipSource = false;
  37. private volatile boolean mRun = false;
  38. private volatile boolean surfaceDone = false;
  39. private Paint overlayPaint;
  40. private int overlayTextColor;
  41. private int overlayBackgroundColor;
  42. private int backgroundColor;
  43. private int ovlPos;
  44. private int dispWidth;
  45. private int dispHeight;
  46. private int displayMode;
  47. private boolean resume = false;
  48.  
  49. private long delay;
  50.  
  51. private OnFrameCapturedListener onFrameCapturedListener;
  52.  
  53. // no more accessible
  54. class MjpegViewThread extends Thread {
  55. private SurfaceHolder mSurfaceHolder;
  56. private int frameCounter = 0;
  57. private long start;
  58. private Bitmap ovl;
  59.  
  60. // no more accessible
  61. MjpegViewThread(SurfaceHolder surfaceHolder) {
  62. mSurfaceHolder = surfaceHolder;
  63. }
  64.  
  65. private Rect destRect(int bmw, int bmh) {
  66.  
  67. int tempx;
  68. int tempy;
  69. if (displayMode == MjpegViewDefault.SIZE_STANDARD) {
  70. tempx = (dispWidth / 2) - (bmw / 2);
  71. tempy = (dispHeight / 2) - (bmh / 2);
  72. return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
  73. }
  74. if (displayMode == MjpegViewDefault.SIZE_BEST_FIT) {
  75. float bmasp = (float) bmw / (float) bmh;
  76. bmw = dispWidth;
  77. bmh = (int) (dispWidth / bmasp);
  78. if (bmh > dispHeight) {
  79. bmh = dispHeight;
  80. bmw = (int) (dispHeight * bmasp);
  81. }
  82. tempx = (dispWidth / 2) - (bmw / 2);
  83. tempy = (dispHeight / 2) - (bmh / 2);
  84. return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
  85. }
  86. if (displayMode == MjpegViewDefault.SIZE_FULLSCREEN)
  87. return new Rect(0, 0, dispWidth, dispHeight);
  88. return null;
  89. }
  90.  
  91. // no more accessible
  92. void setSurfaceSize(int width, int height) {
  93. synchronized (mSurfaceHolder) {
  94. dispWidth = width;
  95. dispHeight = height;
  96. }
  97. }
  98.  
  99. private Bitmap makeFpsOverlay(Paint p, String text) {
  100. Rect b = new Rect();
  101. p.getTextBounds(text, 0, text.length(), b);
  102. int bwidth = b.width() + 2;
  103. int bheight = b.height() + 2;
  104. Bitmap bm = Bitmap.createBitmap(bwidth, bheight,
  105. Bitmap.Config.ARGB_8888);
  106. Canvas c = new Canvas(bm);
  107. p.setColor(overlayBackgroundColor);
  108. c.drawRect(0, 0, bwidth, bheight, p);
  109. p.setColor(overlayTextColor);
  110. c.drawText(text, -b.left + 1,
  111. (bheight / 2) - ((p.ascent() + p.descent()) / 2) + 1, p);
  112. return bm;
  113. }
  114.  
  115. public void run() {
  116. start = System.currentTimeMillis();
  117. PorterDuffXfermode mode = new PorterDuffXfermode(
  118. PorterDuff.Mode.DST_OVER);
  119. Bitmap bm;
  120. int width;
  121. int height;
  122. Rect destRect;
  123. Canvas c = null;
  124. Paint p = new Paint();
  125. String fps = "";
  126. while (mRun) {
  127. if (surfaceDone) {
  128. try {
  129. c = mSurfaceHolder.lockCanvas();
  130.  
  131. if (c == null) {
  132. Log.w(TAG, "null canvas, skipping render");
  133. continue;
  134. }
  135. synchronized (mSurfaceHolder) {
  136. try {
  137. if(flipSource)
  138. {
  139. bm = flip(mIn.readMjpegFrame());
  140. } else {
  141. bm = mIn.readMjpegFrame();
  142. }
  143. _frameCaptured(bm);
  144. destRect = destRect(bm.getWidth(),
  145. bm.getHeight());
  146.  
  147. if (transparentBackground) {
  148. c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
  149. } else {
  150. c.drawColor(backgroundColor);
  151. }
  152.  
  153. c.drawBitmap(bm, null, destRect, p);
  154.  
  155. if (showFps) {
  156. p.setXfermode(mode);
  157. if (ovl != null) {
  158. height = ((ovlPos & 1) == 1) ? destRect.top
  159. : destRect.bottom
  160. - ovl.getHeight();
  161. width = ((ovlPos & 8) == 8) ? destRect.left
  162. : destRect.right
  163. - ovl.getWidth();
  164. c.drawBitmap(ovl, width, height, null);
  165. }
  166. p.setXfermode(null);
  167. frameCounter++;
  168. if ((System.currentTimeMillis() - start) >= 1000) {
  169. fps = String.valueOf(frameCounter)
  170. + "fps";
  171. frameCounter = 0;
  172. start = System.currentTimeMillis();
  173. ovl = makeFpsOverlay(overlayPaint, fps);
  174. }
  175. }
  176. } catch (IOException e) {
  177. Log.e(TAG, "encountered exception during render", e);
  178. }
  179. }
  180. } finally {
  181. if (c != null) {
  182. mSurfaceHolder.unlockCanvasAndPost(c);
  183. } else {
  184. Log.w(TAG, "couldn't unlock surface canvas");
  185. }
  186. }
  187. }
  188. }
  189. }
  190. }
  191.  
  192. Bitmap flip(Bitmap src)
  193. {
  194. Matrix m = new Matrix();
  195. m.preScale(-1, 1);
  196. Bitmap dst = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), m, false);
  197. dst.setDensity(DisplayMetrics.DENSITY_DEFAULT);
  198. return dst;
  199. }
  200.  
  201. private void init() {
  202.  
  203. SurfaceHolder holder = mSurfaceView.getHolder();
  204. holder.addCallback(mSurfaceHolderCallback);
  205. thread = new MjpegViewThread(holder);
  206. mSurfaceView.setFocusable(true);
  207. if (!resume) {
  208. resume = true;
  209. overlayPaint = new Paint();
  210. overlayPaint.setTextAlign(Paint.Align.LEFT);
  211. overlayPaint.setTextSize(12);
  212. overlayPaint.setTypeface(Typeface.DEFAULT);
  213. overlayTextColor = Color.WHITE;
  214. overlayBackgroundColor = Color.BLACK;
  215. backgroundColor = Color.BLACK;
  216. ovlPos = MjpegViewDefault.POSITION_LOWER_RIGHT;
  217. displayMode = MjpegViewDefault.SIZE_STANDARD;
  218. dispWidth = mSurfaceView.getWidth();
  219. dispHeight = mSurfaceView.getHeight();
  220. }
  221. }
  222.  
  223. /* all methods/constructors below are no more accessible */
  224.  
  225. void _startPlayback() {
  226. if (mIn != null && thread != null) {
  227. mRun = true;
  228. /*
  229. * clear canvas cache
  230. * @see https://github.com/niqdev/ipcam-view/issues/14
  231. */
  232. mSurfaceView.destroyDrawingCache();
  233. thread.start();
  234. }
  235. }
  236.  
  237. void _resumePlayback() {
  238. mRun = true;
  239. init();
  240. thread.start();
  241. }
  242.  
  243. /*
  244. * @see https://github.com/niqdev/ipcam-view/issues/14
  245. */
  246. synchronized void _stopPlayback() {
  247. mRun = false;
  248. boolean retry = true;
  249. while (retry) {
  250. try {
  251. // make sure the thread is not null
  252. if (thread != null) {
  253. thread.join(500);
  254. }
  255. retry = false;
  256. } catch (InterruptedException e) {
  257. Log.e(TAG, "error stopping playback thread", e);
  258. }
  259. }
  260.  
  261. // close the connection
  262. if (mIn != null) {
  263. try {
  264. mIn.close();
  265. } catch (IOException e) {
  266. Log.e(TAG, "error closing input stream", e);
  267. }
  268. mIn = null;
  269. }
  270. }
  271.  
  272. void _surfaceChanged(SurfaceHolder holder, int f, int w, int h) {
  273. if (thread != null) {
  274. thread.setSurfaceSize(w, h);
  275. }
  276. }
  277.  
  278. void _surfaceDestroyed(SurfaceHolder holder) {
  279. surfaceDone = false;
  280. _stopPlayback();
  281. if (thread != null) {
  282. thread = null;
  283. }
  284. }
  285.  
  286. void _frameCaptured(Bitmap bitmap){
  287. if (onFrameCapturedListener != null){
  288. onFrameCapturedListener.onFrameCaptured(bitmap);
  289. }
  290. }
  291.  
  292. MjpegViewDefault(SurfaceView surfaceView, SurfaceHolder.Callback callback, boolean transparentBackground) {
  293. this.mSurfaceView = surfaceView;
  294. this.mSurfaceHolderCallback = callback;
  295. this.transparentBackground = transparentBackground;
  296. init();
  297. }
  298.  
  299. void _surfaceCreated(SurfaceHolder holder) {
  300. surfaceDone = true;
  301. }
  302.  
  303. void _showFps(boolean b) {
  304. showFps = b;
  305. }
  306.  
  307. void _flipSource(boolean b) {
  308. flipSource = b;
  309. }
  310.  
  311. /*
  312. * @see https://github.com/niqdev/ipcam-view/issues/14
  313. */
  314. void _setSource(MjpegInputStreamDefault source) {
  315. mIn = source;
  316. // make sure resume is calling _resumePlayback()
  317. if (!resume) {
  318. _startPlayback();
  319. } else {
  320. _resumePlayback();
  321. }
  322. }
  323.  
  324. void _setOverlayPaint(Paint p) {
  325. overlayPaint = p;
  326. }
  327.  
  328. void _setOverlayTextColor(int c) {
  329. overlayTextColor = c;
  330. }
  331.  
  332. void _setOverlayBackgroundColor(int c) {
  333. overlayBackgroundColor = c;
  334. }
  335.  
  336. void _setOverlayPosition(int p) {
  337. ovlPos = p;
  338. }
  339.  
  340. void _setDisplayMode(int s) {
  341. displayMode = s;
  342. }
  343.  
  344. /* override methods */
  345.  
  346. @Override
  347. public void onSurfaceCreated(SurfaceHolder holder) {
  348. _surfaceCreated(holder);
  349. }
  350.  
  351. @Override
  352. public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  353. _surfaceChanged(holder, format, width, height);
  354. }
  355.  
  356. @Override
  357. public void onSurfaceDestroyed(SurfaceHolder holder) {
  358. _surfaceDestroyed(holder);
  359. }
  360.  
  361. @Override
  362. public void setSource(MjpegInputStream stream) {
  363. if (!(stream instanceof MjpegInputStreamDefault)) {
  364. throw new IllegalArgumentException("stream must be an instance of MjpegInputStreamDefault");
  365. }
  366. _setSource((MjpegInputStreamDefault) stream);
  367. }
  368.  
  369. @Override
  370. public void setDisplayMode(DisplayMode mode) {
  371. _setDisplayMode(mode.getValue());
  372. }
  373.  
  374. @Override
  375. public void showFps(boolean show) {
  376. _showFps(show);
  377. }
  378.  
  379. @Override
  380. public void flipSource(boolean flip) {
  381. _flipSource(flip);
  382. }
  383.  
  384. @Override
  385. public void stopPlayback() {
  386. _stopPlayback();
  387. }
  388.  
  389. @Override
  390. public boolean isStreaming() {
  391. return mRun;
  392. }
  393.  
  394. @Override
  395. public void setResolution(int width, int height) {
  396. throw new UnsupportedOperationException("not implemented");
  397. }
  398.  
  399. @Override
  400. public void freeCameraMemory() {
  401. throw new UnsupportedOperationException("not implemented");
  402. }
  403.  
  404. @Override
  405. public void setOnFrameCapturedListener(OnFrameCapturedListener onFrameCapturedListener) {
  406. this.onFrameCapturedListener = onFrameCapturedListener;
  407. }
  408.  
  409. @Override
  410. public void setCustomBackgroundColor(int backgroundColor) {
  411. this.backgroundColor = backgroundColor;
  412. }
  413.  
  414. @Override
  415. public void setFpsOverlayBackgroundColor(int overlayBackgroundColor) {
  416. this.overlayBackgroundColor = overlayBackgroundColor;
  417. }
  418.  
  419. @Override
  420. public void setFpsOverlayTextColor(int overlayTextColor) {
  421. this.overlayTextColor = overlayTextColor;
  422. }
  423.  
  424. @Override
  425. public SurfaceView getSurfaceView() {
  426. return mSurfaceView;
  427. }
  428.  
  429. @Override
  430. public void resetTransparentBackground() {
  431. mSurfaceView.setZOrderOnTop(false);
  432. mSurfaceView.getHolder().setFormat(PixelFormat.OPAQUE);
  433. }
  434.  
  435. @Override
  436. public void setTransparentBackground() {
  437. mSurfaceView.setZOrderOnTop(true);
  438. mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
  439. }
  440.  
  441. @Override
  442. public void clearStream() {
  443. Canvas c = null;
  444.  
  445. try {
  446. c = mSurfaceView.getHolder().lockCanvas();
  447. c.drawColor(0, PorterDuff.Mode.CLEAR);
  448. } finally {
  449. if (c != null) {
  450. mSurfaceView.getHolder().unlockCanvasAndPost(c);
  451. } else {
  452. Log.w(TAG, "couldn't unlock surface canvas");
  453. }
  454. }
  455. }
  456. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement