Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: webrtc/api/android/java/src/org/webrtc/FileVideoCapturer.java

Issue 2547483003: Move /webrtc/api/android files to /webrtc/sdk/android (Closed)
Patch Set: Fixes Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 package org.webrtc;
12
13 import android.content.Context;
14 import android.os.SystemClock;
15
16 import java.util.concurrent.TimeUnit;
17 import java.util.Timer;
18 import java.util.TimerTask;
19 import java.io.RandomAccessFile;
20 import java.io.IOException;
21
22 public class FileVideoCapturer implements VideoCapturer {
23 private interface VideoReader {
24 int getFrameWidth();
25 int getFrameHeight();
26 byte[] getNextFrame();
27 void close();
28 }
29
30 /**
31 * Read video data from file for the .y4m container.
32 */
33 private static class VideoReaderY4M implements VideoReader {
34 private final static String TAG = "VideoReaderY4M";
35 private final int frameWidth;
36 private final int frameHeight;
37 private final int frameSize;
38
39 // First char after header
40 private final long videoStart;
41
42 private static final String Y4M_FRAME_DELIMETER = "FRAME";
43
44 private final RandomAccessFile mediaFileStream;
45
46 public int getFrameWidth() {
47 return frameWidth;
48 }
49
50 public int getFrameHeight() {
51 return frameHeight;
52 }
53
54 public VideoReaderY4M(String file) throws IOException {
55 mediaFileStream = new RandomAccessFile(file, "r");
56 StringBuilder builder = new StringBuilder();
57 for (;;) {
58 int c = mediaFileStream.read();
59 if (c == -1) {
60 // End of file reached.
61 throw new RuntimeException("Found end of file before end of header for file: " + file);
62 }
63 if (c == '\n') {
64 // End of header found.
65 break;
66 }
67 builder.append((char) c);
68 }
69 videoStart = mediaFileStream.getFilePointer();
70 String header = builder.toString();
71 String[] headerTokens = header.split("[ ]");
72 int w = 0;
73 int h = 0;
74 String colorSpace = "";
75 for (String tok : headerTokens) {
76 char c = tok.charAt(0);
77 switch (c) {
78 case 'W':
79 w = Integer.parseInt(tok.substring(1));
80 break;
81 case 'H':
82 h = Integer.parseInt(tok.substring(1));
83 break;
84 case 'C':
85 colorSpace = tok.substring(1);
86 break;
87 }
88 }
89 Logging.d(TAG, "Color space: " + colorSpace);
90 if (!colorSpace.equals("420") && !colorSpace.equals("420mpeg2")) {
91 throw new IllegalArgumentException(
92 "Does not support any other color space than I420 or I420mpeg2");
93 }
94 if ((w % 2) == 1 || (h % 2) == 1) {
95 throw new IllegalArgumentException("Does not support odd width or height ");
96 }
97 frameWidth = w;
98 frameHeight = h;
99 frameSize = w * h * 3 / 2;
100 Logging.d(TAG, "frame dim: (" + w + ", " + h + ") frameSize: " + frameSize );
101 }
102
103 public byte[] getNextFrame() {
104 byte[] frame = new byte[frameSize];
105 try {
106 byte[] frameDelim = new byte[Y4M_FRAME_DELIMETER.length() + 1];
107 if (mediaFileStream.read(frameDelim) < frameDelim.length) {
108 // We reach end of file, loop
109 mediaFileStream.seek(videoStart);
110 if (mediaFileStream.read(frameDelim) < frameDelim.length) {
111 throw new RuntimeException("Error looping video");
112 }
113 }
114 String frameDelimStr = new String(frameDelim);
115 if (!frameDelimStr.equals(Y4M_FRAME_DELIMETER + "\n")) {
116 throw new RuntimeException(
117 "Frames should be delimited by FRAME plus newline, found delimter was: '"
118 + frameDelimStr + "'");
119 }
120 mediaFileStream.readFully(frame);
121 byte[] nv21Frame = new byte[frameSize];
122 nativeI420ToNV21(frame, frameWidth, frameHeight, nv21Frame);
123 return nv21Frame;
124 } catch (IOException e) {
125 throw new RuntimeException(e);
126 }
127 }
128
129 public void close() {
130 try {
131 mediaFileStream.close();
132 } catch (IOException e) {
133 Logging.e(TAG, "Problem closing file", e);
134 }
135 }
136 }
137
138 private final static String TAG = "FileVideoCapturer";
139 private final VideoReader videoReader;
140 private CapturerObserver capturerObserver;
141 private final Timer timer = new Timer();
142
143 private final TimerTask tickTask = new TimerTask() {
144 @Override
145 public void run() {
146 tick();
147 }
148 };
149
150 private int getFrameWidth() {
151 return videoReader.getFrameWidth();
152 }
153
154 private int getFrameHeight() {
155 return videoReader.getFrameHeight();
156 }
157
158 public FileVideoCapturer(String inputFile) throws IOException {
159 try {
160 videoReader = new VideoReaderY4M(inputFile);
161 } catch (IOException e) {
162 Logging.d(TAG, "Could not open video file: " + inputFile);
163 throw e;
164 }
165 }
166
167 private byte[] getNextFrame() {
168 return videoReader.getNextFrame();
169 }
170
171 public void tick() {
172 final long captureTimeNs = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsed Realtime());
173
174 byte[] frameData = getNextFrame();
175 capturerObserver.onByteBufferFrameCaptured(
176 frameData, getFrameWidth(), getFrameHeight(), 0, captureTimeNs);
177 }
178
179 @Override
180 public void initialize(SurfaceTextureHelper surfaceTextureHelper, Context appl icationContext,
181 CapturerObserver capturerObserver) {
182 this.capturerObserver = capturerObserver;
183 }
184
185 @Override
186 public void startCapture(int width, int height, int framerate) {
187 timer.schedule(tickTask, 0, 1000 / framerate);
188 }
189
190 @Override
191 public void stopCapture() throws InterruptedException {
192 timer.cancel();
193 }
194
195 @Override
196 public void changeCaptureFormat(int width, int height, int framerate) {
197 // Empty on purpose
198 }
199
200 @Override
201 public void dispose() {
202 videoReader.close();
203 }
204
205 @Override
206 public boolean isScreencast() {
207 return false;
208 }
209
210 public static native void nativeI420ToNV21(byte[] src, int width, int height, byte[] dst);
211 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698