1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mediadump;
18
19import java.io.BufferedReader;
20import java.io.File;
21import java.io.FileInputStream;
22import java.io.FileReader;
23import java.io.FilenameFilter;
24import java.lang.Integer;
25import java.nio.ByteBuffer;
26import java.nio.ShortBuffer;
27import java.util.ArrayList;
28import java.util.List;
29import java.util.Properties;
30import java.util.Random;
31import java.util.Timer;
32import java.util.TimerTask;
33
34import android.app.Activity;
35import android.content.Context;
36import android.content.Intent;
37import android.content.SharedPreferences;
38import android.graphics.Bitmap;
39import android.graphics.BitmapFactory;
40import android.graphics.Canvas;
41import android.os.Bundle;
42import android.os.Handler;
43import android.os.Message;
44import android.util.Log;
45import android.view.Gravity;
46import android.view.MotionEvent;
47import android.view.View;
48import android.widget.ImageView;
49import android.widget.LinearLayout;
50import android.widget.MediaController;
51import android.widget.MediaController.MediaPlayerControl;
52
53
54/**
55 * A simple player to display the raw rgb files that are generated from
56 * VideDumpView class. It reads the "/sdcard/mediadump/prop.xml" to get
57 * the meta data such as width, height, frame rate, and bytes per pixel.
58 */
59public class RgbPlayerActivity extends Activity {
60
61    @Override
62    protected void onCreate(Bundle savedInstanceState) {
63        super.onCreate(savedInstanceState);
64
65        setContentView(new RgbView(this));
66    }
67
68    private static class RgbView extends View implements MediaPlayerControl {
69        private static final String TAG = "RgbView";
70        private Bitmap mBitmap;
71        private int mStartX = 0;
72        private int mStartY = 0;
73        private int mWidth = 0;
74        private int mHeight = 0;
75        private int mBytesPerPixel = 0;
76        private int mBytesPerLine = 0;
77        private int mBytesPerImage = 0;
78        private byte[] mImageBytes;
79        private ByteBuffer mFlipBuf;
80
81        private int mFrameRate = 0;
82
83        private MediaController mMediaController;
84        private boolean mMediaControllerAttached;
85        private boolean mIsPlaying = false;
86        private int mImageIndex = 0;
87        private List<String> mImageList;
88        private Timer mTimer;
89        private TimerTask mImageTask = new TimerTask() {
90            @Override
91            public void run() {
92                if (mIsPlaying) {
93                    mImageIndex++;
94                    LoadImage();
95                }
96            }
97        };
98        private Handler mHandler = new Handler() {
99            @Override
100            public void handleMessage(Message msg) {
101                super.handleMessage(msg);
102                invalidate();
103            }
104        };
105
106
107        public RgbView(Context context) {
108            super(context);
109
110            // read properties
111            Properties prop = new Properties();
112            try {
113                prop.loadFromXML(new FileInputStream("/sdcard/mediadump/prop.xml"));
114            } catch (java.io.IOException e) {
115                Log.e(TAG, e.getMessage(), e);
116            }
117
118            try {
119                mStartX = Integer.parseInt(prop.getProperty("startX"));
120                mStartY = Integer.parseInt(prop.getProperty("startY"));
121                mWidth = Integer.parseInt(prop.getProperty("width"));
122                mHeight = Integer.parseInt(prop.getProperty("height"));
123                mBytesPerPixel = Integer.parseInt(prop.getProperty("bytesPerPixel"));
124                mFrameRate = Integer.parseInt(prop.getProperty("frameRate"));
125            } catch (java.lang.NumberFormatException e) {
126                Log.e(TAG, e.getMessage(), e);
127            }
128
129            mBytesPerLine = mWidth * mBytesPerPixel;
130            mBytesPerImage = mHeight * mBytesPerLine;
131            mFlipBuf = ByteBuffer.allocate(mBytesPerImage);
132            mBitmap = Bitmap.createBitmap(mWidth, mHeight,
133                                          mBytesPerPixel == 2
134                                          ? Bitmap.Config.RGB_565
135                                          : Bitmap.Config.ARGB_8888);
136
137            mImageList = new ArrayList<String>();
138            try {
139                BufferedReader reader = new BufferedReader(
140                    new FileReader("/sdcard/mediadump/images.lst"));
141                String line;
142                while ((line = reader.readLine()) != null) {
143                    mImageList.add(line);
144                }
145                reader.close();
146            } catch (java.io.IOException e) {
147                Log.e(TAG, e.getMessage(), e);
148            }
149
150            mMediaController = new MediaController(context);
151            mTimer = new Timer();
152            LoadImage();
153        }
154
155        private void attachMediaController() {
156            if (mMediaController != null) {
157                if (!mMediaControllerAttached) {
158                    mMediaController.setMediaPlayer(this);
159                    View anchorView = this.getParent() instanceof View ?
160                            (View)this.getParent() : this;
161                    mMediaController.setAnchorView(anchorView);
162                    mMediaController.setEnabled(true);
163                    mMediaControllerAttached = true;
164                    mTimer.scheduleAtFixedRate(mImageTask, 0, 1000 / mFrameRate);
165                }
166                mMediaController.show();
167            }
168        }
169
170        @Override
171        public boolean onTouchEvent(MotionEvent event) {
172            attachMediaController();
173            return true;
174        }
175
176        private void LoadImage() {
177            try {
178                if (mImageIndex < 0 || mImageIndex >= mImageList.size()) {
179                    mImageIndex = 0;
180                    mIsPlaying = false;
181                }
182
183                String filename = mImageList.get(mImageIndex);
184
185                FileInputStream in = new FileInputStream(filename);
186                mImageBytes = new byte[mBytesPerImage];
187                in.read(mImageBytes);
188            } catch (Exception e) {
189                Log.e("Error reading file", e.toString());
190            }
191
192            // Flip the image vertically since the image from MediaDump is
193            // upside down.
194            for (int i = mHeight - 1; i >= 0; i--) {
195                mFlipBuf.put(mImageBytes, i * mBytesPerLine, mBytesPerLine);
196            }
197            mFlipBuf.rewind();
198            mBitmap.copyPixelsFromBuffer(mFlipBuf);
199            mFlipBuf.rewind();
200            mHandler.sendEmptyMessage(0);
201        }
202
203        @Override
204        protected void onDraw(Canvas canvas) {
205            canvas.drawBitmap(mBitmap, mStartX, mStartY, null);
206        }
207
208        public boolean canPause() {
209            return true;
210        }
211
212        public boolean canSeekBackward() {
213            return true;
214        }
215
216        public boolean canSeekForward() {
217            return true;
218        }
219
220        public int getBufferPercentage() {
221            return 1;
222        }
223
224        public int getCurrentPosition() {
225            return mImageIndex * 1000 / mFrameRate;
226        }
227
228        public int getDuration() {
229            return mImageList.size() * 1000 / mFrameRate;
230        }
231
232        public boolean isPlaying() {
233            return mIsPlaying;
234        }
235
236        public void pause() {
237            mIsPlaying = false;
238        }
239
240        public void seekTo(int pos) {
241            mImageIndex = pos * mFrameRate / 1000;
242        }
243
244        public void start() {
245            mIsPlaying = true;
246        }
247
248        @Override
249        public int getAudioSessionId() {
250            return 0;
251        }
252    }
253
254}
255