├── .gitignore ├── README.md ├── assets ├── sample1.png ├── sample2.png └── sample3.png ├── library ├── AndroidManifest.xml ├── LICENSE.txt ├── ant.properties ├── build.xml ├── proguard-project.txt ├── project.properties └── src │ └── com │ └── dd │ └── crop │ └── TextureVideoView.java └── sample ├── AndroidManifest.xml ├── ant.properties ├── build.xml ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── layout │ └── main.xml └── values │ └── strings.xml └── src └── com └── dd └── sample └── crop └── SampleActivity.java /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | 22 | # IDEA project files 23 | *.iml 24 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :small_red_triangle: **Before using this library, read information below** :small_red_triangle: 2 | ``` 3 | This library is not more supported. 4 | If you want to add new feature or fix a bug, grab source code and do it. If you think your 5 | fix or feature would be useful to other developers, I can add link of your repository to 6 | this README file. Use following e-mail to contact me: dmytrodanylyk@gmail.com 7 | Thank you for using my libraries. 8 | 9 | ``` 10 | 11 | ## Preview 12 | 13 | 14 | 15 | 16 | 17 | ## Description 18 | 19 | [`TextureVideoView`](/library/src/com/dd/crop/TextureVideoView.java) is custom view based on android [`TextureView`](http://developer.android.com/reference/android/view/TextureView.html) which gives you ability easily play and crop video. It's very similar to [`ImageView#setScaleType`](http://developer.android.com/reference/android/widget/ImageView.html#setScaleType(android.widget.ImageView.ScaleType)) 20 | 21 | Crop modes: 22 | 23 | - TOP 24 | - CENTER_CROP 25 | - BOTTOM 26 | 27 | ## Usage 28 | 29 | Include library module to your project or copy [`TextureVideoView`](/library/src/com/dd/crop/TextureVideoView.java) class to your package. 30 | 31 | 32 | ```xml 33 | 37 | ``` 38 | 39 | ```java 40 | TextureVideoView cropTextureView = (TextureVideoView) findViewById(R.id.cropTextureView); 41 | // Use `setScaleType` method to crop video 42 | cropTextureView.setScaleType(TextureVideoView.ScaleType.TOP); 43 | // Use `setDataSource` method to set data source, this could be url, assets folder or path 44 | cropTextureView.setDataSource("http://www.w3schools.com/html/mov_bbb.mp4"); 45 | cropTextureView.play(); 46 | ``` 47 | 48 | ## How it works? 49 | 50 | Read [Texture View - Video Cropping](http://goo.gl/WAikcl) Article 51 | 52 | ## API 53 | 54 | ver 1.0 55 | 56 | ```java 57 | 58 | /** 59 | * Play or resume video. Video will be played as soon as view is available and media player is 60 | * prepared. 61 | * 62 | * If video is stopped or ended and play() method was called, video will start over. 63 | */ 64 | TextureVideoView.play() 65 | 66 | /** 67 | * Pause video. If video is already paused, stopped or ended nothing will happen. 68 | */ 69 | TextureVideoView.pause() 70 | 71 | /** 72 | * Stop video (pause and seek to beginning). If video is already stopped or ended nothing will 73 | * happen. 74 | */ 75 | TextureVideoView.stop() 76 | 77 | /** 78 | * Sets the data source (file-path or http/rtsp URL) to use. 79 | */ 80 | TextureVideoView.setDataSource(String) 81 | 82 | /** 83 | * Sets the data source as a content Uri. 84 | */ 85 | TextureVideoView.setDataSource(Context, Uri) 86 | 87 | /** 88 | * Sets the data source (FileDescriptor) to use. 89 | */ 90 | TextureVideoView.setDataSource(AssetFileDescriptor) 91 | 92 | /** 93 | * Sets the player to be looping or non-looping. 94 | */ 95 | TextureVideoView.setLooping(boolean) 96 | 97 | /** 98 | * Seeks to specified time position. (milliseconds) 99 | */ 100 | TextureVideoView.seekTo(int) 101 | 102 | /** 103 | * Gets the duration of the file. 104 | */ 105 | TextureVideoView.getDuration() 106 | 107 | /** 108 | * Listener trigger `onVideoPrepared` and `onVideoEnd` events 109 | */ 110 | TextureVideoView.setListener(MediaPlayerListener) 111 | ``` 112 | 113 | ## License 114 | 115 | ``` 116 | The MIT License (MIT) 117 | 118 | Copyright (c) 2014 Danylyk Dmytro 119 | 120 | Permission is hereby granted, free of charge, to any person obtaining a copy 121 | of this software and associated documentation files (the "Software"), to deal 122 | in the Software without restriction, including without limitation the rights 123 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 124 | copies of the Software, and to permit persons to whom the Software is 125 | furnished to do so, subject to the following conditions: 126 | 127 | The above copyright notice and this permission notice shall be included in all 128 | copies or substantial portions of the Software. 129 | 130 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 131 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 132 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 133 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 134 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 135 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 136 | SOFTWARE. 137 | ``` 138 | -------------------------------------------------------------------------------- /assets/sample1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmytrodanylyk/video-crop/ba9ff500fd780ce02f4705ff8292de8675bb1564/assets/sample1.png -------------------------------------------------------------------------------- /assets/sample2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmytrodanylyk/video-crop/ba9ff500fd780ce02f4705ff8292de8675bb1564/assets/sample2.png -------------------------------------------------------------------------------- /assets/sample3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmytrodanylyk/video-crop/ba9ff500fd780ce02f4705ff8292de8675bb1564/assets/sample3.png -------------------------------------------------------------------------------- /library/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /library/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Danylyk Dmytro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /library/ant.properties: -------------------------------------------------------------------------------- 1 | # This file is used to override default values used by the Ant build system. 2 | # 3 | # This file must be checked into Version Control Systems, as it is 4 | # integral to the build system of your project. 5 | 6 | # This file is only used by the Ant script. 7 | 8 | # You can use this to override default values such as 9 | # 'source.dir' for the location of your java source folder and 10 | # 'out.dir' for the location of your output folder. 11 | 12 | # You can also use it define how the release builds are signed by declaring 13 | # the following properties: 14 | # 'key.store' for the location of your keystore and 15 | # 'key.alias' for the name of the key to use. 16 | # The password will be asked during the build when you use the 'release' target. 17 | 18 | -------------------------------------------------------------------------------- /library/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 55 | 56 | 68 | 69 | 70 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /library/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /library/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | android.library=true 14 | # Project target. 15 | target=android-14 16 | -------------------------------------------------------------------------------- /library/src/com/dd/crop/TextureVideoView.java: -------------------------------------------------------------------------------- 1 | package com.dd.crop; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.graphics.Matrix; 6 | import android.graphics.SurfaceTexture; 7 | import android.media.MediaPlayer; 8 | import android.net.Uri; 9 | import android.util.AttributeSet; 10 | import android.util.Log; 11 | import android.view.Surface; 12 | import android.view.TextureView; 13 | 14 | import java.io.IOException; 15 | 16 | /* 17 | * The MIT License (MIT) 18 | * 19 | * Copyright (c) 2014 Danylyk Dmytro 20 | * 21 | * Permission is hereby granted, free of charge, to any person obtaining a copy 22 | * of this software and associated documentation files (the "Software"), to deal 23 | * in the Software without restriction, including without limitation the rights 24 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | * copies of the Software, and to permit persons to whom the Software is 26 | * furnished to do so, subject to the following conditions: 27 | * 28 | * The above copyright notice and this permission notice shall be included in all 29 | * copies or substantial portions of the Software. 30 | * 31 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | * SOFTWARE. 38 | */ 39 | 40 | public class TextureVideoView extends TextureView implements TextureView.SurfaceTextureListener { 41 | 42 | // Indicate if logging is on 43 | public static final boolean LOG_ON = true; 44 | 45 | // Log tag 46 | private static final String TAG = TextureVideoView.class.getName(); 47 | 48 | private MediaPlayer mMediaPlayer; 49 | 50 | private float mVideoHeight; 51 | private float mVideoWidth; 52 | 53 | private boolean mIsDataSourceSet; 54 | private boolean mIsViewAvailable; 55 | private boolean mIsVideoPrepared; 56 | private boolean mIsPlayCalled; 57 | 58 | private ScaleType mScaleType; 59 | private State mState; 60 | 61 | public enum ScaleType { 62 | CENTER_CROP, TOP, BOTTOM 63 | } 64 | 65 | public enum State { 66 | UNINITIALIZED, PLAY, STOP, PAUSE, END 67 | } 68 | 69 | public TextureVideoView(Context context) { 70 | super(context); 71 | initView(); 72 | } 73 | 74 | public TextureVideoView(Context context, AttributeSet attrs) { 75 | super(context, attrs); 76 | initView(); 77 | } 78 | 79 | public TextureVideoView(Context context, AttributeSet attrs, int defStyle) { 80 | super(context, attrs, defStyle); 81 | initView(); 82 | } 83 | 84 | private void initView() { 85 | initPlayer(); 86 | setScaleType(ScaleType.CENTER_CROP); 87 | setSurfaceTextureListener(this); 88 | } 89 | 90 | public void setScaleType(ScaleType scaleType) { 91 | mScaleType = scaleType; 92 | } 93 | 94 | private void updateTextureViewSize() { 95 | float viewWidth = getWidth(); 96 | float viewHeight = getHeight(); 97 | 98 | float scaleX = 1.0f; 99 | float scaleY = 1.0f; 100 | 101 | if (mVideoWidth > viewWidth && mVideoHeight > viewHeight) { 102 | scaleX = mVideoWidth / viewWidth; 103 | scaleY = mVideoHeight / viewHeight; 104 | } else if (mVideoWidth < viewWidth && mVideoHeight < viewHeight) { 105 | scaleY = viewWidth / mVideoWidth; 106 | scaleX = viewHeight / mVideoHeight; 107 | } else if (viewWidth > mVideoWidth) { 108 | scaleY = (viewWidth / mVideoWidth) / (viewHeight / mVideoHeight); 109 | } else if (viewHeight > mVideoHeight) { 110 | scaleX = (viewHeight / mVideoHeight) / (viewWidth / mVideoWidth); 111 | } 112 | 113 | // Calculate pivot points, in our case crop from center 114 | int pivotPointX; 115 | int pivotPointY; 116 | 117 | switch (mScaleType) { 118 | case TOP: 119 | pivotPointX = 0; 120 | pivotPointY = 0; 121 | break; 122 | case BOTTOM: 123 | pivotPointX = (int) (viewWidth); 124 | pivotPointY = (int) (viewHeight); 125 | break; 126 | case CENTER_CROP: 127 | pivotPointX = (int) (viewWidth / 2); 128 | pivotPointY = (int) (viewHeight / 2); 129 | break; 130 | default: 131 | pivotPointX = (int) (viewWidth / 2); 132 | pivotPointY = (int) (viewHeight / 2); 133 | break; 134 | } 135 | 136 | Matrix matrix = new Matrix(); 137 | matrix.setScale(scaleX, scaleY, pivotPointX, pivotPointY); 138 | 139 | setTransform(matrix); 140 | } 141 | 142 | private void initPlayer() { 143 | if (mMediaPlayer == null) { 144 | mMediaPlayer = new MediaPlayer(); 145 | } else { 146 | mMediaPlayer.reset(); 147 | } 148 | mIsVideoPrepared = false; 149 | mIsPlayCalled = false; 150 | mState = State.UNINITIALIZED; 151 | } 152 | 153 | /** 154 | * @see android.media.MediaPlayer#setDataSource(String) 155 | */ 156 | public void setDataSource(String path) { 157 | initPlayer(); 158 | 159 | try { 160 | mMediaPlayer.setDataSource(path); 161 | mIsDataSourceSet = true; 162 | prepare(); 163 | } catch (IOException e) { 164 | Log.d(TAG, e.getMessage()); 165 | } 166 | } 167 | 168 | /** 169 | * @see android.media.MediaPlayer#setDataSource(android.content.Context, android.net.Uri) 170 | */ 171 | public void setDataSource(Context context, Uri uri) { 172 | initPlayer(); 173 | 174 | try { 175 | mMediaPlayer.setDataSource(context, uri); 176 | mIsDataSourceSet = true; 177 | prepare(); 178 | } catch (IOException e) { 179 | Log.d(TAG, e.getMessage()); 180 | } 181 | } 182 | 183 | /** 184 | * @see android.media.MediaPlayer#setDataSource(java.io.FileDescriptor) 185 | */ 186 | public void setDataSource(AssetFileDescriptor afd) { 187 | initPlayer(); 188 | 189 | try { 190 | long startOffset = afd.getStartOffset(); 191 | long length = afd.getLength(); 192 | mMediaPlayer.setDataSource(afd.getFileDescriptor(), startOffset, length); 193 | mIsDataSourceSet = true; 194 | prepare(); 195 | } catch (IOException e) { 196 | Log.d(TAG, e.getMessage()); 197 | } 198 | } 199 | 200 | private void prepare() { 201 | try { 202 | mMediaPlayer.setOnVideoSizeChangedListener( 203 | new MediaPlayer.OnVideoSizeChangedListener() { 204 | @Override 205 | public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 206 | mVideoWidth = width; 207 | mVideoHeight = height; 208 | updateTextureViewSize(); 209 | } 210 | } 211 | ); 212 | mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 213 | @Override 214 | public void onCompletion(MediaPlayer mp) { 215 | mState = State.END; 216 | log("Video has ended."); 217 | 218 | if (mListener != null) { 219 | mListener.onVideoEnd(); 220 | } 221 | } 222 | }); 223 | 224 | // don't forget to call MediaPlayer.prepareAsync() method when you use constructor for 225 | // creating MediaPlayer 226 | mMediaPlayer.prepareAsync(); 227 | 228 | // Play video when the media source is ready for playback. 229 | mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 230 | @Override 231 | public void onPrepared(MediaPlayer mediaPlayer) { 232 | mIsVideoPrepared = true; 233 | if (mIsPlayCalled && mIsViewAvailable) { 234 | log("Player is prepared and play() was called."); 235 | play(); 236 | } 237 | 238 | if (mListener != null) { 239 | mListener.onVideoPrepared(); 240 | } 241 | } 242 | }); 243 | 244 | } catch (IllegalArgumentException e) { 245 | Log.d(TAG, e.getMessage()); 246 | } catch (SecurityException e) { 247 | Log.d(TAG, e.getMessage()); 248 | } catch (IllegalStateException e) { 249 | Log.d(TAG, e.toString()); 250 | } 251 | } 252 | 253 | /** 254 | * Play or resume video. Video will be played as soon as view is available and media player is 255 | * prepared. 256 | * 257 | * If video is stopped or ended and play() method was called, video will start over. 258 | */ 259 | public void play() { 260 | if (!mIsDataSourceSet) { 261 | log("play() was called but data source was not set."); 262 | return; 263 | } 264 | 265 | mIsPlayCalled = true; 266 | 267 | if (!mIsVideoPrepared) { 268 | log("play() was called but video is not prepared yet, waiting."); 269 | return; 270 | } 271 | 272 | if (!mIsViewAvailable) { 273 | log("play() was called but view is not available yet, waiting."); 274 | return; 275 | } 276 | 277 | if (mState == State.PLAY) { 278 | log("play() was called but video is already playing."); 279 | return; 280 | } 281 | 282 | if (mState == State.PAUSE) { 283 | log("play() was called but video is paused, resuming."); 284 | mState = State.PLAY; 285 | mMediaPlayer.start(); 286 | return; 287 | } 288 | 289 | if (mState == State.END || mState == State.STOP) { 290 | log("play() was called but video already ended, starting over."); 291 | mState = State.PLAY; 292 | mMediaPlayer.seekTo(0); 293 | mMediaPlayer.start(); 294 | return; 295 | } 296 | 297 | mState = State.PLAY; 298 | mMediaPlayer.start(); 299 | } 300 | 301 | /** 302 | * Pause video. If video is already paused, stopped or ended nothing will happen. 303 | */ 304 | public void pause() { 305 | if (mState == State.PAUSE) { 306 | log("pause() was called but video already paused."); 307 | return; 308 | } 309 | 310 | if (mState == State.STOP) { 311 | log("pause() was called but video already stopped."); 312 | return; 313 | } 314 | 315 | if (mState == State.END) { 316 | log("pause() was called but video already ended."); 317 | return; 318 | } 319 | 320 | mState = State.PAUSE; 321 | if (mMediaPlayer.isPlaying()) { 322 | mMediaPlayer.pause(); 323 | } 324 | } 325 | 326 | /** 327 | * Stop video (pause and seek to beginning). If video is already stopped or ended nothing will 328 | * happen. 329 | */ 330 | public void stop() { 331 | if (mState == State.STOP) { 332 | log("stop() was called but video already stopped."); 333 | return; 334 | } 335 | 336 | if (mState == State.END) { 337 | log("stop() was called but video already ended."); 338 | return; 339 | } 340 | 341 | mState = State.STOP; 342 | if (mMediaPlayer.isPlaying()) { 343 | mMediaPlayer.pause(); 344 | mMediaPlayer.seekTo(0); 345 | } 346 | } 347 | 348 | /** 349 | * @see android.media.MediaPlayer#setLooping(boolean) 350 | */ 351 | public void setLooping(boolean looping) { 352 | mMediaPlayer.setLooping(looping); 353 | } 354 | 355 | /** 356 | * @see android.media.MediaPlayer#seekTo(int) 357 | */ 358 | public void seekTo(int milliseconds) { 359 | mMediaPlayer.seekTo(milliseconds); 360 | } 361 | 362 | /** 363 | * @see android.media.MediaPlayer#getDuration() 364 | */ 365 | public int getDuration() { 366 | return mMediaPlayer.getDuration(); 367 | } 368 | 369 | static void log(String message) { 370 | if (LOG_ON) { 371 | Log.d(TAG, message); 372 | } 373 | } 374 | 375 | private MediaPlayerListener mListener; 376 | 377 | /** 378 | * Listener trigger 'onVideoPrepared' and `onVideoEnd` events 379 | */ 380 | public void setListener(MediaPlayerListener listener) { 381 | mListener = listener; 382 | } 383 | 384 | public interface MediaPlayerListener { 385 | 386 | public void onVideoPrepared(); 387 | 388 | public void onVideoEnd(); 389 | } 390 | 391 | @Override 392 | public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { 393 | Surface surface = new Surface(surfaceTexture); 394 | mMediaPlayer.setSurface(surface); 395 | mIsViewAvailable = true; 396 | if (mIsDataSourceSet && mIsPlayCalled && mIsVideoPrepared) { 397 | log("View is available and play() was called."); 398 | play(); 399 | } 400 | } 401 | 402 | @Override 403 | public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 404 | 405 | } 406 | 407 | @Override 408 | public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 409 | return false; 410 | } 411 | 412 | @Override 413 | public void onSurfaceTextureUpdated(SurfaceTexture surface) { 414 | 415 | } 416 | } 417 | -------------------------------------------------------------------------------- /sample/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 15 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /sample/ant.properties: -------------------------------------------------------------------------------- 1 | # This file is used to override default values used by the Ant build system. 2 | # 3 | # This file must be checked into Version Control Systems, as it is 4 | # integral to the build system of your project. 5 | 6 | # This file is only used by the Ant script. 7 | 8 | # You can use this to override default values such as 9 | # 'source.dir' for the location of your java source folder and 10 | # 'out.dir' for the location of your output folder. 11 | 12 | # You can also use it define how the release builds are signed by declaring 13 | # the following properties: 14 | # 'key.store' for the location of your keystore and 15 | # 'key.alias' for the name of the key to use. 16 | # The password will be asked during the build when you use the 'release' target. 17 | 18 | -------------------------------------------------------------------------------- /sample/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 55 | 56 | 68 | 69 | 70 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /sample/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /sample/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-14 15 | android.library.reference.1=../library 16 | -------------------------------------------------------------------------------- /sample/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmytrodanylyk/video-crop/ba9ff500fd780ce02f4705ff8292de8675bb1564/sample/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmytrodanylyk/video-crop/ba9ff500fd780ce02f4705ff8292de8675bb1564/sample/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmytrodanylyk/video-crop/ba9ff500fd780ce02f4705ff8292de8675bb1564/sample/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 18 | 19 |