|
23 | 23 | import com.yanzhenjie.permission.AndPermission; |
24 | 24 | import com.yanzhenjie.permission.runtime.Permission; |
25 | 25 |
|
26 | | -import java.io.IOException; |
27 | | -import java.io.InputStream; |
28 | | - |
29 | 26 | import io.agora.api.example.MainApplication; |
30 | 27 | import io.agora.api.example.R; |
31 | 28 | import io.agora.api.example.annotation.Example; |
32 | 29 | import io.agora.api.example.common.BaseFragment; |
33 | 30 | import io.agora.api.example.utils.CommonUtil; |
34 | 31 | import io.agora.api.example.utils.TokenUtils; |
35 | | -import io.agora.base.JavaI420Buffer; |
36 | | -import io.agora.base.VideoFrame; |
| 32 | +import io.agora.api.example.utils.VideoFileReader; |
37 | 33 | import io.agora.rtc2.ChannelMediaOptions; |
38 | 34 | import io.agora.rtc2.Constants; |
39 | 35 | import io.agora.rtc2.IRtcEngineEventHandler; |
|
53 | 49 | public class PushExternalVideoYUV extends BaseFragment implements View.OnClickListener { |
54 | 50 | private static final String TAG = PushExternalVideoYUV.class.getSimpleName(); |
55 | 51 |
|
56 | | - private final String RAW_VIDEO_PATH = "sample.yuv"; |
57 | | - private final int RAW_VIDEO_WIDTH = 320; |
58 | | - private final int RAW_VIDEO_HEIGHT = 180; |
59 | | - private final int RAW_VIDEO_FRAME_SIZE = RAW_VIDEO_WIDTH * RAW_VIDEO_HEIGHT / 2 * 3; |
60 | | - private final int RAW_VIDEO_FRAME_RATE = 15; |
61 | | - private final long RAW_VIDEO_FRAME_INTERVAL_NS = 1000 * 1000 * 1000 / RAW_VIDEO_FRAME_RATE; |
62 | | - |
63 | 52 | private FrameLayout fl_local, fl_remote; |
64 | 53 | private Button join; |
65 | 54 | private EditText et_channel; |
66 | 55 | private RtcEngineEx engine; |
67 | 56 | private int myUid; |
68 | 57 | private volatile boolean joined = false; |
69 | 58 |
|
70 | | - private Thread pushingThread; |
71 | | - private volatile boolean pushing = false; |
72 | | - |
73 | | - private InputStream inputStream; |
| 59 | + private VideoFileReader videoFileReader; |
74 | 60 |
|
75 | 61 | @Nullable |
76 | 62 | @Override |
@@ -143,15 +129,8 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { |
143 | 129 |
|
144 | 130 | @Override |
145 | 131 | public void onDestroy() { |
146 | | - pushing = false; |
147 | | - if (pushingThread != null) { |
148 | | - try { |
149 | | - pushingThread.join(); |
150 | | - } catch (InterruptedException e) { |
151 | | - e.printStackTrace(); |
152 | | - } finally { |
153 | | - pushingThread = null; |
154 | | - } |
| 132 | + if(videoFileReader != null){ |
| 133 | + videoFileReader.stop(); |
155 | 134 | } |
156 | 135 |
|
157 | 136 | /**leaveChannel and Destroy the RtcEngine instance*/ |
@@ -206,15 +185,8 @@ public void onClick(View v) { |
206 | 185 | } else { |
207 | 186 | joined = false; |
208 | 187 | join.setText(getString(R.string.join)); |
209 | | - pushing = false; |
210 | | - if (pushingThread != null) { |
211 | | - try { |
212 | | - pushingThread.join(); |
213 | | - } catch (InterruptedException e) { |
214 | | - e.printStackTrace(); |
215 | | - } finally { |
216 | | - pushingThread = null; |
217 | | - } |
| 188 | + if(videoFileReader != null){ |
| 189 | + videoFileReader.stop(); |
218 | 190 | } |
219 | 191 | fl_remote.removeAllViews(); |
220 | 192 | fl_local.removeAllViews(); |
@@ -339,11 +311,14 @@ public void run() { |
339 | 311 | join.setEnabled(true); |
340 | 312 | join.setText(getString(R.string.leave)); |
341 | 313 |
|
342 | | - pushing = true; |
343 | | - if (pushingThread == null) { |
344 | | - pushingThread = new Thread(new PushingTask()); |
345 | | - pushingThread.start(); |
| 314 | + if (videoFileReader == null) { |
| 315 | + videoFileReader = new VideoFileReader(requireContext(), videoFrame -> { |
| 316 | + if(joined && engine != null){ |
| 317 | + engine.pushExternalVideoFrame(videoFrame); |
| 318 | + } |
| 319 | + }); |
346 | 320 | } |
| 321 | + videoFileReader.start(); |
347 | 322 |
|
348 | 323 | } |
349 | 324 | }); |
@@ -407,51 +382,4 @@ public void run() { |
407 | 382 | } |
408 | 383 | }; |
409 | 384 |
|
410 | | - private class PushingTask implements Runnable { |
411 | | - |
412 | | - @Override |
413 | | - public void run() { |
414 | | - try { |
415 | | - inputStream = getContext().getAssets().open(RAW_VIDEO_PATH); |
416 | | - } catch (IOException e) { |
417 | | - e.printStackTrace(); |
418 | | - } |
419 | | - |
420 | | - byte[] buffer = new byte[RAW_VIDEO_FRAME_SIZE]; |
421 | | - while (pushing) { |
422 | | - long start = System.nanoTime(); |
423 | | - try { |
424 | | - int read = inputStream.read(buffer); |
425 | | - while (read < 0) { |
426 | | - inputStream.reset(); |
427 | | - read = inputStream.read(buffer); |
428 | | - } |
429 | | - } catch (IOException e) { |
430 | | - e.printStackTrace(); |
431 | | - } |
432 | | - JavaI420Buffer i420Buffer = JavaI420Buffer.allocate(RAW_VIDEO_WIDTH, RAW_VIDEO_HEIGHT); |
433 | | - i420Buffer.getDataY().put(buffer, 0, i420Buffer.getDataY().limit()); |
434 | | - i420Buffer.getDataU().put(buffer, i420Buffer.getDataY().limit(), i420Buffer.getDataU().limit()); |
435 | | - i420Buffer.getDataV().put(buffer, i420Buffer.getDataY().limit() + i420Buffer.getDataU().limit(), i420Buffer.getDataV().limit()); |
436 | | - engine.pushExternalVideoFrame(new VideoFrame(i420Buffer, 0, System.nanoTime())); |
437 | | - long consume = System.nanoTime() - start; |
438 | | - |
439 | | - try { |
440 | | - Thread.sleep(Math.max(0, (RAW_VIDEO_FRAME_INTERVAL_NS - consume) / 1000 / 1000)); |
441 | | - } catch (InterruptedException e) { |
442 | | - e.printStackTrace(); |
443 | | - } |
444 | | - } |
445 | | - |
446 | | - if (inputStream != null) { |
447 | | - try { |
448 | | - inputStream.close(); |
449 | | - } catch (IOException e) { |
450 | | - e.printStackTrace(); |
451 | | - } finally { |
452 | | - inputStream = null; |
453 | | - } |
454 | | - } |
455 | | - } |
456 | | - } |
457 | 385 | } |
0 commit comments