├── .gitignore ├── COPYING.txt ├── README-libvpx.txt ├── README.md ├── app ├── build.gradle ├── libs │ └── vorbis-java-1.0.0-beta.jar └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── android │ │ └── support │ │ │ └── v4 │ │ │ └── util │ │ │ └── LruCache.java │ ├── com │ │ └── dozingcatsoftware │ │ │ ├── ebml │ │ │ ├── EBMLContainerElement.java │ │ │ ├── EBMLElement.java │ │ │ ├── EBMLElementType.java │ │ │ ├── EBMLFileWriter.java │ │ │ ├── EBMLReader.java │ │ │ ├── EBMLUtilities.java │ │ │ └── MatroskaID.java │ │ │ ├── eyeball │ │ │ ├── AboutActivity.java │ │ │ ├── CameraImageProcessor.java │ │ │ ├── ColorPickerDialog.java │ │ │ ├── ColorScheme.java │ │ │ ├── EyeballMain.java │ │ │ ├── ImageListActivity.java │ │ │ ├── MediaTabActivity.java │ │ │ ├── NewPictureJob.java │ │ │ ├── NewPictureReceiver.java │ │ │ ├── NewPictureReceiverLegacyBroadcast.java │ │ │ ├── OverlayView.java │ │ │ ├── PermissionsChecker.java │ │ │ ├── ProcessPictureOperation.java │ │ │ ├── ProcessPictureService.java │ │ │ ├── RecordingQualityPreference.java │ │ │ ├── SobelEdgeDetector.java │ │ │ ├── VideoListActivity.java │ │ │ ├── VideoPlaybackActivity.java │ │ │ ├── ViewImageActivity.java │ │ │ ├── WGPreferences.java │ │ │ ├── WGUtils.java │ │ │ └── video │ │ │ │ ├── AbstractViewMediaActivity.java │ │ │ │ ├── CombineAudioVideo.java │ │ │ │ ├── CreateVideoZipFileAsyncTask.java │ │ │ │ ├── CreateWebmAsyncTask.java │ │ │ │ ├── ImageRecorder.java │ │ │ │ ├── MediaDirectory.java │ │ │ │ ├── MediaProperties.java │ │ │ │ ├── ProcessVideoTask.java │ │ │ │ ├── VideoReader.java │ │ │ │ ├── VideoRecorder.java │ │ │ │ ├── VorbisEncoder.java │ │ │ │ └── WebMEncoder.java │ │ │ └── util │ │ │ ├── ARManager.java │ │ │ ├── AndroidUtils.java │ │ │ ├── AsyncImageLoader.java │ │ │ ├── CameraPreviewProcessingQueue.java │ │ │ ├── CameraUtils.java │ │ │ ├── FrameRateManager.java │ │ │ ├── ScaledBitmapCache.java │ │ │ ├── ShutterButton.java │ │ │ └── SingleItemProcessingQueue.java │ └── org │ │ └── openintents │ │ └── widget │ │ ├── ColorCircle.java │ │ ├── ColorSlider.java │ │ └── OnColorChangedListener.java │ ├── jni │ ├── .sobel.c.swp │ ├── .wg_video.c.swp │ ├── Android.mk │ ├── Application.mk │ ├── libvpx │ │ ├── AUTHORS │ │ ├── CHANGELOG │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── README │ │ ├── third_party │ │ │ └── libwebm │ │ │ │ ├── AUTHORS.TXT │ │ │ │ ├── Android.mk │ │ │ │ ├── LICENSE.TXT │ │ │ │ ├── PATENTS.TXT │ │ │ │ ├── README.libvpx │ │ │ │ ├── RELEASE.TXT │ │ │ │ ├── mkvmuxer.cpp │ │ │ │ ├── mkvmuxer.hpp │ │ │ │ ├── mkvmuxertypes.hpp │ │ │ │ ├── mkvmuxerutil.cpp │ │ │ │ ├── mkvmuxerutil.hpp │ │ │ │ ├── mkvparser.cpp │ │ │ │ ├── mkvparser.hpp │ │ │ │ ├── mkvreader.cpp │ │ │ │ ├── mkvreader.hpp │ │ │ │ ├── mkvwriter.cpp │ │ │ │ ├── mkvwriter.hpp │ │ │ │ └── webmids.hpp │ │ ├── tools_common.h │ │ ├── vpx │ │ │ ├── svc_context.h │ │ │ ├── vp8.h │ │ │ ├── vp8cx.h │ │ │ ├── vp8dx.h │ │ │ ├── vpx_codec.h │ │ │ ├── vpx_decoder.h │ │ │ ├── vpx_encoder.h │ │ │ ├── vpx_frame_buffer.h │ │ │ ├── vpx_image.h │ │ │ └── vpx_integer.h │ │ ├── vpx_config.h │ │ ├── vpx_ports │ │ │ └── msvc.h │ │ ├── webmenc.cc │ │ ├── webmenc.h │ │ └── y4minput.h │ ├── libvpx_prebuilt_libs │ │ ├── armeabi-v7a │ │ │ └── libvpx.a │ │ └── x86 │ │ │ └── libvpx.a │ ├── sobel.c │ ├── test_wg_video.c │ └── wg_video.c │ └── res │ ├── drawable-hdpi │ ├── btn_camera_shutter_holo.png │ ├── btn_camera_shutter_pressed_holo.png │ ├── btn_video_shutter_holo.png │ ├── btn_video_shutter_pressed_holo.png │ ├── btn_video_shutter_recording_holo.png │ ├── btn_video_shutter_recording_pressed_holo.png │ ├── ic_camera_front_white_36dp.png │ ├── ic_camera_rear_white_36dp.png │ ├── ic_help_outline_white_36dp.png │ ├── ic_pause_white_48dp.png │ ├── ic_photo_camera_white_36dp.png │ ├── ic_photo_library_white_36dp.png │ ├── ic_play_arrow_white_48dp.png │ ├── ic_settings_white_36dp.png │ ├── ic_skip_next_white_48dp.png │ ├── ic_skip_previous_white_48dp.png │ ├── ic_videocam_white_36dp.png │ ├── icon.png │ ├── mediatab_bg_selected.xml │ ├── mediatab_bg_selector.xml │ └── mediatab_bg_unselected.xml │ ├── drawable-ldpi │ └── icon.png │ ├── drawable-mdpi │ ├── btn_camera_shutter_holo.png │ ├── btn_camera_shutter_pressed_holo.png │ ├── btn_video_shutter_holo.png │ ├── btn_video_shutter_pressed_holo.png │ ├── btn_video_shutter_recording_holo.png │ ├── btn_video_shutter_recording_pressed_holo.png │ ├── ic_camera_front_white_36dp.png │ ├── ic_camera_rear_white_36dp.png │ ├── ic_help_outline_white_36dp.png │ ├── ic_pause_white_48dp.png │ ├── ic_photo_camera_white_36dp.png │ ├── ic_photo_library_white_36dp.png │ ├── ic_play_arrow_white_48dp.png │ ├── ic_settings_white_36dp.png │ ├── ic_skip_next_white_48dp.png │ ├── ic_skip_previous_white_48dp.png │ ├── ic_videocam_white_36dp.png │ └── icon.png │ ├── drawable-xhdpi │ ├── btn_camera_shutter_holo.png │ ├── btn_camera_shutter_pressed_holo.png │ ├── btn_video_shutter_holo.png │ ├── btn_video_shutter_pressed_holo.png │ ├── btn_video_shutter_recording_holo.png │ ├── btn_video_shutter_recording_pressed_holo.png │ ├── ic_camera_front_white_36dp.png │ ├── ic_camera_rear_white_36dp.png │ ├── ic_help_outline_white_36dp.png │ ├── ic_pause_white_48dp.png │ ├── ic_photo_camera_white_36dp.png │ ├── ic_photo_library_white_36dp.png │ ├── ic_play_arrow_white_48dp.png │ ├── ic_settings_white_36dp.png │ ├── ic_skip_next_white_48dp.png │ ├── ic_skip_previous_white_48dp.png │ └── ic_videocam_white_36dp.png │ ├── drawable-xxxhdpi │ ├── ic_camera_front_white_36dp.png │ ├── ic_camera_rear_white_36dp.png │ ├── ic_help_outline_white_36dp.png │ ├── ic_pause_white_48dp.png │ ├── ic_photo_camera_white_36dp.png │ ├── ic_photo_library_white_36dp.png │ ├── ic_play_arrow_white_48dp.png │ ├── ic_settings_white_36dp.png │ ├── ic_skip_next_white_48dp.png │ ├── ic_skip_previous_white_48dp.png │ └── ic_videocam_white_36dp.png │ ├── layout │ ├── about.xml │ ├── colorpicker.xml │ ├── custom_colors.xml │ ├── imagegrid.xml │ ├── imagegrid_cell.xml │ ├── imagelist.xml │ ├── imagelist_row.xml │ ├── main.xml │ ├── mediatab.xml │ ├── mediatab_bg.xml │ ├── overlay_and_controls.xml │ ├── playback.xml │ ├── videolist.xml │ └── videolist_row.xml │ ├── values-v21 │ └── styles.xml │ ├── values │ ├── arrays.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── preferences.xml ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/ 3 | .gradle/ 4 | app/.externalNativeBuild/ 5 | app/release/ 6 | build/ 7 | gen/ 8 | local.properties 9 | 10 | -------------------------------------------------------------------------------- /README-libvpx.txt: -------------------------------------------------------------------------------- 1 | WireGoggles uses the libvpx library to create WebM videos. This repository 2 | includes only the subset of libvpx headers and source needed for the NDK code in 3 | wg_video.c to build. The code needs to link against the full libvpx library, 4 | which is included as a binary for ARM and x86 in jni/libvpx_prebuilt_libs. 5 | Building an Android-compatible library from the WebM sources is somewhat tricky; 6 | this is what I did. 7 | 8 | 0. Prerequisites: I was not able to build libvpx successfully on a Mac, so I 9 | used a Linux VM (64-bit Mint Linux 17.3, but anything reasonably recent should 10 | work). You will need to install the Android NDK and the yasm assember, and 11 | possibly other compiler packages so that you can build for ARM and x86. 12 | 13 | 1. Clone the libvpx repository at https://chromium.googlesource.com/webm/libvpx 14 | (i.e. "git clone https://chromium.googlesource.com/webm/libvpx"). Building from 15 | head should work assuming there are no incompatible API changes, but if you 16 | want to use the exact code that the library in the WireGoggles repository was 17 | built against, check out revision ea48370a500537906d62544ca4ed75301d79e772. 18 | 19 | 2. Anywhere you see [NDK_PATH] in the following commands, replace it 20 | with the full path to the Android NDK directory, for example 21 | "/Users/foo/android/android-ndk-r10e". 22 | 23 | To build the ARM library, cd to libvpx and execute: 24 | 25 | =============================================================================== 26 | ./configure --target=armv7-android-gcc --sdk-path=[NDK_PATH] \ 27 | --disable-examples --disable-docs --disable-vp8-decoder --disable-vp9-decoder \ 28 | --enable-vp8-encoder --disable-vp9-encoder --disable-vp10 --disable-neon \ 29 | --disable-neon-asm --disable-runtime-cpu-detect 30 | =============================================================================== 31 | 32 | Then just execute "make", which if all goes well will produce libvpx.a in the 33 | main directory. This is the static library that goes in 34 | jni/libvpx_prebuilt_libs/armeabi-v7a. Run "make clean" before building x86. 35 | 36 | 3. x86 is trickier because we can't use the default NDK runtime. See 37 | http://stackoverflow.com/questions/28010753/android-ndk-returns-an-error-undefined-reference-to-rand 38 | 39 | Run these commands: 40 | 41 | =============================================================================== 42 | export PATH=[ANDROID_NDK_PATH]/toolchains/x86-4.8/prebuilt/linux-x86_64/bin:$PATH 43 | 44 | ASFLAGS="-D__ANDROID__" CROSS=i686-linux-android- \ 45 | LDFLAGS="--sysroot=[NDK_PATH]/platforms/android-9/arch-x86" ./configure \ 46 | --target=x86-android-gcc --sdk-path=[NDK_PATH] --disable-examples \ 47 | --disable-docs --disable-vp8-decoder --disable-vp9-decoder \ 48 | --enable-vp8-encoder --disable-vp9-encoder --disable-vp10 \ 49 | --disable-runtime-cpu-detect --disable-mmx --disable-sse --disable-sse2 \ 50 | --disable-sse3 --disable-ssse3 --disable-sse4_1 \ 51 | --extra-cflags="--sysroot=[NDK_PATH]/platforms/android-9/arch-x86" 52 | =============================================================================== 53 | 54 | Now "make" should produce the libvpx.a static library for x86. 55 | 56 | The configure commands above enable only the VP8 encoder and disble VP9 because 57 | I found that the size and quality difference between them wasn't noticeable, but 58 | VP9 is much slower to encode. If you would like to try VP9 you can change the 59 | flags to --enable-vp9-encoder and set WG_USE_VP9 to 1 in wg_video.c. 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WireGoggles 2 | 3 | As of March 2018 WireGoggles is not under active development. I may fix bugs but don't plan to add new features. 4 | [Vector Camera](https://github.com/dozingcat/VectorCamera) is its successor. 5 | 6 | WireGoggles is an Android app that displays a real-time wireframe outline of what your camera is 7 | pointing at. You can choose from several rendering styles and create your own color schemes, and 8 | save pictures and videos. 9 | 10 | This started out several years ago as a way to learn Android development. Much of the code is 11 | old and not well structured, and should not be taken as the best way to do things. 12 | 13 | WireGoggles is released under version 3 of the GPL; see [COPYING](COPYING.txt) for the license text. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | WireGoggles uses open source code from several third-party projects: 21 | 22 | - libvpx from the [WebM Project](http://www.webmproject.org/license/software/) 23 | - Color picker from [OpenIntents](https://github.com/openintents/openintents/tree/master/colorpicker/ColorPicker) 24 | - vorbis-java encoder from xiph.org 25 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "26.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.dozingcatsoftware.WireGoggles" 9 | minSdkVersion 10 10 | targetSdkVersion 24 11 | 12 | ndk { 13 | moduleName 'libvpx' 14 | abiFilters 'armeabi-v7a', 'x86' 15 | } 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 22 | } 23 | } 24 | 25 | externalNativeBuild { 26 | ndkBuild { 27 | path 'src/main/jni/Android.mk' 28 | } 29 | } 30 | } 31 | 32 | dependencies { 33 | compile files('libs/vorbis-java-1.0.0-beta.jar') 34 | } 35 | -------------------------------------------------------------------------------- /app/libs/vorbis-java-1.0.0-beta.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/libs/vorbis-java-1.0.0-beta.jar -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 20 | 23 | 24 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 44 | 45 | 48 | 49 | 50 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/ebml/EBMLContainerElement.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.ebml; 2 | 3 | import java.io.DataOutput; 4 | import java.io.IOException; 5 | import java.io.OutputStream; 6 | 7 | public class EBMLContainerElement extends EBMLElement { 8 | 9 | static byte[] UNKNOWN_LENGTH_BYTES = new byte[] {0x01, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF}; 10 | long contentSize=-1; 11 | 12 | 13 | public EBMLContainerElement(EBMLElementType elementType) { 14 | super(elementType); 15 | } 16 | 17 | public static EBMLContainerElement createWithHexID(String hexID) { 18 | return new EBMLContainerElement(EBMLElementType.elementTypeForHexString(hexID)); 19 | } 20 | 21 | // content size is stored directly in an ivar so getContentSize() is overridden, getTotalSize still works 22 | @Override 23 | public long getContentSize() { 24 | return contentSize; 25 | } 26 | 27 | public void setContentSize(long value) { 28 | contentSize = value; 29 | } 30 | 31 | public boolean isUnknownSize() { 32 | return contentSize < 0; 33 | } 34 | 35 | // overridden to write only ID and length bytes 36 | @Override 37 | public void writeToStream(OutputStream output) throws IOException { 38 | output.write(getElementType().getIDBytes()); 39 | if (isUnknownSize()) { 40 | output.write(UNKNOWN_LENGTH_BYTES); 41 | } 42 | else { 43 | output.write(EBMLUtilities.bytesForLength(getContentSize())); 44 | } 45 | } 46 | 47 | // because OutputStream doesn't implement DataOutput (interface used by RandomAccessFile), yay Java 48 | @Override 49 | public void writeToStream(DataOutput output) throws IOException { 50 | output.write(getElementType().getIDBytes()); 51 | if (isUnknownSize()) { 52 | output.write(UNKNOWN_LENGTH_BYTES); 53 | } 54 | else { 55 | output.write(EBMLUtilities.bytesForLength(getContentSize())); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/ebml/EBMLElement.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.ebml; 2 | 3 | import java.io.DataOutput; 4 | import java.io.IOException; 5 | import java.io.OutputStream; 6 | 7 | public class EBMLElement { 8 | 9 | EBMLElementType elementType; 10 | Object value; 11 | 12 | static byte[] EMPTY_BYTES = new byte[0]; 13 | 14 | public EBMLElement(EBMLElementType elementType) { 15 | this.elementType = elementType; 16 | } 17 | 18 | public static EBMLElement createWithHexID(String hexID, Object value) { 19 | EBMLElement element = new EBMLElement(EBMLElementType.elementTypeForHexString(hexID)); 20 | element.setValue(value); 21 | return element; 22 | } 23 | 24 | public long getContentSize() { 25 | return dataBytes().length; 26 | } 27 | 28 | public long getTotalSize() { 29 | long contentSize = getContentSize(); 30 | return contentSize + EBMLUtilities.numberOfBytesToEncodeLength(contentSize) + elementType.getIDLength(); 31 | } 32 | 33 | public Object getValue() { 34 | return value; 35 | } 36 | public void setValue(Object v) { 37 | value = v; 38 | } 39 | 40 | // TODO: add setDataBytes method to convert raw bytes to this element's type 41 | 42 | public EBMLElementType getElementType() { 43 | return elementType; 44 | } 45 | 46 | public byte[] dataBytes() { 47 | if (value==null) return EMPTY_BYTES; 48 | if (value instanceof byte[]) { 49 | return (byte[])value; 50 | } 51 | if (value instanceof Float) { 52 | return EBMLUtilities.dataBytesForFloat((Float)value); 53 | } 54 | if (value instanceof Double) { 55 | return EBMLUtilities.dataBytesForDouble((Double)value); 56 | } 57 | if (value instanceof Number) { 58 | return EBMLUtilities.dataBytesForLong(((Number)value).longValue()); 59 | } 60 | if (value instanceof String) { 61 | return ((String)value).getBytes(); 62 | } 63 | throw new IllegalArgumentException("Unknown value type:" + value + "(" + value.getClass() + ")"); 64 | } 65 | 66 | public void writeToStream(OutputStream output) throws IOException { 67 | output.write(this.elementType.getIDBytes()); 68 | byte[] data = this.dataBytes(); 69 | output.write(EBMLUtilities.bytesForLength(data.length)); 70 | output.write(data); 71 | } 72 | 73 | // because OutputStream doesn't implement DataOutput (interface used by RandomAccessFile), yay Java 74 | public void writeToStream(DataOutput output) throws IOException { 75 | output.write(this.elementType.getIDBytes()); 76 | byte[] data = this.dataBytes(); 77 | output.write(EBMLUtilities.bytesForLength(data.length)); 78 | output.write(data); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/ebml/EBMLElementType.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.ebml; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | public class EBMLElementType { 8 | 9 | byte[] idBytes; 10 | String idHexString; 11 | String name; 12 | 13 | public enum ValueType { 14 | CONTAINER, STRING, BINARY, UNSIGNED_INTEGER, SIGNED_INTEGER, FLOAT 15 | }; 16 | ValueType valueType = ValueType.BINARY; 17 | 18 | // Elements with IDs of 4 bytes are containers, but some with shorter IDs are as well 19 | static Set CONTAINER_IDS = new HashSet(Arrays.asList( 20 | MatroskaID.TrackEntry, MatroskaID.Audio 21 | )); 22 | 23 | // TODO: build map of known element types, with value types 24 | static ValueType valueTypeForID(String hexID) { 25 | if (hexID.length()>=8) return ValueType.CONTAINER; 26 | if (CONTAINER_IDS.contains(hexID.toLowerCase())) return ValueType.CONTAINER; 27 | return ValueType.BINARY; 28 | } 29 | 30 | public static EBMLElementType elementTypeForBytes(byte[] bytes) { 31 | EBMLElementType self = new EBMLElementType(); 32 | self.idBytes = bytes.clone(); 33 | self.idHexString = EBMLUtilities.bytesToHexString(self.idBytes); 34 | self.valueType = valueTypeForID(self.idHexString); 35 | return self; 36 | } 37 | 38 | public static EBMLElementType elementTypeForHexString(String hexString) { 39 | EBMLElementType self = new EBMLElementType(); 40 | self.idHexString = hexString.toUpperCase(); 41 | self.idBytes = EBMLUtilities.hexStringToBytes(self.idHexString); 42 | self.valueType = valueTypeForID(self.idHexString); 43 | return self; 44 | } 45 | 46 | public byte[] getIDBytes() { 47 | return idBytes.clone(); 48 | } 49 | 50 | public String getIDHexString() { 51 | return idHexString; 52 | } 53 | 54 | public int getIDLength() { 55 | return idBytes.length; 56 | } 57 | 58 | public String getName() { 59 | return name; 60 | } 61 | public void setName(String value) { 62 | name = value; 63 | } 64 | 65 | 66 | public EBMLElement createElement() { 67 | if (valueType==ValueType.CONTAINER) { 68 | return new EBMLContainerElement(this); 69 | } 70 | else { 71 | return new EBMLElement(this); 72 | } 73 | } 74 | 75 | public boolean hexIDMatches(String hexID) { 76 | return (hexID!=null && this.idHexString.equals(hexID.toUpperCase())); 77 | } 78 | 79 | @Override 80 | public boolean equals(Object other) { 81 | if (!(other instanceof EBMLElementType)) return false; 82 | return this.idHexString.equals(((EBMLElementType)other).idHexString); 83 | } 84 | 85 | @Override 86 | public int hashCode() { 87 | return this.idHexString.hashCode(); 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | return this.idHexString; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/ebml/EBMLFileWriter.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.ebml; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.io.RandomAccessFile; 7 | import java.util.Stack; 8 | 9 | public class EBMLFileWriter { 10 | 11 | // We need a random access file because typically for container elements the content size is initially unknown, so 12 | // we have to write a placeholder value (using the full 8 bytes) and go back and fill it in when we know the size. 13 | RandomAccessFile randomAccessFile; 14 | 15 | // As we write container elements, keep track of the total lengths of their sub-elements. Record the starting position 16 | // so that when the container is closed, we can go back and write the correct length. 17 | static class ContainerStackEntry { 18 | public EBMLContainerElement container; 19 | public long startPosition; 20 | public long contentLength = 0; 21 | } 22 | 23 | Stack containerElementStack = new Stack(); 24 | 25 | public EBMLFileWriter(String path) throws FileNotFoundException { 26 | File f = new File(path); 27 | if (f.exists()) f.delete(); 28 | randomAccessFile = new RandomAccessFile(f, "rw"); 29 | } 30 | 31 | public void writeElement(EBMLElement element) throws IOException { 32 | element.writeToStream(randomAccessFile); 33 | // update parent container with the total length of this element 34 | if (!containerElementStack.empty()) { 35 | ContainerStackEntry parent = containerElementStack.peek(); 36 | parent.contentLength += element.getTotalSize(); 37 | } 38 | } 39 | 40 | public void writeElement(String hexID, Object value) throws IOException { 41 | writeElement(EBMLElement.createWithHexID(hexID, value)); 42 | } 43 | 44 | public void startContainerElement(EBMLContainerElement container) throws IOException { 45 | ContainerStackEntry stackEntry = new ContainerStackEntry(); 46 | stackEntry.container = container; 47 | stackEntry.startPosition = randomAccessFile.getFilePointer(); 48 | containerElementStack.push(stackEntry); 49 | 50 | container.writeToStream(randomAccessFile); 51 | } 52 | 53 | public void startContainerElement(String hexID) throws IOException { 54 | startContainerElement(EBMLContainerElement.createWithHexID(hexID)); 55 | } 56 | 57 | public EBMLContainerElement endContainerElement() throws IOException { 58 | ContainerStackEntry stackEntry = containerElementStack.pop(); 59 | // the length should be correct, so go back to the length placeholder and write the correct length 60 | long currentPosition = randomAccessFile.getFilePointer(); 61 | // The location to write the length is the saved start position, plus the number of ID bytes, plus 1 for the 62 | // leading 01 length byte (which indicates that the length is stored in the next 7 bytes). 63 | long lengthPosition = stackEntry.startPosition + stackEntry.container.getElementType().getIDLength() + 1; 64 | randomAccessFile.seek(lengthPosition); 65 | // EBMLElementContainer.writeElement always writes 8 bytes for the length as a placeholder, first byte is always 01 66 | byte[] lengthBytes = EBMLUtilities.dataBytesForLong(stackEntry.contentLength, 7); 67 | randomAccessFile.write(lengthBytes); 68 | 69 | randomAccessFile.seek(currentPosition); 70 | 71 | // if there's a parent container of this container, update its content size. 72 | // The total size of this container its content size, plus the length of its ID, plus 8 length bytes 73 | if (!containerElementStack.empty()) { 74 | ContainerStackEntry parent = containerElementStack.peek(); 75 | parent.contentLength += stackEntry.contentLength + stackEntry.container.getElementType().getIDLength() + 8; 76 | } 77 | 78 | stackEntry.container.setContentSize(stackEntry.contentLength); 79 | return stackEntry.container; 80 | } 81 | 82 | public void close() throws IOException { 83 | randomAccessFile.close(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/ebml/EBMLReader.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.ebml; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Stack; 6 | 7 | public class EBMLReader { 8 | 9 | public static interface Delegate { 10 | public void parsedEBMLElement(EBMLElement element); 11 | public void startedEBMLContainerElement(EBMLContainerElement element); 12 | public void finishedEBMLContainerElement(EBMLContainerElement element); 13 | public void finishedEBMLStream(); 14 | } 15 | 16 | InputStream input; 17 | long bytesRead; 18 | Delegate delegate; 19 | 20 | static class ContainerStackEntry { 21 | public EBMLContainerElement container; 22 | public long endPosition; 23 | } 24 | 25 | Stack containerStack; 26 | 27 | public EBMLReader(InputStream input, Delegate delegate) { 28 | this.input = input; 29 | this.delegate = delegate; 30 | } 31 | 32 | public void go() { 33 | containerStack = new Stack(); 34 | 35 | while (true) { 36 | try { 37 | byte[] idBytes = readElementID(); 38 | if (idBytes==null) break; 39 | EBMLElement element = EBMLElementType.elementTypeForBytes(idBytes).createElement(); 40 | // capture number of bytes storing the length, so we can increment bytesRead correctly 41 | int[] numLengthBytes = new int[1]; 42 | long length = EBMLUtilities.readEncodedLength(input, numLengthBytes); 43 | this.bytesRead += numLengthBytes[0]; 44 | if (length<=0) break; 45 | if (element instanceof EBMLContainerElement) { 46 | EBMLContainerElement container = (EBMLContainerElement)element; 47 | container.setContentSize(length); 48 | delegate.startedEBMLContainerElement(container); 49 | // push onto container stack with ending position 50 | ContainerStackEntry stackEntry = new ContainerStackEntry(); 51 | stackEntry.container = container; 52 | stackEntry.endPosition = this.bytesRead + container.getContentSize(); 53 | containerStack.push(stackEntry); 54 | } 55 | else { 56 | byte[] value = readBytes((int)length); 57 | element.setValue(value); 58 | delegate.parsedEBMLElement(element); 59 | // check for closed containers 60 | while (!containerStack.empty()) { 61 | ContainerStackEntry stackEntry = containerStack.peek(); 62 | if (bytesRead >= stackEntry.endPosition) { 63 | containerStack.pop(); 64 | delegate.finishedEBMLContainerElement(stackEntry.container); 65 | } 66 | else { 67 | break; 68 | } 69 | } 70 | } 71 | } 72 | catch(Exception ex) { 73 | break; 74 | } 75 | } 76 | delegate.finishedEBMLStream(); 77 | } 78 | 79 | 80 | int readByte() throws IOException { 81 | int value = input.read(); 82 | if (value!=-1) bytesRead++; 83 | return value; 84 | } 85 | 86 | byte[] readBytes(int numBytes) throws IOException { 87 | byte[] bytes = new byte[numBytes]; 88 | int nbytes = 0; 89 | while (nbytes < numBytes) { 90 | int result = this.input.read(bytes, nbytes, bytes.length-nbytes); 91 | if (result==-1) return null; 92 | nbytes += result; 93 | } 94 | this.bytesRead += numBytes; 95 | return bytes; 96 | } 97 | 98 | public byte[] readElementID() { 99 | try { 100 | int first = readByte(); 101 | if (first==-1) return null; 102 | if (first >= 0x80) { 103 | // one-byte ID 104 | return new byte[] {(byte)first}; 105 | } 106 | 107 | int second = readByte(); 108 | if (second==-1) return null; 109 | if (first >= 0x40) { 110 | // two-byte ID 111 | return new byte[] {(byte)first, (byte)second}; 112 | } 113 | 114 | int third = readByte(); 115 | if (third==-1) return null; 116 | if (first >= 0x20) { 117 | // three-byte ID 118 | return new byte[] {(byte)first, (byte)second, (byte)third}; 119 | } 120 | 121 | // must be four bytes 122 | int fourth = readByte(); 123 | if (fourth==-1) return null; 124 | return new byte[] {(byte)first, (byte)second, (byte)third, (byte)fourth}; 125 | } 126 | catch(Exception ex) { 127 | throw new RuntimeException(ex); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/ebml/EBMLUtilities.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.ebml; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | public class EBMLUtilities { 7 | 8 | static String HEX_CHARS_STRING = "0123456789ABCDEF"; 9 | static char[] HEX_CHARS = HEX_CHARS_STRING.toCharArray(); 10 | 11 | public static String bytesToHexString(byte[] bytes) { 12 | StringBuilder sb = new StringBuilder(2*bytes.length); 13 | for(int i=0; i>>4) & 0x0F]); 15 | sb.append(HEX_CHARS[bytes[i] & 0x0F]); 16 | } 17 | return sb.toString(); 18 | } 19 | 20 | public static byte[] hexStringToBytes(String hexString) { 21 | if (hexString.length()%2!=0) throw new IllegalArgumentException("Hex string length must be even: " + hexString); 22 | byte[] bytes = new byte[hexString.length() / 2]; 23 | char[] ucChars = hexString.toUpperCase().toCharArray(); 24 | for(int i=0; i 10000001 = 0x81 38 | * 126 -> 11111110 = 0xFE 39 | * 127 -> 01000000 01111111 = 0x40, 0x7F (can't fit in one byte because EBML reserves length bytes of all 1s) 40 | * 128 -> 01000000 10000000 = 0x40, 0x80 41 | * 42 | */ 43 | public static byte[] bytesForLength(long length) { 44 | byte[] bytes = new byte[numberOfBytesToEncodeLength(length)]; 45 | // put a leading 1 in the encoded bytes, shifted left by 7*size. This will create the correct number of leading zeros. 46 | long mask = 1L << (7*bytes.length); 47 | long value = mask | length; 48 | // big-endian, least significant bytes at end of array 49 | for(int i=bytes.length-1; i>=0; i--) { 50 | bytes[i] = (byte)(value & 0xFF); 51 | value >>= 8; 52 | } 53 | return bytes; 54 | } 55 | 56 | public static int numberOfBytesToEncodeLength(long length) { 57 | if (length<0) throw new IllegalArgumentException("Length is negative: " + length); 58 | if (length < (1<<7 - 1)) return 1; 59 | if (length < (1<<14 - 1)) return 2; 60 | if (length < (1<<21 - 1)) return 3; 61 | if (length < (1<<28 - 1)) return 4; 62 | if (length < (1<<35 - 1)) return 5; 63 | if (length < (1<<42 - 1)) return 6; 64 | if (length < (1<<49 - 1)) return 7; 65 | if (length < (1<<56 - 1)) return 8; 66 | throw new IllegalArgumentException("Length exceeds maximum: " + length); 67 | } 68 | 69 | // bytesReadOut is optional output parameter that will have the total number of bytes read stored at index 0 70 | public static long readEncodedLength(InputStream input, int[] bytesReadOut) { 71 | try { 72 | int lbyte = input.read(); 73 | if (lbyte==-1) return -1; 74 | if (lbyte==0) throw new IllegalStateException("First length byte is 0"); 75 | // there will always be 24 extra leading zeros from the first 3 bytes 76 | int nbytes = 1 + Integer.numberOfLeadingZeros(lbyte) - 24; 77 | 78 | // start with the first byte with the leading 1 masked out 79 | long value = lbyte ^ Integer.highestOneBit(lbyte); 80 | // read successive bytes, shifting current value each time (big-endian, most significant bytes first) 81 | for(int i=1; i>>= 8; 108 | } 109 | return bytes; 110 | } 111 | 112 | public static byte[] dataBytesForLong(long value) { 113 | return dataBytesForLong(value, 1); 114 | } 115 | 116 | public static long longForDataBytes(byte[] bytes) { 117 | long value = 0; 118 | for(int i=0; i imageDirectories; 31 | List> imageDirectoryMaps; 32 | 33 | GridView gridView; 34 | int selectedGridIndex; 35 | 36 | // A cache of scaled Bitmaps for the image files, so we can avoid reloading them as the user scrolls. 37 | ScaledBitmapCache bitmapCache; 38 | AsyncImageLoader imageLoader = new AsyncImageLoader(); 39 | 40 | @Override 41 | public void onCreate(Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.imagegrid); 44 | 45 | bitmapCache = new ScaledBitmapCache(this, ScaledBitmapCache.createIdentityLocator()); 46 | 47 | gridView = (GridView) findViewById(R.id.gridview); 48 | gridView.setOnItemClickListener(new OnItemClickListener() { 49 | @Override 50 | public void onItemClick(AdapterView parent, View view, int position, long id) { 51 | selectedGridIndex = position; 52 | ViewImageActivity.startActivityWithImageDirectory(ImageListActivity.this, imageDirectories.get(position).getPath()); 53 | } 54 | }); 55 | } 56 | 57 | @Override public void onResume() { 58 | super.onResume(); 59 | readImageThumbnails(); 60 | displayGrid(); 61 | } 62 | 63 | void readImageThumbnails() { 64 | imageDirectories = MediaDirectory.videoDirectoriesInDirectory(WGUtils.savedImageDirectory); 65 | imageDirectoryMaps = new ArrayList>(); 66 | for(MediaDirectory vd : imageDirectories) { 67 | Map dmap = new HashMap(); 68 | dmap.put("thumbnailURI", Uri.fromFile(new File(vd.thumbnailFilePath()))); 69 | imageDirectoryMaps.add(dmap); 70 | } 71 | } 72 | 73 | void displayGrid() { 74 | SimpleAdapter adapter = new SimpleAdapter(this, imageDirectoryMaps, 75 | R.layout.imagegrid_cell, 76 | new String[] {"thumbnailURI"}, 77 | new int[] {R.id.grid_image}); 78 | adapter.setViewBinder(new SimpleAdapter.ViewBinder() { 79 | @Override 80 | public boolean setViewValue(View view, Object data, String textRepresentation) { 81 | Uri imageUri = (Uri)data; 82 | imageLoader.loadImageIntoViewAsync(bitmapCache, imageUri, (ImageView)view, CELL_WIDTH, CELL_HEIGHT, getResources()); 83 | return true; 84 | } 85 | }); 86 | gridView.setAdapter(adapter); 87 | 88 | // show text message if no images available 89 | View noImagesView = findViewById(R.id.noImagesTextView); 90 | noImagesView.setVisibility(imageDirectoryMaps.size()>0 ? View.GONE : View.VISIBLE); 91 | 92 | System.gc(); // seems to avoid OutOfMemoryErrors when selecting image after deleting earlier image 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/MediaTabActivity.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import com.dozingcatsoftware.WireGoggles.R; 4 | 5 | import android.app.TabActivity; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.widget.TabHost; 12 | import android.widget.TextView; 13 | 14 | public class MediaTabActivity extends TabActivity { 15 | 16 | public static Intent startActivity(Context parent, boolean showVideo) { 17 | Intent intent = new Intent(parent, MediaTabActivity.class); 18 | if (showVideo) { 19 | intent.putExtra("video", true); 20 | } 21 | parent.startActivity(intent); 22 | return intent; 23 | } 24 | 25 | 26 | @Override public void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | 29 | TabHost tabHost = getTabHost(); 30 | addTab(tabHost, "Pictures", ImageListActivity.class); 31 | addTab(tabHost, "Videos", VideoListActivity.class); 32 | 33 | // start on video tab if requested 34 | if (this.getIntent().getBooleanExtra("video", false)) { 35 | tabHost.setCurrentTab(1); 36 | } 37 | } 38 | 39 | TabHost.TabSpec addTab(TabHost tabHost, String label, Class activityClass) { 40 | Intent tabIntent = (new Intent()).setClass(this, activityClass); 41 | View tabView = createTabView(label); 42 | TabHost.TabSpec tabSpec = tabHost.newTabSpec(label).setIndicator(tabView).setContent(tabIntent); 43 | tabHost.addTab(tabSpec); 44 | return tabSpec; 45 | } 46 | 47 | View createTabView(String label) { 48 | View view = LayoutInflater.from(this).inflate(R.layout.mediatab_bg, null); 49 | TextView tv = (TextView) view.findViewById(R.id.tabsText); 50 | tv.setText(label); 51 | return view; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/NewPictureReceiver.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Build; 7 | import android.util.Log; 8 | 9 | public class NewPictureReceiver extends BroadcastReceiver { 10 | 11 | @Override public void onReceive(Context context, Intent intent) { 12 | // On Android N and later we use a JobService and shouldn't get this notification. 13 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 14 | return; 15 | } 16 | Log.i("NewPictureReceiver", "Got picture: " + intent.getData()); 17 | try { 18 | (new ProcessPictureOperation()).processPicture(context, intent.getData()); 19 | } 20 | catch(Exception ex) { 21 | Log.e("NewPictureReceiver", "Error saving picture", ex); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/NewPictureReceiverLegacyBroadcast.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | /** 4 | * This class exists only to handle the undocumented com.android.camera.NEW_PICTURE 5 | * broadcast intent sent by the camera app in Android verions before 4.0. 6 | */ 7 | public class NewPictureReceiverLegacyBroadcast extends NewPictureReceiver { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/PermissionsChecker.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import android.Manifest; 4 | import android.annotation.TargetApi; 5 | import android.app.Activity; 6 | import android.content.pm.PackageManager; 7 | 8 | @TargetApi(23) 9 | public class PermissionsChecker { 10 | public static final int CAMERA_AND_STORAGE_REQUEST_CODE = 1001; 11 | public static final int STORAGE_FOR_PHOTO_REQUEST_CODE = 1002; 12 | public static final int STORAGE_FOR_LIBRARY_REQUEST_CODE = 1003; 13 | public static final int STORAGE_FOR_CONVERT_PICTURE_REQUEST_CODE = 1004; 14 | public static final int RECORD_AUDIO_FOR_VIDEO_REQUEST_CODE = 1005; 15 | 16 | static boolean hasPermission(Activity activity, String perm) { 17 | return activity.checkSelfPermission(perm) == PackageManager.PERMISSION_GRANTED; 18 | } 19 | 20 | public static boolean hasCameraPermission(Activity activity) { 21 | return hasPermission(activity, Manifest.permission.CAMERA); 22 | } 23 | 24 | public static boolean hasRecordAudioPermission(Activity activity) { 25 | return hasPermission(activity, Manifest.permission.RECORD_AUDIO); 26 | } 27 | 28 | public static boolean hasStoragePermission(Activity activity) { 29 | return hasPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) && 30 | hasPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); 31 | } 32 | 33 | public static void requestCameraAndStoragePermissions(Activity activity) { 34 | activity.requestPermissions( 35 | new String[] { 36 | Manifest.permission.CAMERA, 37 | Manifest.permission.RECORD_AUDIO, 38 | Manifest.permission.READ_EXTERNAL_STORAGE, 39 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 40 | }, 41 | CAMERA_AND_STORAGE_REQUEST_CODE); 42 | } 43 | 44 | public static void requestStoragePermissionsToTakePhoto(Activity activity) { 45 | activity.requestPermissions( 46 | new String[] { 47 | Manifest.permission.READ_EXTERNAL_STORAGE, 48 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 49 | }, 50 | STORAGE_FOR_PHOTO_REQUEST_CODE); 51 | } 52 | 53 | public static void requestStoragePermissionsToGoToLibrary(Activity activity) { 54 | activity.requestPermissions( 55 | new String[] { 56 | Manifest.permission.READ_EXTERNAL_STORAGE, 57 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 58 | }, 59 | STORAGE_FOR_LIBRARY_REQUEST_CODE); 60 | } 61 | 62 | public static void requestStoragePermissionsToConvertPicture(Activity activity) { 63 | activity.requestPermissions( 64 | new String[] { 65 | Manifest.permission.READ_EXTERNAL_STORAGE, 66 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 67 | }, 68 | STORAGE_FOR_CONVERT_PICTURE_REQUEST_CODE); 69 | } 70 | 71 | public static void requestRecordAudioPermissionForVideo(Activity activity) { 72 | activity.requestPermissions( 73 | new String[] { 74 | Manifest.permission.RECORD_AUDIO, 75 | }, 76 | RECORD_AUDIO_FOR_VIDEO_REQUEST_CODE); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/ProcessPictureService.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.IBinder; 6 | 7 | public class ProcessPictureService extends Service { 8 | 9 | @Override 10 | public IBinder onBind(Intent arg0) { 11 | return null; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/RecordingQualityPreference.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import com.dozingcatsoftware.eyeball.video.VideoRecorder; 4 | 5 | import android.content.Context; 6 | import android.preference.ListPreference; 7 | import android.util.AttributeSet; 8 | 9 | /** Subclass of ListPreference to handle setting summary and item display strings 10 | * according to resolution passed to parent PreferenceActivity. 11 | */ 12 | public class RecordingQualityPreference extends ListPreference { 13 | 14 | int width; 15 | int height; 16 | 17 | public RecordingQualityPreference(Context context, AttributeSet attributeSet) { 18 | super(context, attributeSet); 19 | } 20 | 21 | public void updateDisplaySize(String[] baseLabels, int newWidth, int newHeight) { 22 | this.width = newWidth; 23 | this.height = newHeight; 24 | 25 | CharSequence[] entryValues = this.getEntryValues(); 26 | String[] labelsWithResolution = new String[baseLabels.length]; 27 | for(int i=0; i 0 && this.height > 0) { 54 | resolutionSuffix = String.format(" (%dx%d)", 55 | VideoRecorder.scaledSizeForQuality(this.width, quality), 56 | VideoRecorder.scaledSizeForQuality(this.height, quality)); 57 | } 58 | return qualityLabel + resolutionSuffix; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/VideoListActivity.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import java.io.File; 4 | import java.text.SimpleDateFormat; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import com.dozingcatsoftware.WireGoggles.R; 11 | import com.dozingcatsoftware.eyeball.video.MediaDirectory; 12 | import com.dozingcatsoftware.eyeball.video.MediaProperties; 13 | 14 | import android.app.ListActivity; 15 | import android.content.Intent; 16 | import android.net.Uri; 17 | import android.os.Bundle; 18 | import android.view.View; 19 | import android.widget.ListAdapter; 20 | import android.widget.ListView; 21 | import android.widget.SimpleAdapter; 22 | 23 | public class VideoListActivity extends ListActivity { 24 | 25 | List videoDirectories; 26 | List> videoDirectoryMaps; 27 | 28 | static SimpleDateFormat VIDEO_DATE_FORMAT = new SimpleDateFormat("MMM dd yyyy, HH:mm"); 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | setContentView(R.layout.videolist); 34 | 35 | buildListView(); 36 | } 37 | 38 | void buildListView() { 39 | videoDirectories = MediaDirectory.videoDirectoriesInDirectory(WGUtils.savedVideoDirectory); 40 | videoDirectoryMaps = new ArrayList>(); 41 | for(MediaDirectory vd : videoDirectories) { 42 | MediaProperties props = vd.getVideoProperties(); 43 | 44 | Map dmap = new HashMap(); 45 | dmap.put("title", VIDEO_DATE_FORMAT.format(props.dateCreated())); 46 | String mbString = String.format("%.1f", vd.videoFileSize()/1000000.0); 47 | dmap.put("info", props.durationInSeconds() + " seconds, " + mbString + "MB"); 48 | dmap.put("thumbnailURI", Uri.fromFile(new File(vd.thumbnailFilePath())).toString()); 49 | 50 | videoDirectoryMaps.add(dmap); 51 | } 52 | 53 | ListAdapter adapter = new SimpleAdapter(this, videoDirectoryMaps, 54 | R.layout.videolist_row, 55 | new String[] {"title", "info", "thumbnailURI"}, 56 | new int[] {R.id.listrow_text1, R.id.listrow_text2, R.id.listrow_image}); 57 | setListAdapter(adapter); 58 | 59 | System.gc(); // seems to avoid OutOfMemoryErrors 60 | } 61 | 62 | @Override 63 | protected void onListItemClick(ListView l, View v, int position, long id) { 64 | VideoPlaybackActivity.startActivityWithVideoDirectory(this, videoDirectories.get(position).getPath()); 65 | } 66 | 67 | @Override 68 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 69 | if (resultCode==VideoPlaybackActivity.DELETE_RESULT) { 70 | buildListView(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/WGPreferences.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import com.dozingcatsoftware.WireGoggles.R; 4 | 5 | import android.content.ComponentName; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.pm.PackageManager; 9 | import android.os.Build; 10 | import android.os.Bundle; 11 | import android.preference.ListPreference; 12 | import android.preference.Preference; 13 | import android.preference.Preference.OnPreferenceChangeListener; 14 | import android.preference.PreferenceActivity; 15 | 16 | public class WGPreferences extends PreferenceActivity { 17 | @Override protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | addPreferencesFromResource(R.xml.preferences); 20 | 21 | int width = this.getIntent().getIntExtra("width", 0); 22 | int height = this.getIntent().getIntExtra("height", 0); 23 | 24 | RecordingQualityPreference qualityPref = 25 | (RecordingQualityPreference)findPreference(getString(R.string.recordingQualityPrefsKey)); 26 | qualityPref.updateDisplaySize( 27 | getResources().getStringArray(R.array.recordingQualityLabels), width, height); 28 | 29 | // Show the description of the selected video export type. Setting android:summary="%s" 30 | // in preferences.xml does the same thing, but only on post-Gingerbread Android versions. 31 | final ListPreference videoExportPref = (ListPreference)findPreference(getString(R.string.videoExportTypePrefsKey)); 32 | videoExportPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { 33 | @Override public boolean onPreferenceChange(Preference preference, Object newValue) { 34 | updateDisplayedSummary(videoExportPref, (String) newValue); 35 | return true; 36 | } 37 | }); 38 | updateDisplayedSummary(videoExportPref, videoExportPref.getValue()); 39 | 40 | Preference autoConvertPref = getPreferenceManager().findPreference(getString(R.string.autoConvertPicturesPrefsKey)); 41 | autoConvertPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { 42 | @Override 43 | public boolean onPreferenceChange(Preference pref, Object value) { 44 | // Update broadcast receivers immediately so the change takes effect even if the 45 | // user doesn't go back to the main activity. 46 | setAutoConvertEnabled(WGPreferences.this, Boolean.TRUE.equals(value)); 47 | return true; 48 | } 49 | }); 50 | } 51 | 52 | void updateDisplayedSummary(ListPreference pref, String value) { 53 | int index = pref.findIndexOfValue(value); 54 | if (index == -1) index = 0; 55 | pref.setSummary(pref.getEntries()[index]); 56 | } 57 | 58 | public static Intent startActivity(Context parent, int width, int height) { 59 | Intent intent = new Intent(parent, WGPreferences.class); 60 | intent.putExtra("width", width); 61 | intent.putExtra("height", height); 62 | // don't return to preferences screen if the user goes home 63 | intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 64 | parent.startActivity(intent); 65 | return intent; 66 | } 67 | 68 | /** 69 | * Sets whether pictures saved by the camera app should automatically be converted via the 70 | * NewPictureReceiver broadcast receiver, or the NewPictureJob service in Android N or later. 71 | */ 72 | public static void setAutoConvertEnabled(Context context, boolean enabled) { 73 | // For N and above, schedule or cancel a JobService. 74 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 75 | if (enabled) { 76 | NewPictureJob.scheduleJob(context); 77 | } 78 | else { 79 | NewPictureJob.cancelJob(context); 80 | } 81 | } 82 | else { 83 | boolean receiverEnabled = false; 84 | boolean legacyReceiverEnabled = false; 85 | if (enabled) { 86 | try { 87 | // Android 4.0 and later have a Camera.ACTION_NEW_PICTURE constant, which camera 88 | // apps send after taking a picture. The NewPictureReceiver class listens for 89 | // this broadcast. Earlier Android versions send the undocumented 90 | // com.android.camera.NEW_PICTURE. This determines which receiver to enable 91 | // based on whether the ACTION_NEW_PICTURE field exists. 92 | android.hardware.Camera.class.getField("ACTION_NEW_PICTURE"); 93 | receiverEnabled = true; 94 | } 95 | catch(Exception ex) { 96 | legacyReceiverEnabled = true; 97 | } 98 | } 99 | PackageManager pm = context.getPackageManager(); 100 | pm.setComponentEnabledSetting(new ComponentName(context, NewPictureReceiver.class), 101 | receiverEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 102 | : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 103 | PackageManager.DONT_KILL_APP); 104 | pm.setComponentEnabledSetting( 105 | new ComponentName(context, NewPictureReceiverLegacyBroadcast.class), 106 | legacyReceiverEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 107 | : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 108 | PackageManager.DONT_KILL_APP); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/WGUtils.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.text.DateFormat; 6 | import java.text.SimpleDateFormat; 7 | import java.util.Date; 8 | 9 | import android.graphics.Bitmap; 10 | import android.os.Environment; 11 | 12 | public class WGUtils { 13 | 14 | static DateFormat filenameDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS"); 15 | 16 | static String baseDirectory = Environment.getExternalStorageDirectory() + File.separator + "WireGoggles"; 17 | static String savedVideoDirectory = baseDirectory + File.separator + "video"; 18 | static String savedImageDirectory = baseDirectory + File.separator + "images"; 19 | 20 | public static String savePicture(Bitmap bitmap, String path) { 21 | if (path==null) { 22 | // use base image directory plus name generated from timestamp 23 | File dir = new File(savedImageDirectory); 24 | if (!dir.exists()) { 25 | dir.mkdirs(); 26 | } 27 | if (!dir.isDirectory()) { 28 | //updateStatusTextWithFade("Unable to create directory:"+dir.getPath()); 29 | return null; 30 | } 31 | Date now = new Date(); 32 | String filename = filenameDateFormat.format(now) + ".png"; 33 | path = dir.getPath() + File.separator + filename; 34 | } 35 | else { 36 | // path provided directly, all intermediate directories must exist 37 | } 38 | 39 | try { 40 | FileOutputStream out = new FileOutputStream(path); 41 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); 42 | out.close(); 43 | return path; 44 | } 45 | catch(Exception ex) { 46 | return null; 47 | } 48 | } 49 | 50 | public static String pathForNewVideoRecording() { 51 | return savedVideoDirectory + File.separator + filenameDateFormat.format(new Date()); 52 | } 53 | 54 | public static String pathForNewImageDirectory() { 55 | return savedImageDirectory + File.separator + filenameDateFormat.format(new Date()); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/video/CreateVideoZipFileAsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball.video; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import java.util.zip.ZipEntry; 7 | import java.util.zip.ZipOutputStream; 8 | 9 | import com.dozingcatsoftware.eyeball.CameraImageProcessor; 10 | 11 | import android.graphics.Bitmap; 12 | import android.os.AsyncTask; 13 | import android.util.Log; 14 | 15 | /** 16 | * Creates a ZIP archive containing a PNG for each frame in a recorded video. 17 | */ 18 | public class CreateVideoZipFileAsyncTask extends 19 | AsyncTask { 20 | 21 | // Passed to execute in the ProcessVideoTask.Params argument. 22 | private MediaDirectory videoDirectory; 23 | private String outputPath; 24 | private CameraImageProcessor imageProcessor; 25 | 26 | @Override protected ProcessVideoTask.Result doInBackground(ProcessVideoTask.Params... params) { 27 | this.videoDirectory = params[0].videoDirectory; 28 | this.outputPath = params[0].outputPath; 29 | this.imageProcessor = params[0].imageProcessor; 30 | ProcessVideoTask.Result result = ProcessVideoTask.Result.SUCCEEDED; 31 | 32 | String tempZipFile = outputPath + ".tmp.zip"; 33 | ZipOutputStream out = null; 34 | try { 35 | out = new ZipOutputStream(new FileOutputStream(tempZipFile)); 36 | VideoReader videoReader = new VideoReader(videoDirectory.getPath()); 37 | MediaProperties videoProperties = videoReader.getVideoProperties(); 38 | int numFrames = videoDirectory.getVideoProperties().getNumberOfFrames(); 39 | int width = videoProperties.getWidth(); 40 | int height = videoProperties.getHeight(); 41 | byte[] frameData = new byte[width * height]; 42 | 43 | for (int i=1; i<=numFrames; i++) { 44 | String filename = String.format("/%s/%05d.png", 45 | videoDirectory.getDirectoryNameForSharing(), i); 46 | out.putNextEntry(new ZipEntry(filename)); 47 | 48 | videoReader.getDataForNextFrame(frameData); 49 | imageProcessor.processCameraImage(frameData, width, height); 50 | // 0 is "quality" argument, ignored since PNG is lossless. 51 | imageProcessor.getBitmap().compress(Bitmap.CompressFormat.PNG, 0, out); 52 | 53 | out.closeEntry(); 54 | if (this.isCancelled()) { 55 | throw new InterruptedException(); 56 | } 57 | double fractionDone = 1.0*i / numFrames; 58 | publishProgress(new ProcessVideoTask.Progress( 59 | ProcessVideoTask.MediaType.VIDEO, fractionDone)); 60 | } 61 | 62 | out.close(); 63 | (new File(tempZipFile)).renameTo(new File(outputPath)); 64 | } 65 | catch (IOException ex) { 66 | Log.e("WG_ZIP", "Error creating zip file from video", ex); 67 | result = ProcessVideoTask.Result.FAILED; 68 | } 69 | catch(InterruptedException iex) { 70 | result = ProcessVideoTask.Result.CANCELLED; 71 | } 72 | finally { 73 | try { 74 | if (out!=null) out.close(); 75 | } 76 | catch (IOException ignored) {} 77 | 78 | File f = new File(tempZipFile); 79 | if (f.exists()) f.delete(); 80 | } 81 | return result; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/video/CreateWebmAsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball.video; 2 | 3 | import java.io.File; 4 | 5 | import com.dozingcatsoftware.eyeball.CameraImageProcessor; 6 | 7 | import android.os.AsyncTask; 8 | 9 | public class CreateWebmAsyncTask extends 10 | AsyncTask { 11 | 12 | private WebMEncoder videoEncoder; // to create WebM with video track only 13 | 14 | // Passed to execute in the ProcessVideoTask.Params argument. 15 | private MediaDirectory videoDirectory; 16 | private String outputPath; 17 | private CameraImageProcessor imageProcessor; 18 | 19 | String videoWebmPath; 20 | 21 | @SuppressWarnings("serial") 22 | static class ExecutionFailedException extends RuntimeException {} 23 | 24 | @Override protected ProcessVideoTask.Result doInBackground(ProcessVideoTask.Params... params) { 25 | this.videoDirectory = params[0].videoDirectory; 26 | this.outputPath = params[0].outputPath; 27 | this.imageProcessor = params[0].imageProcessor; 28 | 29 | ProcessVideoTask.Result result = ProcessVideoTask.Result.SUCCEEDED; 30 | 31 | videoWebmPath = outputPath.endsWith(".webm") ? 32 | (outputPath.substring(0, outputPath.length()-5) + "-video.webm") : 33 | (outputPath + "-video.webm"); 34 | 35 | try { 36 | // Create WebM file with video track. 37 | int numFrames = videoDirectory.getVideoProperties().getNumberOfFrames(); 38 | videoEncoder = new WebMEncoder(this.videoDirectory, videoWebmPath, this.imageProcessor); 39 | videoEncoder.startEncoding(); 40 | while (!videoEncoder.allFramesFinished()) { 41 | if (!videoEncoder.encodeNextFrame()) { 42 | throw new ExecutionFailedException(); 43 | } 44 | 45 | if (this.isCancelled()) { 46 | throw new InterruptedException(); 47 | } 48 | double fractionDone = 1.0*videoEncoder.currentFrameNumber() / numFrames; 49 | publishProgress(new ProcessVideoTask.Progress(ProcessVideoTask.MediaType.VIDEO, fractionDone)); 50 | } 51 | videoEncoder.finishEncoding(); 52 | 53 | // Add audio track by encoding PCM file to Vorbis and inserting into a new WebM file. 54 | String audioPath = videoDirectory.audioFilePath(); 55 | File audioFile = new File(audioPath); 56 | if (audioFile.isFile()) { 57 | final long audioFileSize = (new File(audioPath)).length(); 58 | 59 | CombineAudioVideo.EncoderDelegate encoderDelegate = new CombineAudioVideo.EncoderDelegate() { 60 | @Override 61 | public void receivedOggPage(long bytesRead) { 62 | double fractionDone = 1.0*bytesRead / audioFileSize; 63 | publishProgress(new ProcessVideoTask.Progress(ProcessVideoTask.MediaType.AUDIO, fractionDone)); 64 | } 65 | }; 66 | CombineAudioVideo.insertAudioIntoWebm(videoDirectory.audioFilePath(), videoWebmPath, outputPath, encoderDelegate); 67 | // Remove temporary video-only WebM file. 68 | (new File(videoWebmPath)).delete(); 69 | } 70 | else { 71 | // No audio, rename video WebM file. 72 | (new File(videoWebmPath)).renameTo(new File(outputPath)); 73 | } 74 | } 75 | catch(InterruptedException iex) { 76 | result = ProcessVideoTask.Result.CANCELLED; 77 | } 78 | catch(Exception ex) { 79 | result = ProcessVideoTask.Result.FAILED; 80 | } 81 | 82 | if (result != ProcessVideoTask.Result.SUCCEEDED) { 83 | cleanupAfterError(); 84 | } 85 | 86 | return result; 87 | } 88 | 89 | void cleanupAfterError() { 90 | File f = new File(videoWebmPath); 91 | if (f.exists()) f.delete(); 92 | f = new File(outputPath); 93 | if (f.exists()) f.delete(); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/video/ImageRecorder.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball.video; 2 | 3 | import java.io.IOException; 4 | 5 | import android.content.Context; 6 | import android.graphics.Bitmap; 7 | 8 | import com.dozingcatsoftware.eyeball.CameraImageProcessor; 9 | import com.dozingcatsoftware.eyeball.WGUtils; 10 | import com.dozingcatsoftware.util.AndroidUtils; 11 | 12 | /** This class handles storing data and metadata for single images. It uses VideoRecorder to record a single-frame "video". 13 | */ 14 | 15 | public class ImageRecorder { 16 | 17 | Context context; 18 | String imageDirectory; 19 | MediaProperties imageProperties; 20 | 21 | public static int THUMBNAIL_SIZE = 120; 22 | 23 | public ImageRecorder(Context context, String directory) { 24 | this.context = context; 25 | this.imageDirectory = directory; 26 | } 27 | 28 | public void saveImage(byte[] data, Bitmap bitmap, int width, int height, 29 | Integer colorScheme, boolean solidColor, boolean noiseFilter, CameraImageProcessor.Orientation orientation) 30 | throws IOException { 31 | VideoRecorder recorder = new VideoRecorder(this.imageDirectory, width, height, VideoRecorder.Quality.HIGH, 32 | colorScheme, solidColor, noiseFilter, orientation); 33 | recorder.recordFrame(data); 34 | recorder.endRecording(); 35 | recorder.storeThumbnailImage(bitmap, THUMBNAIL_SIZE); 36 | writePNGImage(bitmap); 37 | } 38 | 39 | 40 | public void saveImage(CameraImageProcessor imageProcessor, Integer colorScheme, boolean solidColor, boolean noiseFilter) throws IOException { 41 | this.saveImage(imageProcessor.getImageData(), imageProcessor.getBitmap(), imageProcessor.getImageWidth(), imageProcessor.getImageHeight(), 42 | colorScheme, solidColor, noiseFilter, imageProcessor.getOrientation()); 43 | } 44 | 45 | public void writePNGImage(Bitmap bitmap) throws IOException { 46 | String path = this.imageDirectory + ".png"; 47 | WGUtils.savePicture(bitmap, path); 48 | AndroidUtils.scanSavedMediaFile(context, path); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/video/MediaProperties.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball.video; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | import org.json.JSONArray; 8 | import org.json.JSONException; 9 | import org.json.JSONObject; 10 | 11 | public class MediaProperties { 12 | 13 | JSONObject properties; 14 | 15 | public MediaProperties() { 16 | this.properties = new JSONObject(); 17 | } 18 | 19 | public MediaProperties(JSONObject props) { 20 | this.properties = props; 21 | } 22 | 23 | int getIntProperty(String key, int defvalue) { 24 | return properties.optInt(key, defvalue); 25 | } 26 | 27 | long getLongProperty(String key, long defvalue) { 28 | return properties.optLong(key, defvalue); 29 | } 30 | 31 | 32 | void setProperty(String key, Object value) { 33 | try {properties.put(key, value);} 34 | catch(Exception ex) { 35 | throw new RuntimeException(ex); 36 | } 37 | } 38 | 39 | public int getVersion() { 40 | return getIntProperty("version", 1); 41 | } 42 | public void setVersion(Integer value) { 43 | setProperty("version", value); 44 | } 45 | 46 | public int getWidth() { 47 | return getIntProperty("width", -1); 48 | } 49 | public void setWidth(Integer value) { 50 | setProperty("width", value); 51 | } 52 | 53 | public int getHeight() { 54 | return getIntProperty("height", -1); 55 | } 56 | public void setHeight(Integer value) { 57 | setProperty("height", value); 58 | } 59 | 60 | public int getNumberOfFrames() { 61 | return getIntProperty("numFrames", -1); 62 | } 63 | public void setNumberOfFrames(Integer value) { 64 | setProperty("numFrames", value); 65 | } 66 | 67 | public long getStartTime() { 68 | return getLongProperty("startTime", -1); 69 | } 70 | public void setStartTime(Long value) { 71 | setProperty("startTime", value); 72 | } 73 | 74 | public long getEndTime() { 75 | return getLongProperty("endTime", -1); 76 | } 77 | public void setEndTime(Long value) { 78 | setProperty("endTime", value); 79 | } 80 | 81 | public int getColorScheme() { 82 | return getIntProperty("colorScheme", -1); 83 | } 84 | public void setColorScheme(Integer value) { 85 | setProperty("colorScheme", value); 86 | } 87 | 88 | public boolean isSolidColor() { 89 | return properties.optBoolean("solidColor", false); 90 | } 91 | public void setSolidColor(boolean value) { 92 | setProperty("solidColor", value); 93 | } 94 | 95 | public boolean useNoiseFilter() { 96 | return properties.optBoolean("noiseFilter", false); 97 | } 98 | public void setUseNoiseFilter(boolean value) { 99 | setProperty("noiseFilter", value); 100 | } 101 | 102 | public Date dateCreated() { 103 | long start = getStartTime(); 104 | if (start==-1) { 105 | // shouldn't happen 106 | return new Date(); 107 | } 108 | return new Date(start); 109 | } 110 | 111 | public long durationInMilliseconds() { 112 | long start = getStartTime(); 113 | long end = getEndTime(); 114 | if (start==-1 || end==-1) return 0; 115 | return end-start; 116 | } 117 | 118 | public long durationInSeconds() { 119 | return durationInMilliseconds() / 1000; 120 | } 121 | 122 | // arrays require annoying conversions to/from JSONArray 123 | public List getFrameDurations() { 124 | try { 125 | JSONArray array = properties.getJSONArray("frameDurations"); 126 | List result = new ArrayList(); 127 | int size = array.length(); 128 | for(int i=0; i durations = getFrameDurations(); 140 | if (durations==null) return null; 141 | int[] result = new int[durations.size()]; 142 | for(int i=0; i durations) { 162 | JSONArray array = new JSONArray(); 163 | for(Number n : durations) { 164 | array.put(n); 165 | } 166 | setProperty("frameDurations", array); 167 | } 168 | 169 | 170 | } 171 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/video/ProcessVideoTask.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball.video; 2 | 3 | import com.dozingcatsoftware.eyeball.CameraImageProcessor; 4 | 5 | /** Defines parameters, progress, and results for async video processing tasks. */ 6 | public class ProcessVideoTask { 7 | 8 | private ProcessVideoTask() {} 9 | 10 | public static class Params { 11 | public final MediaDirectory videoDirectory; 12 | public final String outputPath; 13 | public final CameraImageProcessor imageProcessor; 14 | 15 | public Params(MediaDirectory videoDirectory, String outputPath, CameraImageProcessor imageProcessor) { 16 | this.videoDirectory = videoDirectory; 17 | this.outputPath = outputPath; 18 | this.imageProcessor = imageProcessor; 19 | } 20 | } 21 | 22 | public static class Progress { 23 | public final MediaType mediaType; 24 | public final double fractionDone; 25 | 26 | public Progress(MediaType mediaType, double fractionDone) { 27 | this.mediaType = mediaType; 28 | this.fractionDone = fractionDone; 29 | } 30 | } 31 | 32 | public static enum MediaType { 33 | VIDEO, AUDIO 34 | }; 35 | 36 | public static enum Result { 37 | SUCCEEDED, FAILED, CANCELLED 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/video/VideoReader.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball.video; 2 | 3 | import java.io.IOException; 4 | import java.io.RandomAccessFile; 5 | 6 | public class VideoReader { 7 | MediaDirectory videoDirectory; 8 | MediaProperties videoProperties; 9 | 10 | RandomAccessFile videoFile; 11 | int bytesPerFrame; 12 | int currentFrame; 13 | 14 | 15 | public VideoReader(String directory) { 16 | this.videoDirectory = new MediaDirectory(directory); 17 | this.videoProperties = videoDirectory.getVideoProperties(); 18 | this.bytesPerFrame = videoProperties.getWidth() * videoProperties.getHeight(); 19 | } 20 | 21 | public MediaProperties getVideoProperties() { 22 | return videoProperties; 23 | } 24 | 25 | public MediaDirectory getVideoDirectory() { 26 | return videoDirectory; 27 | } 28 | 29 | // fills data with bytes for next frame, and advances frame number 30 | public void getDataForNextFrame(byte[] data) throws IOException { 31 | if (this.videoFile==null) { 32 | this.videoFile = this.videoDirectory.videoRandomAccessFile(); 33 | } 34 | 35 | long offset = currentFrame * bytesPerFrame; 36 | if (offset!=videoFile.getFilePointer()) { 37 | videoFile.seek(offset); 38 | } 39 | videoFile.readFully(data, 0, bytesPerFrame); 40 | ++currentFrame; 41 | } 42 | 43 | public void moveToFrameNumber(int frameNumber) { 44 | if (frameNumber<0) frameNumber = 0; 45 | int maxFrames = this.videoProperties.getNumberOfFrames(); 46 | if (frameNumber>=maxFrames) frameNumber = maxFrames; 47 | 48 | this.currentFrame = frameNumber; 49 | } 50 | 51 | // returns the number of the next frame to be displayed. 0-based, so returns 0 for a video that hasn't started yet. 52 | public int currentFrameNumber() { 53 | return currentFrame; 54 | } 55 | 56 | public boolean isAtEnd() { 57 | return this.currentFrame >= this.videoProperties.getNumberOfFrames(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/eyeball/video/WebMEncoder.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.eyeball.video; 2 | 3 | import com.dozingcatsoftware.eyeball.CameraImageProcessor; 4 | 5 | import android.graphics.Bitmap; 6 | import android.util.Log; 7 | 8 | public class WebMEncoder { 9 | 10 | MediaDirectory videoDirectory; 11 | MediaProperties videoProperties; 12 | VideoReader videoReader; 13 | CameraImageProcessor imageProcessor; 14 | String outputPath; 15 | //int quality; 16 | int framesEncoded = 0; 17 | EncodingCallback encodingCallback; 18 | 19 | byte[] frameData; 20 | int[] frameARGB; 21 | Thread encodingThread; 22 | volatile boolean abortEncodingThread; 23 | 24 | 25 | public static interface EncodingCallback { 26 | public void frameEncoded(WebMEncoder encoder, int frameNumber, int totalFrames); 27 | } 28 | 29 | public WebMEncoder(MediaDirectory vd, String outputPath, CameraImageProcessor imageProcessor) { 30 | this.videoDirectory = vd; 31 | this.videoProperties = vd.getVideoProperties(); 32 | this.outputPath = outputPath; 33 | this.videoReader = new VideoReader(videoDirectory.getPath()); 34 | this.imageProcessor = imageProcessor; 35 | } 36 | 37 | public void setEncodingCallback(EncodingCallback value) { 38 | this.encodingCallback = value; 39 | } 40 | 41 | public String getOutputPath() { 42 | return outputPath; 43 | } 44 | 45 | public void startEncoding() { 46 | this.frameData = new byte[videoProperties.getWidth() * videoProperties.getHeight()]; 47 | this.frameARGB = new int[this.frameData.length]; 48 | float fps = videoProperties.getNumberOfFrames() / (videoProperties.durationInMilliseconds() / 1000.0f); 49 | int[] frameEndTimes = videoProperties.getFrameRelativeEndTimes(); 50 | int deadline = 1000000; // In microseconds; normally VP8 is much faster than one frame per second. 51 | this.nativeStartEncoding(outputPath, videoProperties.getWidth(), videoProperties.getHeight(), fps, frameEndTimes, deadline); 52 | } 53 | 54 | public boolean encodeNextFrame() { 55 | try { 56 | videoReader.getDataForNextFrame(frameData); 57 | imageProcessor.processCameraImage(frameData, videoProperties.getWidth(), videoProperties.getHeight()); 58 | Bitmap bitmap = imageProcessor.getBitmap(); 59 | bitmap.getPixels(this.frameARGB, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight()); 60 | nativeEncodeFrame(this.frameARGB); 61 | } 62 | catch(Throwable ex) { 63 | Log.e("WG-WEBM", "Error encoding frame", ex); 64 | return false; 65 | } 66 | return true; 67 | } 68 | 69 | public boolean finishEncoding() { 70 | try { 71 | nativeFinishEncoding(); 72 | } 73 | catch(Throwable ex) { 74 | Log.e("WG-WEBM", "Error finishing encoding", ex); 75 | return false; 76 | } 77 | this.frameData = null; 78 | this.frameARGB = null; 79 | this.imageProcessor = null; 80 | return true; 81 | } 82 | 83 | public int numberOfFrames() { 84 | return videoProperties.getNumberOfFrames(); 85 | } 86 | 87 | public int currentFrameNumber() { 88 | return videoReader.currentFrameNumber(); 89 | } 90 | 91 | public boolean allFramesFinished() { 92 | return videoReader.isAtEnd(); 93 | } 94 | 95 | public void runEncodingInThread() { 96 | 97 | } 98 | 99 | public void cancelEncoding() { 100 | if (encodingThread!=null) { 101 | abortEncodingThread = true; 102 | encodingThread.interrupt(); 103 | try {encodingThread.join(100);} 104 | catch(InterruptedException ex) {} 105 | } 106 | nativeCancelEncoding(); 107 | (new java.io.File(outputPath)).delete(); 108 | } 109 | 110 | public native int nativeStartEncoding(String path, int width, int height, float fps, int[] frameEndTimes, int deadline); 111 | public native int nativeEncodeFrame(int[] argb); 112 | public native int nativeFinishEncoding(); 113 | public native int nativeCancelEncoding(); 114 | 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/util/ARManager.java: -------------------------------------------------------------------------------- 1 | package com.dozingcatsoftware.util; 2 | 3 | import android.app.Activity; 4 | import android.hardware.Camera; 5 | import android.view.SurfaceHolder; 6 | import android.view.SurfaceView; 7 | 8 | public class ARManager implements SurfaceHolder.Callback { 9 | 10 | Activity activity; 11 | SurfaceView cameraView; 12 | Camera.PreviewCallback previewCallback; 13 | Runnable cameraOpenedCallback; 14 | 15 | Camera camera; 16 | boolean cameraViewReady = false; 17 | int cameraId = 0; 18 | 19 | int preferredPreviewWidth = 0, preferredPreviewHeight = 0; 20 | int numPreviewCallbackBuffers = 0; 21 | 22 | public ARManager(Activity _activity, SurfaceView _cameraView, Camera.PreviewCallback _previewCallback) { 23 | this.activity = _activity; 24 | this.cameraView = _cameraView; 25 | this.previewCallback = _previewCallback; 26 | } 27 | 28 | public void setupCameraView() { 29 | cameraView.getHolder().addCallback(this); 30 | cameraView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 31 | } 32 | 33 | public static ARManager createAndSetupCameraView(Activity _activity, SurfaceView _cameraView, Camera.PreviewCallback _previewCallback) { 34 | ARManager manager = new ARManager(_activity, _cameraView, _previewCallback); 35 | manager.setupCameraView(); 36 | return manager; 37 | } 38 | 39 | public void setPreferredPreviewSize(int width, int height) { 40 | this.preferredPreviewWidth = width; 41 | this.preferredPreviewHeight = height; 42 | } 43 | 44 | public void setNumberOfPreviewCallbackBuffers(int n) { 45 | this.numPreviewCallbackBuffers = n; 46 | } 47 | 48 | public void setCameraOpenedCallback(Runnable callback) { 49 | cameraOpenedCallback = callback; 50 | } 51 | 52 | public boolean startCamera() { 53 | if (camera==null) { 54 | try { 55 | camera = CameraUtils.openCamera(cameraId); 56 | if (cameraOpenedCallback!=null) { 57 | cameraOpenedCallback.run(); 58 | } 59 | camera.setPreviewDisplay(cameraView.getHolder()); 60 | if (preferredPreviewWidth>0 && preferredPreviewHeight>0) { 61 | CameraUtils.setNearestCameraPreviewSize(camera, preferredPreviewWidth, preferredPreviewHeight); 62 | } 63 | 64 | if (numPreviewCallbackBuffers > 0) { 65 | CameraUtils.createPreviewCallbackBuffers(camera, this.numPreviewCallbackBuffers); 66 | CameraUtils.setPreviewCallbackWithBuffer(camera, this.previewCallback); 67 | } 68 | else { 69 | camera.setPreviewCallback(this.previewCallback); 70 | } 71 | camera.startPreview(); 72 | } 73 | catch(Exception ex) { 74 | camera = null; 75 | } 76 | } 77 | return (camera!=null); 78 | } 79 | 80 | 81 | public void startCameraIfVisible() { 82 | if (cameraViewReady) { 83 | startCamera(); 84 | } 85 | } 86 | 87 | public void stopCamera() { 88 | if (camera!=null) { 89 | camera.setPreviewCallback(null); 90 | camera.stopPreview(); 91 | camera.release(); 92 | camera = null; 93 | } 94 | } 95 | 96 | public void switchToCamera(int _cameraId) { 97 | if (camera!=null) { 98 | stopCamera(); 99 | } 100 | this.cameraId = _cameraId; 101 | startCameraIfVisible(); 102 | } 103 | 104 | public void switchToNextCamera() { 105 | switchToCamera((cameraId + 1) % CameraUtils.numberOfCameras()); 106 | } 107 | 108 | // SurfaceHolder callbacks 109 | @Override 110 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 111 | this.cameraViewReady = true; 112 | startCameraIfVisible(); 113 | } 114 | 115 | @Override 116 | public void surfaceCreated(SurfaceHolder holder) { 117 | // all done in surfaceChanged 118 | } 119 | 120 | @Override 121 | public void surfaceDestroyed(SurfaceHolder holder) { 122 | this.cameraViewReady = false; 123 | stopCamera(); 124 | } 125 | 126 | 127 | public Camera getCamera() { 128 | return camera; 129 | } 130 | public int getCameraId() { 131 | return cameraId; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/util/AsyncImageLoader.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Brian Nenninger 2 | 3 | package com.dozingcatsoftware.util; 4 | 5 | import java.lang.ref.WeakReference; 6 | 7 | import android.content.res.Resources; 8 | import android.graphics.Bitmap; 9 | import android.graphics.drawable.BitmapDrawable; 10 | import android.graphics.drawable.Drawable; 11 | import android.net.Uri; 12 | import android.os.AsyncTask; 13 | import android.widget.ImageView; 14 | 15 | /** 16 | * Class to handle assigning a bitmap to a view, when the bitmap may need to be loaded from 17 | * storage asynchronously. 18 | * 19 | * This code is based on the sample code at http://developer.android.com/training/displaying-bitmaps/index.html 20 | */ 21 | public class AsyncImageLoader { 22 | 23 | static class BitmapWorkerTask extends AsyncTask { 24 | WeakReference imageViewReference; 25 | Uri data = null; 26 | ScaledBitmapCache bitmapCache; 27 | int width; 28 | int height; 29 | 30 | public BitmapWorkerTask(ImageView imageView, ScaledBitmapCache bitmapCache, int width, int height) { 31 | // Use a WeakReference to ensure the ImageView can be garbage collected 32 | imageViewReference = new WeakReference(imageView); 33 | this.bitmapCache = bitmapCache; 34 | this.width = width; 35 | this.height = height; 36 | } 37 | 38 | // Decode image in background. 39 | @Override protected Bitmap doInBackground(Uri...args) { 40 | data = args[0]; 41 | return bitmapCache.getScaledBitmap(args[0], width, height); 42 | } 43 | 44 | // Once complete, see if ImageView is still around and set bitmap. 45 | @Override protected void onPostExecute(Bitmap bitmap) { 46 | if (imageViewReference != null && bitmap != null) { 47 | final ImageView imageView = imageViewReference.get(); 48 | if (imageView != null) { 49 | imageView.setImageBitmap(bitmap); 50 | } 51 | } 52 | } 53 | 54 | private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { 55 | if (imageView != null) { 56 | final Drawable drawable = imageView.getDrawable(); 57 | if (drawable instanceof AsyncDrawable) { 58 | final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; 59 | return asyncDrawable.getBitmapWorkerTask(); 60 | } 61 | } 62 | return null; 63 | } 64 | 65 | public static boolean cancelPotentialWork(Uri uri, ImageView imageView) { 66 | final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); 67 | 68 | if (bitmapWorkerTask != null) { 69 | final Uri taskUri = bitmapWorkerTask.data; 70 | if (!uri.equals(taskUri)) { 71 | // Cancel previous task 72 | bitmapWorkerTask.cancel(true); 73 | } 74 | else { 75 | // The same work is already in progress 76 | return false; 77 | } 78 | } 79 | // No task associated with the ImageView, or an existing task was cancelled 80 | return true; 81 | } 82 | } 83 | 84 | static class AsyncDrawable extends BitmapDrawable { 85 | private final WeakReference bitmapWorkerTaskReference; 86 | 87 | public AsyncDrawable(Resources res, BitmapWorkerTask bitmapWorkerTask) { 88 | super(res, (Bitmap)null); 89 | bitmapWorkerTaskReference = new WeakReference(bitmapWorkerTask); 90 | } 91 | 92 | public BitmapWorkerTask getBitmapWorkerTask() { 93 | return bitmapWorkerTaskReference.get(); 94 | } 95 | } 96 | 97 | /** 98 | * Sets the bitmap of an ImageView, loading the bitmap using a background AsyncTask if needed. 99 | * If the image URI is found in-memory in the ScaledBitmapCache, assigns it directly to the 100 | * ImageView and returns. Otherwise, creates an AsyncTask in which the ScaledBitmapCache reads 101 | * the bitmap from secondary storage and assigns it to the ImageView when loaded. 102 | */ 103 | public void loadImageIntoViewAsync(final ScaledBitmapCache bitmapCache, Uri imageUri, ImageView imageView, 104 | final int width, final int height, Resources resources) { 105 | // check in-memory cache, if found no need for an AsyncTask 106 | Bitmap bitmap = bitmapCache.getInMemoryScaledBitmap(imageUri, width, height); 107 | if (bitmap!=null) { 108 | imageView.setImageBitmap(bitmap); 109 | return; 110 | } 111 | // read from storage with AsyncTask 112 | if (BitmapWorkerTask.cancelPotentialWork(imageUri, imageView)) { 113 | BitmapWorkerTask task = new BitmapWorkerTask(imageView, bitmapCache, width, height); 114 | AsyncDrawable asyncDrawable = new AsyncDrawable(resources, task); 115 | imageView.setImageDrawable(asyncDrawable); 116 | task.execute(imageUri); 117 | } 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/util/CameraPreviewProcessingQueue.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Brian Nenninger 2 | 3 | package com.dozingcatsoftware.util; 4 | 5 | /** 6 | * Specialized wrapper around SingleItemProcessingQueue for the purpose of processing camera preview images. 7 | */ 8 | public class CameraPreviewProcessingQueue { 9 | 10 | public static interface Processor { 11 | // Called in a separate thread to process a camera preview image 12 | public abstract void processCameraImage(byte[] data, int width, int height); 13 | } 14 | 15 | static class CameraPreviewImage { 16 | final byte[] data; 17 | final int width; 18 | final int height; 19 | 20 | public CameraPreviewImage(byte[] data, int width, int height) { 21 | this.data = data; 22 | this.width = width; 23 | this.height = height; 24 | } 25 | } 26 | 27 | SingleItemProcessingQueue processingQueue = new SingleItemProcessingQueue(); 28 | 29 | /** Called by camera preview callback method when a frame is received. 30 | */ 31 | public boolean processImageData(byte[] data, int width, int height) { 32 | return processingQueue.queueData(new CameraPreviewImage(data, width, height)); 33 | } 34 | 35 | public void start(final Processor imageProcessor) { 36 | processingQueue.start(new SingleItemProcessingQueue.Processor() { 37 | @Override public void processData(CameraPreviewImage data) { 38 | imageProcessor.processCameraImage(data.data, data.width, data.height); 39 | } 40 | }); 41 | } 42 | 43 | public void stop() { 44 | processingQueue.stop(); 45 | } 46 | 47 | public void pause() { 48 | processingQueue.pause(); 49 | } 50 | 51 | public void unpause() { 52 | processingQueue.unpause(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/util/ScaledBitmapCache.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Brian Nenninger 2 | 3 | package com.dozingcatsoftware.util; 4 | 5 | import java.io.File; 6 | import java.io.FileOutputStream; 7 | import java.io.OutputStream; 8 | 9 | 10 | import android.content.Context; 11 | import android.graphics.Bitmap; 12 | import android.graphics.Bitmap.CompressFormat; 13 | import android.net.Uri; 14 | import android.support.v4.util.LruCache; 15 | 16 | /** This class implements a two-level cache for Bitmaps. The first level is an in-memory map 17 | * which uses an LruCache so that the Bitmaps will be freed when necessary. The second 18 | * level is a location directory on the SD card, where smaller versions of the images 19 | * will be saved for faster retrieval. The exact location is determined by the ThumbnailLocator 20 | * implementation passed to the constructor. 21 | */ 22 | 23 | public class ScaledBitmapCache { 24 | 25 | static int MEMORY_CACHE_SIZE = 2*1024*1024; 26 | 27 | public static interface ThumbnailLocator { 28 | File thumbnailFileForUri(Uri imageUri); 29 | } 30 | 31 | // Simple ThumbnailLocator for putting thumbnails into a single directory using the image URI's filename. 32 | public static ThumbnailLocator createFixedDirectoryLocator(final String thumbnailDirectory) { 33 | return new ThumbnailLocator() { 34 | public File thumbnailFileForUri(Uri imageUri) { 35 | String filename = imageUri.getLastPathSegment(); 36 | return new File(thumbnailDirectory + File.separator + filename); 37 | } 38 | }; 39 | } 40 | 41 | public static ThumbnailLocator createIdentityLocator() { 42 | return new ThumbnailLocator() { 43 | public File thumbnailFileForUri(Uri imageUri) { 44 | return new File(imageUri.getPath()); 45 | } 46 | }; 47 | } 48 | 49 | Context context; 50 | ThumbnailLocator thumbnailLocator; 51 | 52 | LruCache scaledBitmapCache = new LruCache(MEMORY_CACHE_SIZE) { 53 | @Override protected int sizeOf(Uri uri, Bitmap bitmap) { 54 | int size = AndroidUtils.getBitmapByteCount(bitmap); 55 | return size; 56 | } 57 | }; 58 | 59 | public ScaledBitmapCache(Context context, ThumbnailLocator thumbnailLocator) { 60 | this.context = context; 61 | this.thumbnailLocator = thumbnailLocator; 62 | } 63 | 64 | public ScaledBitmapCache(Context context, String imageDirectory) { 65 | this(context, createFixedDirectoryLocator(imageDirectory)); 66 | } 67 | 68 | public Bitmap getInMemoryScaledBitmap(Uri imageUri, int minWidth, int minHeight) { 69 | Bitmap bitmap = scaledBitmapCache.get(imageUri); 70 | if (bitmap!=null && bitmap.getWidth()>=minWidth && bitmap.getHeight()>=minHeight) { 71 | return bitmap; 72 | } 73 | return null; 74 | } 75 | 76 | public Bitmap getScaledBitmap(Uri imageUri, int minWidth, int minHeight) { 77 | Bitmap bitmap = getInMemoryScaledBitmap(imageUri, minWidth, minHeight); 78 | if (bitmap!=null) return bitmap; 79 | 80 | // check thumbnail directory 81 | File thumbfile = thumbnailLocator.thumbnailFileForUri(imageUri); 82 | if (thumbfile!=null && thumbfile.isFile()) { 83 | try { 84 | bitmap = AndroidUtils.scaledBitmapFromURIWithMinimumSize(context, 85 | Uri.fromFile(thumbfile), minWidth, minHeight); 86 | if (bitmap!=null && bitmap.getWidth()>=minWidth && bitmap.getHeight()>=minHeight) { 87 | scaledBitmapCache.put(imageUri, bitmap); 88 | return bitmap; 89 | } 90 | } 91 | catch(Exception ignored) {} 92 | } 93 | 94 | // read full-size image 95 | try { 96 | bitmap = AndroidUtils.scaledBitmapFromURIWithMinimumSize(context, imageUri, minWidth, minHeight); 97 | } 98 | catch(Exception ex) { 99 | bitmap = null; 100 | } 101 | if (bitmap!=null) { 102 | // write to in-memory map and save thumbnail image 103 | scaledBitmapCache.put(imageUri, bitmap); 104 | try { 105 | // create thumbnail directory if it doesn't exist 106 | thumbfile.getParentFile().mkdirs(); 107 | OutputStream thumbnailOutputStream = new FileOutputStream(thumbfile); 108 | bitmap.compress(CompressFormat.JPEG, 90, thumbnailOutputStream); 109 | thumbnailOutputStream.close(); 110 | // create .noindex file so thumbnail pictures won't be indexed and show up in the gallery app 111 | (new File(thumbfile.getParentFile().getPath() + File.separator + ".nomedia")).createNewFile(); 112 | } 113 | catch(Exception ignored) {} 114 | } 115 | return bitmap; 116 | } 117 | 118 | public void removeUri(Uri imageUri) { 119 | scaledBitmapCache.remove(imageUri); 120 | thumbnailLocator.thumbnailFileForUri(imageUri).delete(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/util/ShutterButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 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 | 17 | package com.dozingcatsoftware.util; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.widget.ImageView; 22 | 23 | /** 24 | * A button designed to be used for the on-screen shutter button. 25 | * It's currently an {@code ImageView} that can call a delegate when the 26 | * pressed state changes. 27 | */ 28 | public class ShutterButton extends ImageView { 29 | /** 30 | * A callback to be invoked when a ShutterButton's pressed state changes. 31 | */ 32 | public interface OnShutterButtonListener { 33 | /** 34 | * Called when a ShutterButton has been pressed. 35 | * 36 | * @param pressed The ShutterButton that was pressed. 37 | */ 38 | void onShutterButtonFocus(boolean pressed); 39 | void onShutterButtonClick(); 40 | } 41 | 42 | private OnShutterButtonListener mListener; 43 | private boolean mOldPressed; 44 | 45 | public ShutterButton(Context context, AttributeSet attrs) { 46 | super(context, attrs); 47 | } 48 | 49 | public void setOnShutterButtonListener(OnShutterButtonListener listener) { 50 | mListener = listener; 51 | } 52 | 53 | /** 54 | * Hook into the drawable state changing to get changes to isPressed -- the 55 | * onPressed listener doesn't always get called when the pressed state 56 | * changes. 57 | */ 58 | @Override 59 | protected void drawableStateChanged() { 60 | super.drawableStateChanged(); 61 | final boolean pressed = isPressed(); 62 | if (pressed != mOldPressed) { 63 | if (!pressed) { 64 | // When pressing the physical camera button the sequence of 65 | // events is: 66 | // focus pressed, optional camera pressed, focus released. 67 | // We want to emulate this sequence of events with the shutter 68 | // button. When clicking using a trackball button, the view 69 | // system changes the the drawable state before posting click 70 | // notification, so the sequence of events is: 71 | // pressed(true), optional click, pressed(false) 72 | // When clicking using touch events, the view system changes the 73 | // drawable state after posting click notification, so the 74 | // sequence of events is: 75 | // pressed(true), pressed(false), optional click 76 | // Since we're emulating the physical camera button, we want to 77 | // have the same order of events. So we want the optional click 78 | // callback to be delivered before the pressed(false) callback. 79 | // 80 | // To do this, we delay the posting of the pressed(false) event 81 | // slightly by pushing it on the event queue. This moves it 82 | // after the optional click notification, so our client always 83 | // sees events in this sequence: 84 | // pressed(true), optional click, pressed(false) 85 | post(new Runnable() { 86 | public void run() { 87 | callShutterButtonFocus(pressed); 88 | } 89 | }); 90 | } else { 91 | callShutterButtonFocus(pressed); 92 | } 93 | mOldPressed = pressed; 94 | } 95 | } 96 | 97 | private void callShutterButtonFocus(boolean pressed) { 98 | if (mListener != null) { 99 | mListener.onShutterButtonFocus(pressed); 100 | } 101 | } 102 | 103 | @Override 104 | public boolean performClick() { 105 | boolean result = super.performClick(); 106 | if (mListener != null) { 107 | mListener.onShutterButtonClick(); 108 | } 109 | return result; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/java/com/dozingcatsoftware/util/SingleItemProcessingQueue.java: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Brian Nenninger 2 | 3 | package com.dozingcatsoftware.util; 4 | 5 | /** 6 | * A variant of a producer-consumer queue where only a single data object is queued behind 7 | * the data currently being processed. If new data arrives while previous data is still 8 | * waiting to be processed, we just drop that previous data. Incoming data is added by 9 | * calling {@code queueData}, and is processed on a secondary thread. 10 | */ 11 | public class SingleItemProcessingQueue { 12 | 13 | private static final boolean DEBUG = false; 14 | 15 | /** Interface defining a method to process incoming data. */ 16 | public static interface Processor { 17 | /** 18 | * Called on a secondary thread when data is available to process. 19 | */ 20 | void processData(T data); 21 | } 22 | 23 | Thread thread; 24 | boolean running; 25 | boolean paused; 26 | boolean waiting; 27 | T nextData; 28 | 29 | /** 30 | * Starts processing data supplied via {@code queueData}, using the specified processor 31 | * and optionally setting the processing thread name. 32 | */ 33 | public void start(final Processor processor, String threadName) { 34 | if (thread==null) { 35 | thread = new Thread() { 36 | @Override 37 | public void run() { 38 | threadEntry(processor); 39 | } 40 | }; 41 | running = true; 42 | thread.start(); 43 | } 44 | if (threadName!=null) thread.setName(threadName); 45 | } 46 | 47 | /** Calls the two-argument start method with no thread name. */ 48 | public void start(Processor processor) { 49 | start(processor, null); 50 | } 51 | 52 | /** Stops the processing thread. */ 53 | public void stop() { 54 | if (thread!=null) { 55 | running = false; 56 | synchronized(this) { 57 | this.notify(); 58 | } 59 | try { 60 | thread.join(); 61 | } 62 | catch(InterruptedException ie) {} 63 | thread = null; 64 | } 65 | } 66 | 67 | /** 68 | * Temporarily halts processing input data. The processing thread is not stopped, 69 | * but no incoming data will be processed until {@code unpause} is called. 70 | */ 71 | public void pause() { 72 | paused = true; 73 | } 74 | 75 | /** Resumes processing data after a call to {@code pause}. */ 76 | public void unpause() { 77 | paused = false; 78 | } 79 | 80 | /** 81 | * Adds data to be processed by the processing thread. Returns false if there is a previous 82 | * data object queued. 83 | */ 84 | public boolean queueData(T data) { 85 | // set nextData and notify processor thread if it's waiting for it 86 | synchronized(this) { 87 | if (DEBUG) android.util.Log.i("SingleItemProcessingQueue", "setting nextData"); 88 | if (this.nextData != null) { 89 | return false; 90 | } 91 | this.nextData = data; 92 | if (waiting) { 93 | if (DEBUG) android.util.Log.i("SingleItemProcessingQueue", "calling notify()"); 94 | this.notify(); 95 | } 96 | return true; 97 | } 98 | } 99 | 100 | void threadEntry(Processor processor) { 101 | try { 102 | while(running) { 103 | T currentData = null; 104 | synchronized(this) { 105 | // wait until nextData is set in queueData 106 | while(this.nextData==null) { 107 | if (DEBUG) android.util.Log.e("SingleItemProcessingQueue", "waiting for data"); 108 | waiting = true; 109 | try {this.wait(250);} 110 | catch(InterruptedException ie) {} 111 | if (!running) return; 112 | } 113 | currentData = this.nextData; 114 | this.nextData = null; 115 | waiting = false; 116 | } 117 | if (!paused) { 118 | if (DEBUG) android.util.Log.i("SingleItemProcessingQueue", "calling processData()"); 119 | processor.processData(currentData); 120 | if (DEBUG) android.util.Log.i("SingleItemProcessingQueue", "processData() done"); 121 | } 122 | } 123 | } 124 | catch(Throwable ex) { 125 | android.util.Log.e("SingleItemProcessingQueue", "Exception in SingleItemProcessingQueue", ex); 126 | } 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /app/src/main/java/org/openintents/widget/OnColorChangedListener.java: -------------------------------------------------------------------------------- 1 | package org.openintents.widget; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Interface for notifications of position change of slider. 7 | * 8 | * @author Peli 9 | */ 10 | public interface OnColorChangedListener { 11 | 12 | /** 13 | * This method is called when the user changed the color. 14 | * 15 | * This works in touch mode, by dragging the along the 16 | * color circle with the finger. 17 | */ 18 | void onColorChanged(View view, int newColor); 19 | 20 | /** 21 | * This method is called when the user clicks the center button. 22 | * 23 | * @param colorcircle 24 | * @param newColor 25 | */ 26 | void onColorPicked(View view, int newColor); 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/jni/.sobel.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/jni/.sobel.c.swp -------------------------------------------------------------------------------- /app/src/main/jni/.wg_video.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/jni/.wg_video.c.swp -------------------------------------------------------------------------------- /app/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | # Prebuilt libvpx static library, built directly on Linux rather than through 4 | # the NDK. See README-libvpx.txt. 5 | include $(CLEAR_VARS) 6 | LOCAL_MODULE := libvpx 7 | LOCAL_SRC_FILES := libvpx_prebuilt_libs/$(TARGET_ARCH_ABI)/libvpx.a 8 | include $(PREBUILT_STATIC_LIBRARY) 9 | 10 | 11 | # Helper functions to write WebM files. These will build with the NDK. 12 | include $(CLEAR_VARS) 13 | LOCAL_MODULE := libwebmenc 14 | LOCAL_SRC_FILES := libvpx/webmenc.cc \ 15 | libvpx/third_party/libwebm/mkvmuxer.cpp \ 16 | libvpx/third_party/libwebm/mkvmuxerutil.cpp \ 17 | libvpx/third_party/libwebm/mkvparser.cpp \ 18 | libvpx/third_party/libwebm/mkvreader.cpp \ 19 | libvpx/third_party/libwebm/mkvwriter.cpp 20 | include $(BUILD_STATIC_LIBRARY) 21 | 22 | 23 | # WireGoggles code. 24 | include $(CLEAR_VARS) 25 | LOCAL_MODULE := wiregoggles 26 | LOCAL_SRC_FILES := sobel.c wg_video.c 27 | LOCAL_STATIC_LIBRARIES := libvpx libwebmenc 28 | LOCAL_C_INCLUDES += jni/libvpx/ 29 | include $(BUILD_SHARED_LIBRARY) 30 | -------------------------------------------------------------------------------- /app/src/main/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_MODULES := libvpx wiregoggles 2 | APP_PLATFORM := android-4 3 | APP_ABI := armeabi-v7a x86 4 | APP_CPPFLAGS += -std=c++11 5 | APP_STL := gnustl_static 6 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/AUTHORS: -------------------------------------------------------------------------------- 1 | # This file is automatically generated from the git commit history 2 | # by tools/gen_authors.sh. 3 | 4 | Aaron Watry 5 | Abo Talib Mahfoodh 6 | Adam Xu 7 | Adrian Grange 8 | Aℓex Converse 9 | Ahmad Sharif 10 | Alexander Voronov 11 | Alexis Ballier 12 | Alok Ahuja 13 | Alpha Lam 14 | A.Mahfoodh 15 | Ami Fischman 16 | Andoni Morales Alastruey 17 | Andres Mejia 18 | Andrew Russell 19 | Angie Chiang 20 | Aron Rosenberg 21 | Attila Nagy 22 | Brion Vibber 23 | changjun.yang 24 | Charles 'Buck' Krasic 25 | chm 26 | Christian Duvivier 27 | Daniel Kang 28 | Deb Mukherjee 29 | Dim Temp 30 | Dmitry Kovalev 31 | Dragan Mrdjan 32 | Ed Baker 33 | Ehsan Akhgari 34 | Erik Niemeyer 35 | Fabio Pedretti 36 | Frank Galligan 37 | Fredrik Söderquist 38 | Fritz Koenig 39 | Gaute Strokkenes 40 | Geza Lore 41 | Ghislain MARY 42 | Giuseppe Scrivano 43 | Gordana Cmiljanovic 44 | Guillaume Martres 45 | Guillermo Ballester Valor 46 | Hangyu Kuang 47 | Hanno Böck 48 | Henrik Lundin 49 | Hui Su 50 | Ivan Maltz 51 | Jacek Caban 52 | Jacky Chen 53 | James Berry 54 | James Yu 55 | James Zern 56 | Jan Gerber 57 | Jan Kratochvil 58 | Janne Salonen 59 | Jeff Faust 60 | Jeff Muizelaar 61 | Jeff Petkau 62 | Jia Jia 63 | Jim Bankoski 64 | Jingning Han 65 | Joey Parrish 66 | Johann Koenig 67 | John Koleszar 68 | Johnny Klonaris 69 | John Stark 70 | Joshua Bleecher Snyder 71 | Joshua Litt 72 | Julia Robson 73 | Justin Clift 74 | Justin Lebar 75 | KO Myung-Hun 76 | Lawrence Velázquez 77 | Lou Quillio 78 | Luca Barbato 79 | Makoto Kato 80 | Mans Rullgard 81 | Marco Paniconi 82 | Mark Mentovai 83 | Martin Ettl 84 | Martin Storsjo 85 | Matthew Heaney 86 | Michael Kohler 87 | Mike Frysinger 88 | Mike Hommey 89 | Mikhal Shemer 90 | Minghai Shang 91 | Morton Jonuschat 92 | Nico Weber 93 | Parag Salasakar 94 | Pascal Massimino 95 | Patrik Westin 96 | Paul Wilkins 97 | Pavol Rusnak 98 | Paweł Hajdan 99 | Pengchong Jin 100 | Peter de Rivaz 101 | Philip Jägenstedt 102 | Priit Laes 103 | Rafael Ávila de Espíndola 104 | Rafaël Carré 105 | Ralph Giles 106 | Rob Bradford 107 | Ronald S. Bultje 108 | Rui Ueyama 109 | Sami Pietilä 110 | Scott Graham 111 | Scott LaVarnway 112 | Sean McGovern 113 | Sergey Ulanov 114 | Shimon Doodkin 115 | Shunyao Li 116 | Stefan Holmer 117 | Suman Sunkara 118 | Taekhyun Kim 119 | Takanori MATSUURA 120 | Tamar Levy 121 | Tao Bai 122 | Tero Rintaluoma 123 | Thijs Vermeir 124 | Tim Kopp 125 | Timothy B. Terriberry 126 | Tom Finegan 127 | Vignesh Venkatasubramanian 128 | Yaowu Xu 129 | Yongzhe Wang 130 | Yunqing Wang 131 | Zoe Liu 132 | Google Inc. 133 | The Mozilla Foundation 134 | The Xiph.Org Foundation 135 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, The WebM Project authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | * Neither the name of Google, nor the WebM Project, nor the names 16 | of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written 18 | permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | ------------------------------------ 3 | 4 | "These implementations" means the copyrightable works that implement the WebM 5 | codecs distributed by Google as part of the WebM Project. 6 | 7 | Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, 8 | royalty-free, irrevocable (except as stated in this section) patent license to 9 | make, have made, use, offer to sell, sell, import, transfer, and otherwise 10 | run, modify and propagate the contents of these implementations of WebM, where 11 | such license applies only to those patent claims, both currently owned by 12 | Google and acquired in the future, licensable by Google that are necessarily 13 | infringed by these implementations of WebM. This grant does not include claims 14 | that would be infringed only as a consequence of further modification of these 15 | implementations. If you or your agent or exclusive licensee institute or order 16 | or agree to the institution of patent litigation or any other patent 17 | enforcement activity against any entity (including a cross-claim or 18 | counterclaim in a lawsuit) alleging that any of these implementations of WebM 19 | or any code incorporated within any of these implementations of WebM 20 | constitute direct or contributory patent infringement, or inducement of 21 | patent infringement, then any patent rights granted to you under this License 22 | for these implementations of WebM shall terminate as of the date such 23 | litigation is filed. 24 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/README: -------------------------------------------------------------------------------- 1 | README - 23 March 2015 2 | 3 | Welcome to the WebM VP8/VP9 Codec SDK! 4 | 5 | COMPILING THE APPLICATIONS/LIBRARIES: 6 | The build system used is similar to autotools. Building generally consists of 7 | "configuring" with your desired build options, then using GNU make to build 8 | the application. 9 | 10 | 1. Prerequisites 11 | 12 | * All x86 targets require the Yasm[1] assembler be installed. 13 | * All Windows builds require that Cygwin[2] be installed. 14 | * Building the documentation requires Doxygen[3]. If you do not 15 | have this package, the install-docs option will be disabled. 16 | * Downloading the data for the unit tests requires curl[4] and sha1sum. 17 | sha1sum is provided via the GNU coreutils, installed by default on 18 | many *nix platforms, as well as MinGW and Cygwin. If coreutils is not 19 | available, a compatible version of sha1sum can be built from 20 | source[5]. These requirements are optional if not running the unit 21 | tests. 22 | 23 | [1]: http://www.tortall.net/projects/yasm 24 | [2]: http://www.cygwin.com 25 | [3]: http://www.doxygen.org 26 | [4]: http://curl.haxx.se 27 | [5]: http://www.microbrew.org/tools/md5sha1sum/ 28 | 29 | 2. Out-of-tree builds 30 | Out of tree builds are a supported method of building the application. For 31 | an out of tree build, the source tree is kept separate from the object 32 | files produced during compilation. For instance: 33 | 34 | $ mkdir build 35 | $ cd build 36 | $ ../libvpx/configure 37 | $ make 38 | 39 | 3. Configuration options 40 | The 'configure' script supports a number of options. The --help option can be 41 | used to get a list of supported options: 42 | $ ../libvpx/configure --help 43 | 44 | 4. Cross development 45 | For cross development, the most notable option is the --target option. The 46 | most up-to-date list of supported targets can be found at the bottom of the 47 | --help output of the configure script. As of this writing, the list of 48 | available targets is: 49 | 50 | armv6-darwin-gcc 51 | armv6-linux-rvct 52 | armv6-linux-gcc 53 | armv6-none-rvct 54 | arm64-darwin-gcc 55 | armv7-android-gcc 56 | armv7-darwin-gcc 57 | armv7-linux-rvct 58 | armv7-linux-gcc 59 | armv7-none-rvct 60 | armv7-win32-vs11 61 | armv7-win32-vs12 62 | armv7-win32-vs14 63 | armv7s-darwin-gcc 64 | mips32-linux-gcc 65 | mips64-linux-gcc 66 | sparc-solaris-gcc 67 | x86-android-gcc 68 | x86-darwin8-gcc 69 | x86-darwin8-icc 70 | x86-darwin9-gcc 71 | x86-darwin9-icc 72 | x86-darwin10-gcc 73 | x86-darwin11-gcc 74 | x86-darwin12-gcc 75 | x86-darwin13-gcc 76 | x86-darwin14-gcc 77 | x86-iphonesimulator-gcc 78 | x86-linux-gcc 79 | x86-linux-icc 80 | x86-os2-gcc 81 | x86-solaris-gcc 82 | x86-win32-gcc 83 | x86-win32-vs7 84 | x86-win32-vs8 85 | x86-win32-vs9 86 | x86-win32-vs10 87 | x86-win32-vs11 88 | x86-win32-vs12 89 | x86-win32-vs14 90 | x86_64-android-gcc 91 | x86_64-darwin9-gcc 92 | x86_64-darwin10-gcc 93 | x86_64-darwin11-gcc 94 | x86_64-darwin12-gcc 95 | x86_64-darwin13-gcc 96 | x86_64-darwin14-gcc 97 | x86_64-iphonesimulator-gcc 98 | x86_64-linux-gcc 99 | x86_64-linux-icc 100 | x86_64-solaris-gcc 101 | x86_64-win64-gcc 102 | x86_64-win64-vs8 103 | x86_64-win64-vs9 104 | x86_64-win64-vs10 105 | x86_64-win64-vs11 106 | x86_64-win64-vs12 107 | x86_64-win64-vs14 108 | generic-gnu 109 | 110 | The generic-gnu target, in conjunction with the CROSS environment variable, 111 | can be used to cross compile architectures that aren't explicitly listed, if 112 | the toolchain is a cross GNU (gcc/binutils) toolchain. Other POSIX toolchains 113 | will likely work as well. For instance, to build using the mipsel-linux-uclibc 114 | toolchain, the following command could be used (note, POSIX SH syntax, adapt 115 | to your shell as necessary): 116 | 117 | $ CROSS=mipsel-linux-uclibc- ../libvpx/configure 118 | 119 | In addition, the executables to be invoked can be overridden by specifying the 120 | environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be 121 | passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS. 122 | 123 | 5. Configuration errors 124 | If the configuration step fails, the first step is to look in the error log. 125 | This defaults to config.log. This should give a good indication of what went 126 | wrong. If not, contact us for support. 127 | 128 | VP8/VP9 TEST VECTORS: 129 | The test vectors can be downloaded and verified using the build system after 130 | running configure. To specify an alternate directory the 131 | LIBVPX_TEST_DATA_PATH environment variable can be used. 132 | 133 | $ ./configure --enable-unit-tests 134 | $ LIBVPX_TEST_DATA_PATH=../libvpx-test-data make testdata 135 | 136 | SUPPORT 137 | This library is an open source project supported by its community. Please 138 | please email webm-discuss@webmproject.org for help. 139 | 140 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/AUTHORS.TXT: -------------------------------------------------------------------------------- 1 | # Names should be added to this file like so: 2 | # Name or Organization 3 | 4 | Google Inc. 5 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_MODULE:= libwebm 5 | LOCAL_SRC_FILES:= mkvparser.cpp \ 6 | mkvreader.cpp \ 7 | mkvmuxer.cpp \ 8 | mkvmuxerutil.cpp \ 9 | mkvwriter.cpp 10 | include $(BUILD_STATIC_LIBRARY) 11 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/LICENSE.TXT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Google Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | * Neither the name of Google nor the names of its contributors may 16 | be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/PATENTS.TXT: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | ------------------------------------ 3 | 4 | "These implementations" means the copyrightable works that implement the WebM 5 | codecs distributed by Google as part of the WebM Project. 6 | 7 | Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, 8 | royalty-free, irrevocable (except as stated in this section) patent license to 9 | make, have made, use, offer to sell, sell, import, transfer, and otherwise 10 | run, modify and propagate the contents of these implementations of WebM, where 11 | such license applies only to those patent claims, both currently owned by 12 | Google and acquired in the future, licensable by Google that are necessarily 13 | infringed by these implementations of WebM. This grant does not include claims 14 | that would be infringed only as a consequence of further modification of these 15 | implementations. If you or your agent or exclusive licensee institute or order 16 | or agree to the institution of patent litigation or any other patent 17 | enforcement activity against any entity (including a cross-claim or 18 | counterclaim in a lawsuit) alleging that any of these implementations of WebM 19 | or any code incorporated within any of these implementations of WebM 20 | constitute direct or contributory patent infringement, or inducement of 21 | patent infringement, then any patent rights granted to you under this License 22 | for these implementations of WebM shall terminate as of the date such 23 | litigation is filed. 24 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/README.libvpx: -------------------------------------------------------------------------------- 1 | URL: https://chromium.googlesource.com/webm/libwebm 2 | Version: 476366249e1fda7710a389cd41c57db42305e0d4 3 | License: BSD 4 | License File: LICENSE.txt 5 | 6 | Description: 7 | libwebm is used to handle WebM container I/O. 8 | 9 | Local Changes: 10 | * 11 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/RELEASE.TXT: -------------------------------------------------------------------------------- 1 | 1.0.0.5 2 | * Handled case when no duration 3 | * Handled empty clusters 4 | * Handled empty clusters when seeking 5 | * Implemented check lacing bits 6 | 7 | 1.0.0.4 8 | * Made Cues member variables mutables 9 | * Defined against badly-formatted cue points 10 | * Segment::GetCluster returns CuePoint too 11 | * Separated cue-based searches 12 | 13 | 1.0.0.3 14 | * Added Block::GetOffset() to get a frame's offset in a block 15 | * Changed cluster count type from size_t to long 16 | * Parsed SeekHead to find cues 17 | * Allowed seeking beyond end of cluster cache 18 | * Added not to attempt to reparse cues element 19 | * Restructured Segment::LoadCluster 20 | * Marked position of cues without parsing cues element 21 | * Allowed cue points to be loaded incrementally 22 | * Implemented to load lazily cue points as they're searched 23 | * Merged Cues::LoadCuePoint into Cues::Find 24 | * Lazy init cues 25 | * Loaded cue point during find 26 | 27 | 1.0.0.2 28 | * added support for Cues element 29 | * seeking was improved 30 | 31 | 1.0.0.1 32 | * fixed item 141 33 | * added item 142 34 | * added this file, RELEASE.TXT, to repository 35 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/mkvmuxertypes.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | 9 | #ifndef MKVMUXERTYPES_HPP 10 | #define MKVMUXERTYPES_HPP 11 | 12 | // Copied from Chromium basictypes.h 13 | // A macro to disallow the copy constructor and operator= functions 14 | // This should be used in the private: declarations for a class 15 | #define LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TypeName) \ 16 | TypeName(const TypeName&); \ 17 | void operator=(const TypeName&) 18 | 19 | namespace mkvmuxer { 20 | 21 | typedef unsigned char uint8; 22 | typedef short int16; 23 | typedef int int32; 24 | typedef unsigned int uint32; 25 | typedef long long int64; 26 | typedef unsigned long long uint64; 27 | 28 | } // end namespace mkvmuxer 29 | 30 | #endif // MKVMUXERTYPES_HPP 31 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/mkvmuxerutil.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | 9 | #ifndef MKVMUXERUTIL_HPP 10 | #define MKVMUXERUTIL_HPP 11 | 12 | #include "mkvmuxer.hpp" 13 | #include "mkvmuxertypes.hpp" 14 | 15 | namespace mkvmuxer { 16 | 17 | class IMkvWriter; 18 | 19 | const uint64 kEbmlUnknownValue = 0x01FFFFFFFFFFFFFFULL; 20 | const int64 kMaxBlockTimecode = 0x07FFFLL; 21 | 22 | // Writes out |value| in Big Endian order. Returns 0 on success. 23 | int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size); 24 | 25 | // Returns the size in bytes of the element. 26 | int32 GetUIntSize(uint64 value); 27 | int32 GetIntSize(int64 value); 28 | int32 GetCodedUIntSize(uint64 value); 29 | uint64 EbmlMasterElementSize(uint64 type, uint64 value); 30 | uint64 EbmlElementSize(uint64 type, int64 value); 31 | uint64 EbmlElementSize(uint64 type, uint64 value); 32 | uint64 EbmlElementSize(uint64 type, float value); 33 | uint64 EbmlElementSize(uint64 type, const char* value); 34 | uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size); 35 | uint64 EbmlDateElementSize(uint64 type); 36 | 37 | // Creates an EBML coded number from |value| and writes it out. The size of 38 | // the coded number is determined by the value of |value|. |value| must not 39 | // be in a coded form. Returns 0 on success. 40 | int32 WriteUInt(IMkvWriter* writer, uint64 value); 41 | 42 | // Creates an EBML coded number from |value| and writes it out. The size of 43 | // the coded number is determined by the value of |size|. |value| must not 44 | // be in a coded form. Returns 0 on success. 45 | int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size); 46 | 47 | // Output an Mkv master element. Returns true if the element was written. 48 | bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 value, uint64 size); 49 | 50 | // Outputs an Mkv ID, calls |IMkvWriter::ElementStartNotify|, and passes the 51 | // ID to |SerializeInt|. Returns 0 on success. 52 | int32 WriteID(IMkvWriter* writer, uint64 type); 53 | 54 | // Output an Mkv non-master element. Returns true if the element was written. 55 | bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value); 56 | bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value); 57 | bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value); 58 | bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value); 59 | bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value, 60 | uint64 size); 61 | bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value); 62 | 63 | // Output a Mkv Frame. It decides the correct element to write (Block vs 64 | // SimpleBlock) based on the parameters of the Frame. 65 | uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame, 66 | Cluster* cluster); 67 | 68 | // Output a void element. |size| must be the entire size in bytes that will be 69 | // void. The function will calculate the size of the void header and subtract 70 | // it from |size|. 71 | uint64 WriteVoidElement(IMkvWriter* writer, uint64 size); 72 | 73 | // Returns the version number of the muxer in |major|, |minor|, |build|, 74 | // and |revision|. 75 | void GetVersion(int32* major, int32* minor, int32* build, int32* revision); 76 | 77 | // Returns a random number to be used for UID, using |seed| to seed 78 | // the random-number generator (see POSIX rand_r() for semantics). 79 | uint64 MakeUID(unsigned int* seed); 80 | 81 | } // end namespace mkvmuxer 82 | 83 | #endif // MKVMUXERUTIL_HPP 84 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/mkvreader.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 The WebM project authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | 9 | #include "mkvreader.hpp" 10 | 11 | #include 12 | 13 | namespace mkvparser { 14 | 15 | MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {} 16 | 17 | MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) { 18 | GetFileSize(); 19 | } 20 | 21 | MkvReader::~MkvReader() { 22 | if (reader_owns_file_) 23 | Close(); 24 | m_file = NULL; 25 | } 26 | 27 | int MkvReader::Open(const char* fileName) { 28 | if (fileName == NULL) 29 | return -1; 30 | 31 | if (m_file) 32 | return -1; 33 | 34 | #ifdef _MSC_VER 35 | const errno_t e = fopen_s(&m_file, fileName, "rb"); 36 | 37 | if (e) 38 | return -1; // error 39 | #else 40 | m_file = fopen(fileName, "rb"); 41 | 42 | if (m_file == NULL) 43 | return -1; 44 | #endif 45 | return !GetFileSize(); 46 | } 47 | 48 | bool MkvReader::GetFileSize() { 49 | if (m_file == NULL) 50 | return false; 51 | #ifdef _MSC_VER 52 | int status = _fseeki64(m_file, 0L, SEEK_END); 53 | 54 | if (status) 55 | return false; // error 56 | 57 | m_length = _ftelli64(m_file); 58 | #else 59 | fseek(m_file, 0L, SEEK_END); 60 | m_length = ftell(m_file); 61 | #endif 62 | assert(m_length >= 0); 63 | 64 | if (m_length < 0) 65 | return false; 66 | 67 | #ifdef _MSC_VER 68 | status = _fseeki64(m_file, 0L, SEEK_SET); 69 | 70 | if (status) 71 | return false; // error 72 | #else 73 | fseek(m_file, 0L, SEEK_SET); 74 | #endif 75 | 76 | return true; 77 | } 78 | 79 | void MkvReader::Close() { 80 | if (m_file != NULL) { 81 | fclose(m_file); 82 | m_file = NULL; 83 | } 84 | } 85 | 86 | int MkvReader::Length(long long* total, long long* available) { 87 | if (m_file == NULL) 88 | return -1; 89 | 90 | if (total) 91 | *total = m_length; 92 | 93 | if (available) 94 | *available = m_length; 95 | 96 | return 0; 97 | } 98 | 99 | int MkvReader::Read(long long offset, long len, unsigned char* buffer) { 100 | if (m_file == NULL) 101 | return -1; 102 | 103 | if (offset < 0) 104 | return -1; 105 | 106 | if (len < 0) 107 | return -1; 108 | 109 | if (len == 0) 110 | return 0; 111 | 112 | if (offset >= m_length) 113 | return -1; 114 | 115 | #ifdef _MSC_VER 116 | const int status = _fseeki64(m_file, offset, SEEK_SET); 117 | 118 | if (status) 119 | return -1; // error 120 | #else 121 | fseek(m_file, offset, SEEK_SET); 122 | #endif 123 | 124 | const size_t size = fread(buffer, 1, len, m_file); 125 | 126 | if (size < size_t(len)) 127 | return -1; // error 128 | 129 | return 0; // success 130 | } 131 | 132 | } // end namespace mkvparser 133 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/mkvreader.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 The WebM project authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | 9 | #ifndef MKVREADER_HPP 10 | #define MKVREADER_HPP 11 | 12 | #include "mkvparser.hpp" 13 | #include 14 | 15 | namespace mkvparser { 16 | 17 | class MkvReader : public IMkvReader { 18 | public: 19 | MkvReader(); 20 | explicit MkvReader(FILE* fp); 21 | virtual ~MkvReader(); 22 | 23 | int Open(const char*); 24 | void Close(); 25 | 26 | virtual int Read(long long position, long length, unsigned char* buffer); 27 | virtual int Length(long long* total, long long* available); 28 | 29 | private: 30 | MkvReader(const MkvReader&); 31 | MkvReader& operator=(const MkvReader&); 32 | 33 | // Determines the size of the file. This is called either by the constructor 34 | // or by the Open function depending on file ownership. Returns true on 35 | // success. 36 | bool GetFileSize(); 37 | 38 | long long m_length; 39 | FILE* m_file; 40 | bool reader_owns_file_; 41 | }; 42 | 43 | } // end namespace mkvparser 44 | 45 | #endif // MKVREADER_HPP 46 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/mkvwriter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | 9 | #include "mkvwriter.hpp" 10 | 11 | #ifdef _MSC_VER 12 | #include // for _SH_DENYWR 13 | #endif 14 | 15 | #include 16 | 17 | namespace mkvmuxer { 18 | 19 | MkvWriter::MkvWriter() : file_(NULL), writer_owns_file_(true) {} 20 | 21 | MkvWriter::MkvWriter(FILE* fp) : file_(fp), writer_owns_file_(false) {} 22 | 23 | MkvWriter::~MkvWriter() { Close(); } 24 | 25 | int32 MkvWriter::Write(const void* buffer, uint32 length) { 26 | if (!file_) 27 | return -1; 28 | 29 | if (length == 0) 30 | return 0; 31 | 32 | if (buffer == NULL) 33 | return -1; 34 | 35 | const size_t bytes_written = fwrite(buffer, 1, length, file_); 36 | 37 | return (bytes_written == length) ? 0 : -1; 38 | } 39 | 40 | bool MkvWriter::Open(const char* filename) { 41 | if (filename == NULL) 42 | return false; 43 | 44 | if (file_) 45 | return false; 46 | 47 | #ifdef _MSC_VER 48 | file_ = _fsopen(filename, "wb", _SH_DENYWR); 49 | #else 50 | file_ = fopen(filename, "wb"); 51 | #endif 52 | if (file_ == NULL) 53 | return false; 54 | return true; 55 | } 56 | 57 | void MkvWriter::Close() { 58 | if (file_ && writer_owns_file_) { 59 | fclose(file_); 60 | } 61 | file_ = NULL; 62 | } 63 | 64 | int64 MkvWriter::Position() const { 65 | if (!file_) 66 | return 0; 67 | 68 | #ifdef _MSC_VER 69 | return _ftelli64(file_); 70 | #else 71 | return ftell(file_); 72 | #endif 73 | } 74 | 75 | int32 MkvWriter::Position(int64 position) { 76 | if (!file_) 77 | return -1; 78 | 79 | #ifdef _MSC_VER 80 | return _fseeki64(file_, position, SEEK_SET); 81 | #else 82 | return fseek(file_, position, SEEK_SET); 83 | #endif 84 | } 85 | 86 | bool MkvWriter::Seekable() const { return true; } 87 | 88 | void MkvWriter::ElementStartNotify(uint64, int64) {} 89 | 90 | } // namespace mkvmuxer 91 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/mkvwriter.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | 9 | #ifndef MKVWRITER_HPP 10 | #define MKVWRITER_HPP 11 | 12 | #include 13 | 14 | #include "mkvmuxer.hpp" 15 | #include "mkvmuxertypes.hpp" 16 | 17 | namespace mkvmuxer { 18 | 19 | // Default implementation of the IMkvWriter interface on Windows. 20 | class MkvWriter : public IMkvWriter { 21 | public: 22 | MkvWriter(); 23 | explicit MkvWriter(FILE* fp); 24 | virtual ~MkvWriter(); 25 | 26 | // IMkvWriter interface 27 | virtual int64 Position() const; 28 | virtual int32 Position(int64 position); 29 | virtual bool Seekable() const; 30 | virtual int32 Write(const void* buffer, uint32 length); 31 | virtual void ElementStartNotify(uint64 element_id, int64 position); 32 | 33 | // Creates and opens a file for writing. |filename| is the name of the file 34 | // to open. This function will overwrite the contents of |filename|. Returns 35 | // true on success. 36 | bool Open(const char* filename); 37 | 38 | // Closes an opened file. 39 | void Close(); 40 | 41 | private: 42 | // File handle to output file. 43 | FILE* file_; 44 | bool writer_owns_file_; 45 | 46 | LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter); 47 | }; 48 | 49 | } // end namespace mkvmuxer 50 | 51 | #endif // MKVWRITER_HPP 52 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/third_party/libwebm/webmids.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | 9 | #ifndef WEBMIDS_HPP 10 | #define WEBMIDS_HPP 11 | 12 | namespace mkvmuxer { 13 | 14 | enum MkvId { 15 | kMkvEBML = 0x1A45DFA3, 16 | kMkvEBMLVersion = 0x4286, 17 | kMkvEBMLReadVersion = 0x42F7, 18 | kMkvEBMLMaxIDLength = 0x42F2, 19 | kMkvEBMLMaxSizeLength = 0x42F3, 20 | kMkvDocType = 0x4282, 21 | kMkvDocTypeVersion = 0x4287, 22 | kMkvDocTypeReadVersion = 0x4285, 23 | kMkvVoid = 0xEC, 24 | kMkvSignatureSlot = 0x1B538667, 25 | kMkvSignatureAlgo = 0x7E8A, 26 | kMkvSignatureHash = 0x7E9A, 27 | kMkvSignaturePublicKey = 0x7EA5, 28 | kMkvSignature = 0x7EB5, 29 | kMkvSignatureElements = 0x7E5B, 30 | kMkvSignatureElementList = 0x7E7B, 31 | kMkvSignedElement = 0x6532, 32 | // segment 33 | kMkvSegment = 0x18538067, 34 | // Meta Seek Information 35 | kMkvSeekHead = 0x114D9B74, 36 | kMkvSeek = 0x4DBB, 37 | kMkvSeekID = 0x53AB, 38 | kMkvSeekPosition = 0x53AC, 39 | // Segment Information 40 | kMkvInfo = 0x1549A966, 41 | kMkvTimecodeScale = 0x2AD7B1, 42 | kMkvDuration = 0x4489, 43 | kMkvDateUTC = 0x4461, 44 | kMkvTitle = 0x7BA9, 45 | kMkvMuxingApp = 0x4D80, 46 | kMkvWritingApp = 0x5741, 47 | // Cluster 48 | kMkvCluster = 0x1F43B675, 49 | kMkvTimecode = 0xE7, 50 | kMkvPrevSize = 0xAB, 51 | kMkvBlockGroup = 0xA0, 52 | kMkvBlock = 0xA1, 53 | kMkvBlockDuration = 0x9B, 54 | kMkvReferenceBlock = 0xFB, 55 | kMkvLaceNumber = 0xCC, 56 | kMkvSimpleBlock = 0xA3, 57 | kMkvBlockAdditions = 0x75A1, 58 | kMkvBlockMore = 0xA6, 59 | kMkvBlockAddID = 0xEE, 60 | kMkvBlockAdditional = 0xA5, 61 | kMkvDiscardPadding = 0x75A2, 62 | // Track 63 | kMkvTracks = 0x1654AE6B, 64 | kMkvTrackEntry = 0xAE, 65 | kMkvTrackNumber = 0xD7, 66 | kMkvTrackUID = 0x73C5, 67 | kMkvTrackType = 0x83, 68 | kMkvFlagEnabled = 0xB9, 69 | kMkvFlagDefault = 0x88, 70 | kMkvFlagForced = 0x55AA, 71 | kMkvFlagLacing = 0x9C, 72 | kMkvDefaultDuration = 0x23E383, 73 | kMkvMaxBlockAdditionID = 0x55EE, 74 | kMkvName = 0x536E, 75 | kMkvLanguage = 0x22B59C, 76 | kMkvCodecID = 0x86, 77 | kMkvCodecPrivate = 0x63A2, 78 | kMkvCodecName = 0x258688, 79 | kMkvCodecDelay = 0x56AA, 80 | kMkvSeekPreRoll = 0x56BB, 81 | // video 82 | kMkvVideo = 0xE0, 83 | kMkvFlagInterlaced = 0x9A, 84 | kMkvStereoMode = 0x53B8, 85 | kMkvAlphaMode = 0x53C0, 86 | kMkvPixelWidth = 0xB0, 87 | kMkvPixelHeight = 0xBA, 88 | kMkvPixelCropBottom = 0x54AA, 89 | kMkvPixelCropTop = 0x54BB, 90 | kMkvPixelCropLeft = 0x54CC, 91 | kMkvPixelCropRight = 0x54DD, 92 | kMkvDisplayWidth = 0x54B0, 93 | kMkvDisplayHeight = 0x54BA, 94 | kMkvDisplayUnit = 0x54B2, 95 | kMkvAspectRatioType = 0x54B3, 96 | kMkvFrameRate = 0x2383E3, 97 | // end video 98 | // audio 99 | kMkvAudio = 0xE1, 100 | kMkvSamplingFrequency = 0xB5, 101 | kMkvOutputSamplingFrequency = 0x78B5, 102 | kMkvChannels = 0x9F, 103 | kMkvBitDepth = 0x6264, 104 | // end audio 105 | // ContentEncodings 106 | kMkvContentEncodings = 0x6D80, 107 | kMkvContentEncoding = 0x6240, 108 | kMkvContentEncodingOrder = 0x5031, 109 | kMkvContentEncodingScope = 0x5032, 110 | kMkvContentEncodingType = 0x5033, 111 | kMkvContentCompression = 0x5034, 112 | kMkvContentCompAlgo = 0x4254, 113 | kMkvContentCompSettings = 0x4255, 114 | kMkvContentEncryption = 0x5035, 115 | kMkvContentEncAlgo = 0x47E1, 116 | kMkvContentEncKeyID = 0x47E2, 117 | kMkvContentSignature = 0x47E3, 118 | kMkvContentSigKeyID = 0x47E4, 119 | kMkvContentSigAlgo = 0x47E5, 120 | kMkvContentSigHashAlgo = 0x47E6, 121 | kMkvContentEncAESSettings = 0x47E7, 122 | kMkvAESSettingsCipherMode = 0x47E8, 123 | kMkvAESSettingsCipherInitData = 0x47E9, 124 | // end ContentEncodings 125 | // Cueing Data 126 | kMkvCues = 0x1C53BB6B, 127 | kMkvCuePoint = 0xBB, 128 | kMkvCueTime = 0xB3, 129 | kMkvCueTrackPositions = 0xB7, 130 | kMkvCueTrack = 0xF7, 131 | kMkvCueClusterPosition = 0xF1, 132 | kMkvCueBlockNumber = 0x5378, 133 | // Chapters 134 | kMkvChapters = 0x1043A770, 135 | kMkvEditionEntry = 0x45B9, 136 | kMkvChapterAtom = 0xB6, 137 | kMkvChapterUID = 0x73C4, 138 | kMkvChapterStringUID = 0x5654, 139 | kMkvChapterTimeStart = 0x91, 140 | kMkvChapterTimeEnd = 0x92, 141 | kMkvChapterDisplay = 0x80, 142 | kMkvChapString = 0x85, 143 | kMkvChapLanguage = 0x437C, 144 | kMkvChapCountry = 0x437E, 145 | // Tags 146 | kMkvTags = 0x1254C367, 147 | kMkvTag = 0x7373, 148 | kMkvSimpleTag = 0x67C8, 149 | kMkvTagName = 0x45A3, 150 | kMkvTagString = 0x4487 151 | }; 152 | 153 | } // end namespace mkvmuxer 154 | 155 | #endif // WEBMIDS_HPP 156 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/tools_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 The WebM 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 | #ifndef TOOLS_COMMON_H_ 11 | #define TOOLS_COMMON_H_ 12 | 13 | #include 14 | 15 | #include "./vpx_config.h" 16 | #include "vpx/vpx_codec.h" 17 | #include "vpx/vpx_image.h" 18 | #include "vpx/vpx_integer.h" 19 | #include "vpx_ports/msvc.h" 20 | 21 | #if CONFIG_ENCODERS 22 | #include "./y4minput.h" 23 | #endif 24 | 25 | #if defined(_MSC_VER) 26 | /* MSVS uses _f{seek,tell}i64. */ 27 | #define fseeko _fseeki64 28 | #define ftello _ftelli64 29 | #elif defined(_WIN32) 30 | /* MinGW uses f{seek,tell}o64 for large files. */ 31 | #define fseeko fseeko64 32 | #define ftello ftello64 33 | #endif /* _WIN32 */ 34 | 35 | #if CONFIG_OS_SUPPORT 36 | #if defined(_MSC_VER) 37 | #include /* NOLINT */ 38 | #define isatty _isatty 39 | #define fileno _fileno 40 | #else 41 | #include /* NOLINT */ 42 | #endif /* _MSC_VER */ 43 | #endif /* CONFIG_OS_SUPPORT */ 44 | 45 | /* Use 32-bit file operations in WebM file format when building ARM 46 | * executables (.axf) with RVCT. */ 47 | #if !CONFIG_OS_SUPPORT 48 | #define fseeko fseek 49 | #define ftello ftell 50 | #endif /* CONFIG_OS_SUPPORT */ 51 | 52 | #define LITERALU64(hi, lo) ((((uint64_t)hi) << 32) | lo) 53 | 54 | #ifndef PATH_MAX 55 | #define PATH_MAX 512 56 | #endif 57 | 58 | #define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */ 59 | #define IVF_FILE_HDR_SZ 32 60 | 61 | #define RAW_FRAME_HDR_SZ sizeof(uint32_t) 62 | 63 | #define VP8_FOURCC 0x30385056 64 | #define VP9_FOURCC 0x30395056 65 | #define VP10_FOURCC 0x303a5056 66 | 67 | enum VideoFileType { 68 | FILE_TYPE_RAW, 69 | FILE_TYPE_IVF, 70 | FILE_TYPE_Y4M, 71 | FILE_TYPE_WEBM 72 | }; 73 | 74 | struct FileTypeDetectionBuffer { 75 | char buf[4]; 76 | size_t buf_read; 77 | size_t position; 78 | }; 79 | 80 | struct VpxRational { 81 | int numerator; 82 | int denominator; 83 | }; 84 | 85 | struct VpxInputContext { 86 | const char *filename; 87 | FILE *file; 88 | int64_t length; 89 | struct FileTypeDetectionBuffer detect; 90 | enum VideoFileType file_type; 91 | uint32_t width; 92 | uint32_t height; 93 | struct VpxRational pixel_aspect_ratio; 94 | vpx_img_fmt_t fmt; 95 | vpx_bit_depth_t bit_depth; 96 | int only_i420; 97 | uint32_t fourcc; 98 | struct VpxRational framerate; 99 | #if CONFIG_ENCODERS 100 | y4m_input y4m; 101 | #endif 102 | }; 103 | 104 | #ifdef __cplusplus 105 | extern "C" { 106 | #endif 107 | 108 | #if defined(__GNUC__) 109 | #define VPX_NO_RETURN __attribute__((noreturn)) 110 | #else 111 | #define VPX_NO_RETURN 112 | #endif 113 | 114 | /* Sets a stdio stream into binary mode */ 115 | FILE *set_binary_mode(FILE *stream); 116 | 117 | void die(const char *fmt, ...) VPX_NO_RETURN; 118 | void fatal(const char *fmt, ...) VPX_NO_RETURN; 119 | void warn(const char *fmt, ...); 120 | 121 | void die_codec(vpx_codec_ctx_t *ctx, const char *s) VPX_NO_RETURN; 122 | 123 | /* The tool including this file must define usage_exit() */ 124 | void usage_exit(void) VPX_NO_RETURN; 125 | 126 | #undef VPX_NO_RETURN 127 | 128 | int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame); 129 | 130 | typedef struct VpxInterface { 131 | const char *const name; 132 | const uint32_t fourcc; 133 | vpx_codec_iface_t *(*const codec_interface)(); 134 | } VpxInterface; 135 | 136 | int get_vpx_encoder_count(void); 137 | const VpxInterface *get_vpx_encoder_by_index(int i); 138 | const VpxInterface *get_vpx_encoder_by_name(const char *name); 139 | 140 | int get_vpx_decoder_count(void); 141 | const VpxInterface *get_vpx_decoder_by_index(int i); 142 | const VpxInterface *get_vpx_decoder_by_name(const char *name); 143 | const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc); 144 | 145 | // TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part 146 | // of vpx_image_t support 147 | int vpx_img_plane_width(const vpx_image_t *img, int plane); 148 | int vpx_img_plane_height(const vpx_image_t *img, int plane); 149 | void vpx_img_write(const vpx_image_t *img, FILE *file); 150 | int vpx_img_read(vpx_image_t *img, FILE *file); 151 | 152 | double sse_to_psnr(double samples, double peak, double mse); 153 | 154 | #if CONFIG_VP9_HIGHBITDEPTH 155 | void vpx_img_upshift(vpx_image_t *dst, vpx_image_t *src, int input_shift); 156 | void vpx_img_downshift(vpx_image_t *dst, vpx_image_t *src, int down_shift); 157 | void vpx_img_truncate_16_to_8(vpx_image_t *dst, vpx_image_t *src); 158 | #endif 159 | 160 | #ifdef __cplusplus 161 | } /* extern "C" */ 162 | #endif 163 | 164 | #endif // TOOLS_COMMON_H_ 165 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/vpx/svc_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 The WebM 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 | /** 12 | * SvcContext - input parameters and state to encode a multi-layered 13 | * spatial SVC frame 14 | */ 15 | 16 | #ifndef VPX_SVC_CONTEXT_H_ 17 | #define VPX_SVC_CONTEXT_H_ 18 | 19 | #include "./vp8cx.h" 20 | #include "./vpx_encoder.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | typedef enum SVC_LOG_LEVEL { 27 | SVC_LOG_ERROR, 28 | SVC_LOG_INFO, 29 | SVC_LOG_DEBUG 30 | } SVC_LOG_LEVEL; 31 | 32 | typedef struct { 33 | // public interface to svc_command options 34 | int spatial_layers; // number of spatial layers 35 | int temporal_layers; // number of temporal layers 36 | int temporal_layering_mode; 37 | SVC_LOG_LEVEL log_level; // amount of information to display 38 | int log_print; // when set, printf log messages instead of returning the 39 | // message with svc_get_message 40 | int output_rc_stat; // for outputting rc stats 41 | int speed; // speed setting for codec 42 | int threads; 43 | int aqmode; // turns on aq-mode=3 (cyclic_refresh): 0=off, 1=on. 44 | // private storage for vpx_svc_encode 45 | void *internal; 46 | } SvcContext; 47 | 48 | #define OPTION_BUFFER_SIZE 1024 49 | #define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v 50 | 51 | typedef struct SvcInternal { 52 | char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options 53 | 54 | // values extracted from option, quantizers 55 | vpx_svc_extra_cfg_t svc_params; 56 | int enable_auto_alt_ref[VPX_SS_MAX_LAYERS]; 57 | int bitrates[VPX_SS_MAX_LAYERS]; 58 | 59 | // accumulated statistics 60 | double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V 61 | uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; 62 | uint32_t bytes_sum[VPX_SS_MAX_LAYERS]; 63 | 64 | // codec encoding values 65 | int width; // width of highest layer 66 | int height; // height of highest layer 67 | int kf_dist; // distance between keyframes 68 | 69 | // state variables 70 | int psnr_pkt_received; 71 | int layer; 72 | int use_multiple_frame_contexts; 73 | 74 | char message_buffer[2048]; 75 | vpx_codec_ctx_t *codec_ctx; 76 | } SvcInternal_t; 77 | 78 | /** 79 | * Set SVC options 80 | * options are supplied as a single string separated by spaces 81 | * Format: encoding-mode= 82 | * layers= 83 | * scaling-factors=/,/,... 84 | * quantizers=,,... 85 | */ 86 | vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options); 87 | 88 | /** 89 | * initialize SVC encoding 90 | */ 91 | vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, 92 | vpx_codec_ctx_t *codec_ctx, 93 | vpx_codec_iface_t *iface, 94 | vpx_codec_enc_cfg_t *cfg); 95 | /** 96 | * encode a frame of video with multiple layers 97 | */ 98 | vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx, 99 | vpx_codec_ctx_t *codec_ctx, 100 | struct vpx_image *rawimg, 101 | vpx_codec_pts_t pts, 102 | int64_t duration, int deadline); 103 | 104 | /** 105 | * finished with svc encoding, release allocated resources 106 | */ 107 | void vpx_svc_release(SvcContext *svc_ctx); 108 | 109 | /** 110 | * dump accumulated statistics and reset accumulated values 111 | */ 112 | const char *vpx_svc_dump_statistics(SvcContext *svc_ctx); 113 | 114 | /** 115 | * get status message from previous encode 116 | */ 117 | const char *vpx_svc_get_message(const SvcContext *svc_ctx); 118 | 119 | #ifdef __cplusplus 120 | } // extern "C" 121 | #endif 122 | 123 | #endif // VPX_SVC_CONTEXT_H_ 124 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/vpx/vpx_frame_buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The WebM 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 | #ifndef VPX_VPX_FRAME_BUFFER_H_ 12 | #define VPX_VPX_FRAME_BUFFER_H_ 13 | 14 | /*!\file 15 | * \brief Describes the decoder external frame buffer interface. 16 | */ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | #include "./vpx_integer.h" 23 | 24 | /*!\brief The maximum number of work buffers used by libvpx. 25 | * Support maximum 4 threads to decode video in parallel. 26 | * Each thread will use one work buffer. 27 | * TODO(hkuang): Add support to set number of worker threads dynamically. 28 | */ 29 | #define VPX_MAXIMUM_WORK_BUFFERS 8 30 | 31 | /*!\brief The maximum number of reference buffers that a VP9 encoder may use. 32 | */ 33 | #define VP9_MAXIMUM_REF_BUFFERS 8 34 | 35 | /*!\brief External frame buffer 36 | * 37 | * This structure holds allocated frame buffers used by the decoder. 38 | */ 39 | typedef struct vpx_codec_frame_buffer { 40 | uint8_t *data; /**< Pointer to the data buffer */ 41 | size_t size; /**< Size of data in bytes */ 42 | void *priv; /**< Frame's private data */ 43 | } vpx_codec_frame_buffer_t; 44 | 45 | /*!\brief get frame buffer callback prototype 46 | * 47 | * This callback is invoked by the decoder to retrieve data for the frame 48 | * buffer in order for the decode call to complete. The callback must 49 | * allocate at least min_size in bytes and assign it to fb->data. The callback 50 | * must zero out all the data allocated. Then the callback must set fb->size 51 | * to the allocated size. The application does not need to align the allocated 52 | * data. The callback is triggered when the decoder needs a frame buffer to 53 | * decode a compressed image into. This function may be called more than once 54 | * for every call to vpx_codec_decode. The application may set fb->priv to 55 | * some data which will be passed back in the ximage and the release function 56 | * call. |fb| is guaranteed to not be NULL. On success the callback must 57 | * return 0. Any failure the callback must return a value less than 0. 58 | * 59 | * \param[in] priv Callback's private data 60 | * \param[in] new_size Size in bytes needed by the buffer 61 | * \param[in,out] fb Pointer to vpx_codec_frame_buffer_t 62 | */ 63 | typedef int (*vpx_get_frame_buffer_cb_fn_t)( 64 | void *priv, size_t min_size, vpx_codec_frame_buffer_t *fb); 65 | 66 | /*!\brief release frame buffer callback prototype 67 | * 68 | * This callback is invoked by the decoder when the frame buffer is not 69 | * referenced by any other buffers. |fb| is guaranteed to not be NULL. On 70 | * success the callback must return 0. Any failure the callback must return 71 | * a value less than 0. 72 | * 73 | * \param[in] priv Callback's private data 74 | * \param[in] fb Pointer to vpx_codec_frame_buffer_t 75 | */ 76 | typedef int (*vpx_release_frame_buffer_cb_fn_t)( 77 | void *priv, vpx_codec_frame_buffer_t *fb); 78 | 79 | #ifdef __cplusplus 80 | } // extern "C" 81 | #endif 82 | 83 | #endif // VPX_VPX_FRAME_BUFFER_H_ 84 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/vpx/vpx_integer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 The WebM 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 | 12 | #ifndef VPX_VPX_INTEGER_H_ 13 | #define VPX_VPX_INTEGER_H_ 14 | 15 | /* get ptrdiff_t, size_t, wchar_t, NULL */ 16 | #include 17 | 18 | #if defined(_MSC_VER) 19 | #define VPX_FORCE_INLINE __forceinline 20 | #define VPX_INLINE __inline 21 | #else 22 | #define VPX_FORCE_INLINE __inline__ __attribute__(always_inline) 23 | // TODO(jbb): Allow a way to force inline off for older compilers. 24 | #define VPX_INLINE inline 25 | #endif 26 | 27 | #if (defined(_MSC_VER) && (_MSC_VER < 1600)) || defined(VPX_EMULATE_INTTYPES) 28 | typedef signed char int8_t; 29 | typedef signed short int16_t; 30 | typedef signed int int32_t; 31 | 32 | typedef unsigned char uint8_t; 33 | typedef unsigned short uint16_t; 34 | typedef unsigned int uint32_t; 35 | 36 | #if (defined(_MSC_VER) && (_MSC_VER < 1600)) 37 | typedef signed __int64 int64_t; 38 | typedef unsigned __int64 uint64_t; 39 | #define INT64_MAX _I64_MAX 40 | #define INT32_MAX _I32_MAX 41 | #define INT32_MIN _I32_MIN 42 | #define INT16_MAX _I16_MAX 43 | #define INT16_MIN _I16_MIN 44 | #endif 45 | 46 | #ifndef _UINTPTR_T_DEFINED 47 | typedef size_t uintptr_t; 48 | #endif 49 | 50 | #else 51 | 52 | /* Most platforms have the C99 standard integer types. */ 53 | 54 | #if defined(__cplusplus) 55 | # if !defined(__STDC_FORMAT_MACROS) 56 | # define __STDC_FORMAT_MACROS 57 | # endif 58 | # if !defined(__STDC_LIMIT_MACROS) 59 | # define __STDC_LIMIT_MACROS 60 | # endif 61 | #endif // __cplusplus 62 | 63 | #include 64 | 65 | #endif 66 | 67 | /* VS2010 defines stdint.h, but not inttypes.h */ 68 | #if defined(_MSC_VER) && _MSC_VER < 1800 69 | #define PRId64 "I64d" 70 | #else 71 | #include 72 | #endif 73 | 74 | #endif // VPX_VPX_INTEGER_H_ 75 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/vpx_config.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011 The WebM project authors. All Rights Reserved. */ 2 | /* */ 3 | /* Use of this source code is governed by a BSD-style license */ 4 | /* that can be found in the LICENSE file in the root of the source */ 5 | /* tree. An additional intellectual property rights grant can be found */ 6 | /* in the file PATENTS. All contributing project authors may */ 7 | /* be found in the AUTHORS file in the root of the source tree. */ 8 | /* This file automatically generated by configure. Do not edit! */ 9 | #ifndef VPX_CONFIG_H 10 | #define VPX_CONFIG_H 11 | #define RESTRICT 12 | #define INLINE inline 13 | #define ARCH_ARM 1 14 | #define ARCH_MIPS 0 15 | #define ARCH_X86 0 16 | #define ARCH_X86_64 0 17 | #define HAVE_EDSP 0 18 | #define HAVE_MEDIA 1 19 | #define HAVE_NEON 0 20 | #define HAVE_NEON_ASM 0 21 | #define HAVE_MIPS32 0 22 | #define HAVE_DSPR2 0 23 | #define HAVE_MSA 0 24 | #define HAVE_MIPS64 0 25 | #define HAVE_MMX 0 26 | #define HAVE_SSE 0 27 | #define HAVE_SSE2 0 28 | #define HAVE_SSE3 0 29 | #define HAVE_SSSE3 0 30 | #define HAVE_SSE4_1 0 31 | #define HAVE_AVX 0 32 | #define HAVE_AVX2 0 33 | #define HAVE_VPX_PORTS 1 34 | #define HAVE_STDINT_H 1 35 | #define HAVE_PTHREAD_H 1 36 | #define HAVE_SYS_MMAN_H 1 37 | #define HAVE_UNISTD_H 1 38 | #define CONFIG_DEPENDENCY_TRACKING 1 39 | #define CONFIG_EXTERNAL_BUILD 0 40 | #define CONFIG_INSTALL_DOCS 0 41 | #define CONFIG_INSTALL_BINS 1 42 | #define CONFIG_INSTALL_LIBS 1 43 | #define CONFIG_INSTALL_SRCS 0 44 | #define CONFIG_USE_X86INC 0 45 | #define CONFIG_DEBUG 0 46 | #define CONFIG_GPROF 0 47 | #define CONFIG_GCOV 0 48 | #define CONFIG_RVCT 0 49 | #define CONFIG_GCC 1 50 | #define CONFIG_MSVS 0 51 | #define CONFIG_PIC 1 52 | #define CONFIG_BIG_ENDIAN 0 53 | #define CONFIG_CODEC_SRCS 0 54 | #define CONFIG_DEBUG_LIBS 0 55 | #define CONFIG_DEQUANT_TOKENS 0 56 | #define CONFIG_DC_RECON 0 57 | #define CONFIG_RUNTIME_CPU_DETECT 0 58 | #define CONFIG_POSTPROC 0 59 | #define CONFIG_VP9_POSTPROC 0 60 | #define CONFIG_MULTITHREAD 1 61 | #define CONFIG_INTERNAL_STATS 0 62 | #define CONFIG_VP8_ENCODER 1 63 | #define CONFIG_VP8_DECODER 1 64 | #define CONFIG_VP9_ENCODER 0 65 | #define CONFIG_VP9_DECODER 0 66 | #define CONFIG_VP10_ENCODER 0 67 | #define CONFIG_VP10_DECODER 0 68 | #define CONFIG_VP8 1 69 | #define CONFIG_VP9 0 70 | #define CONFIG_VP10 0 71 | #define CONFIG_ENCODERS 1 72 | #define CONFIG_DECODERS 1 73 | #define CONFIG_STATIC_MSVCRT 0 74 | #define CONFIG_SPATIAL_RESAMPLING 1 75 | #define CONFIG_REALTIME_ONLY 1 76 | #define CONFIG_ONTHEFLY_BITPACKING 0 77 | #define CONFIG_ERROR_CONCEALMENT 0 78 | #define CONFIG_SHARED 0 79 | #define CONFIG_STATIC 1 80 | #define CONFIG_SMALL 1 81 | #define CONFIG_POSTPROC_VISUALIZER 0 82 | #define CONFIG_OS_SUPPORT 1 83 | #define CONFIG_UNIT_TESTS 0 84 | #define CONFIG_WEBM_IO 1 85 | #define CONFIG_LIBYUV 1 86 | #define CONFIG_DECODE_PERF_TESTS 0 87 | #define CONFIG_ENCODE_PERF_TESTS 0 88 | #define CONFIG_MULTI_RES_ENCODING 0 89 | #define CONFIG_TEMPORAL_DENOISING 1 90 | #define CONFIG_VP9_TEMPORAL_DENOISING 0 91 | #define CONFIG_COEFFICIENT_RANGE_CHECKING 0 92 | #define CONFIG_VP9_HIGHBITDEPTH 0 93 | #define CONFIG_BETTER_HW_COMPATIBILITY 0 94 | #define CONFIG_EXPERIMENTAL 0 95 | #define CONFIG_SIZE_LIMIT 0 96 | #define CONFIG_SPATIAL_SVC 0 97 | #define CONFIG_FP_MB_STATS 0 98 | #define CONFIG_EMULATE_HARDWARE 0 99 | #define CONFIG_MISC_FIXES 0 100 | #endif /* VPX_CONFIG_H */ 101 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/vpx_ports/msvc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebM 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 | #ifndef VPX_PORTS_MSVC_H_ 12 | #define VPX_PORTS_MSVC_H_ 13 | #ifdef _MSC_VER 14 | 15 | #include "./vpx_config.h" 16 | 17 | # if _MSC_VER < 1900 // VS2015 provides snprintf 18 | # define snprintf _snprintf 19 | # endif // _MSC_VER < 1900 20 | 21 | #if _MSC_VER < 1800 // VS2013 provides round 22 | #include 23 | static INLINE double round(double x) { 24 | if (x < 0) 25 | return ceil(x - 0.5); 26 | else 27 | return floor(x + 0.5); 28 | } 29 | #endif // _MSC_VER < 1800 30 | 31 | #endif // _MSC_VER 32 | #endif // VPX_PORTS_MSVC_H_ 33 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/webmenc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The WebM 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 | #include "./webmenc.h" 11 | 12 | #include 13 | 14 | #include "third_party/libwebm/mkvmuxer.hpp" 15 | #include "third_party/libwebm/mkvmuxerutil.hpp" 16 | #include "third_party/libwebm/mkvwriter.hpp" 17 | 18 | namespace { 19 | const uint64_t kDebugTrackUid = 0xDEADBEEF; 20 | const int kVideoTrackNumber = 1; 21 | } // namespace 22 | 23 | void write_webm_file_header(struct EbmlGlobal *glob, 24 | const vpx_codec_enc_cfg_t *cfg, 25 | const struct vpx_rational *fps, 26 | stereo_format_t stereo_fmt, 27 | unsigned int fourcc, 28 | const struct VpxRational *par) { 29 | mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(glob->stream); 30 | mkvmuxer::Segment *const segment = new mkvmuxer::Segment(); 31 | segment->Init(writer); 32 | segment->set_mode(mkvmuxer::Segment::kFile); 33 | segment->OutputCues(true); 34 | 35 | mkvmuxer::SegmentInfo *const info = segment->GetSegmentInfo(); 36 | const uint64_t kTimecodeScale = 1000000; 37 | info->set_timecode_scale(kTimecodeScale); 38 | std::string version = "vpxenc"; 39 | if (!glob->debug) { 40 | version.append(std::string(" ") + vpx_codec_version_str()); 41 | } 42 | info->set_writing_app(version.c_str()); 43 | 44 | const uint64_t video_track_id = 45 | segment->AddVideoTrack(static_cast(cfg->g_w), 46 | static_cast(cfg->g_h), 47 | kVideoTrackNumber); 48 | mkvmuxer::VideoTrack* const video_track = 49 | static_cast( 50 | segment->GetTrackByNumber(video_track_id)); 51 | video_track->SetStereoMode(stereo_fmt); 52 | const char *codec_id; 53 | switch (fourcc) { 54 | case VP8_FOURCC: 55 | codec_id = "V_VP8"; 56 | break; 57 | case VP9_FOURCC: 58 | codec_id = "V_VP9"; 59 | break; 60 | case VP10_FOURCC: 61 | codec_id = "V_VP10"; 62 | break; 63 | default: 64 | codec_id = "V_VP10"; 65 | break; 66 | } 67 | video_track->set_codec_id(codec_id); 68 | if (par->numerator > 1 || par->denominator > 1) { 69 | // TODO(fgalligan): Add support of DisplayUnit, Display Aspect Ratio type 70 | // to WebM format. 71 | const uint64_t display_width = 72 | static_cast(((cfg->g_w * par->numerator * 1.0) / 73 | par->denominator) + .5); 74 | video_track->set_display_width(display_width); 75 | video_track->set_display_height(cfg->g_h); 76 | } 77 | if (glob->debug) { 78 | video_track->set_uid(kDebugTrackUid); 79 | } 80 | glob->writer = writer; 81 | glob->segment = segment; 82 | } 83 | 84 | void write_webm_block(struct EbmlGlobal *glob, 85 | const vpx_codec_enc_cfg_t *cfg, 86 | const vpx_codec_cx_pkt_t *pkt) { 87 | mkvmuxer::Segment *const segment = 88 | reinterpret_cast(glob->segment); 89 | int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * 90 | cfg->g_timebase.num / cfg->g_timebase.den; 91 | if (pts_ns <= glob->last_pts_ns) 92 | pts_ns = glob->last_pts_ns + 1000000; 93 | glob->last_pts_ns = pts_ns; 94 | 95 | segment->AddFrame(static_cast(pkt->data.frame.buf), 96 | pkt->data.frame.sz, 97 | kVideoTrackNumber, 98 | pts_ns, 99 | pkt->data.frame.flags & VPX_FRAME_IS_KEY); 100 | } 101 | 102 | void write_webm_file_footer(struct EbmlGlobal *glob) { 103 | mkvmuxer::MkvWriter *const writer = 104 | reinterpret_cast(glob->writer); 105 | mkvmuxer::Segment *const segment = 106 | reinterpret_cast(glob->segment); 107 | segment->Finalize(); 108 | delete segment; 109 | delete writer; 110 | glob->writer = NULL; 111 | glob->segment = NULL; 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/webmenc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 The WebM 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 | #ifndef WEBMENC_H_ 11 | #define WEBMENC_H_ 12 | 13 | #include 14 | #include 15 | 16 | #include "tools_common.h" 17 | #include "vpx/vpx_encoder.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /* TODO(vigneshv): Rename this struct */ 24 | struct EbmlGlobal { 25 | int debug; 26 | FILE *stream; 27 | int64_t last_pts_ns; 28 | void *writer; 29 | void *segment; 30 | }; 31 | 32 | /* Stereo 3D packed frame format */ 33 | typedef enum stereo_format { 34 | STEREO_FORMAT_MONO = 0, 35 | STEREO_FORMAT_LEFT_RIGHT = 1, 36 | STEREO_FORMAT_BOTTOM_TOP = 2, 37 | STEREO_FORMAT_TOP_BOTTOM = 3, 38 | STEREO_FORMAT_RIGHT_LEFT = 11 39 | } stereo_format_t; 40 | 41 | void write_webm_file_header(struct EbmlGlobal *glob, 42 | const vpx_codec_enc_cfg_t *cfg, 43 | const struct vpx_rational *fps, 44 | stereo_format_t stereo_fmt, 45 | unsigned int fourcc, 46 | const struct VpxRational *par); 47 | 48 | void write_webm_block(struct EbmlGlobal *glob, 49 | const vpx_codec_enc_cfg_t *cfg, 50 | const vpx_codec_cx_pkt_t *pkt); 51 | 52 | void write_webm_file_footer(struct EbmlGlobal *glob); 53 | 54 | #ifdef __cplusplus 55 | } // extern "C" 56 | #endif 57 | 58 | #endif // WEBMENC_H_ 59 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx/y4minput.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010 The WebM 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 | * Based on code from the OggTheora software codec source code, 11 | * Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors. 12 | */ 13 | 14 | #ifndef Y4MINPUT_H_ 15 | #define Y4MINPUT_H_ 16 | 17 | # include 18 | # include "vpx/vpx_image.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | 25 | 26 | typedef struct y4m_input y4m_input; 27 | 28 | 29 | 30 | /*The function used to perform chroma conversion.*/ 31 | typedef void (*y4m_convert_func)(y4m_input *_y4m, 32 | unsigned char *_dst, unsigned char *_src); 33 | 34 | 35 | 36 | struct y4m_input { 37 | int pic_w; 38 | int pic_h; 39 | int fps_n; 40 | int fps_d; 41 | int par_n; 42 | int par_d; 43 | char interlace; 44 | int src_c_dec_h; 45 | int src_c_dec_v; 46 | int dst_c_dec_h; 47 | int dst_c_dec_v; 48 | char chroma_type[16]; 49 | /*The size of each converted frame buffer.*/ 50 | size_t dst_buf_sz; 51 | /*The amount to read directly into the converted frame buffer.*/ 52 | size_t dst_buf_read_sz; 53 | /*The size of the auxilliary buffer.*/ 54 | size_t aux_buf_sz; 55 | /*The amount to read into the auxilliary buffer.*/ 56 | size_t aux_buf_read_sz; 57 | y4m_convert_func convert; 58 | unsigned char *dst_buf; 59 | unsigned char *aux_buf; 60 | enum vpx_img_fmt vpx_fmt; 61 | int bps; 62 | unsigned int bit_depth; 63 | }; 64 | 65 | int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip, 66 | int only_420); 67 | void y4m_input_close(y4m_input *_y4m); 68 | int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *img); 69 | 70 | #ifdef __cplusplus 71 | } // extern "C" 72 | #endif 73 | 74 | #endif // Y4MINPUT_H_ 75 | -------------------------------------------------------------------------------- /app/src/main/jni/libvpx_prebuilt_libs/armeabi-v7a/libvpx.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/jni/libvpx_prebuilt_libs/armeabi-v7a/libvpx.a -------------------------------------------------------------------------------- /app/src/main/jni/libvpx_prebuilt_libs/x86/libvpx.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/jni/libvpx_prebuilt_libs/x86/libvpx.a -------------------------------------------------------------------------------- /app/src/main/jni/test_wg_video.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "vpx/vpx_encoder.h" 4 | #include "vpx/vp8cx.h" 5 | #include "vpx/vpx_decoder.h" 6 | #define interface (&vpx_codec_vp8_cx_algo) 7 | 8 | // include vpxenc example source directly because it has lots of useful functions 9 | #include "vpxenc.c" 10 | 11 | int test_vpx() { 12 | vpx_codec_enc_cfg_t cfg; 13 | FILE *outfile; 14 | vpx_image_t vpx_image; 15 | vpx_codec_ctx_t codec; 16 | EbmlGlobal ebml = {0}; 17 | struct vpx_rational arg_framerate = {30, 1}; 18 | uint32_t hash = 0; 19 | 20 | if (0!=vpx_codec_enc_config_default(interface, &cfg, 0)) return 1000; 21 | cfg.g_w = 480; 22 | cfg.g_h = 320; 23 | 24 | outfile = fopen("/mnt/sdcard/1.webm", "wb"); 25 | if (!outfile) return 1000; 26 | 27 | if (!vpx_img_alloc(&vpx_image, VPX_IMG_FMT_YV12, cfg.g_w, cfg.g_h, 1)) return 1001; 28 | 29 | if (0!=vpx_codec_enc_init(&codec, interface, &cfg, 0)) return 1002; 30 | 31 | 32 | ebml.stream = outfile; 33 | write_webm_file_header(&ebml, &cfg, &arg_framerate); 34 | 35 | int numFrames = 127; 36 | int frameCounter = 0; 37 | while (frameCounter <= numFrames) { 38 | if (frameCounter < numFrames) { 39 | unsigned char *yplane = vpx_image.planes[0]; 40 | int index = 0; 41 | int x,y; 42 | for(y=0; ykind) { 69 | case VPX_CODEC_CX_FRAME_PKT: 70 | hash = murmur(pkt->data.frame.buf, pkt->data.frame.sz, hash); 71 | write_webm_block(&ebml, &cfg, pkt); 72 | break; 73 | } 74 | } 75 | 76 | frameCounter++; 77 | } 78 | 79 | 80 | write_webm_file_footer(&ebml, hash); 81 | 82 | if (0!=vpx_codec_destroy(&codec)) return 1099; 83 | fclose(outfile); 84 | 85 | return 11; 86 | } 87 | 88 | #include 89 | jint Java_com_dozingcatsoftware_eyeball_EyeballMain_testVPX(JNIEnv* env, jobject thiz) { 90 | return test_vpx(); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_camera_shutter_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/btn_camera_shutter_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_camera_shutter_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/btn_camera_shutter_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_video_shutter_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/btn_video_shutter_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_video_shutter_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/btn_video_shutter_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_video_shutter_recording_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/btn_video_shutter_recording_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_video_shutter_recording_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/btn_video_shutter_recording_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_camera_front_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_camera_front_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_camera_rear_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_camera_rear_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_help_outline_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_help_outline_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_pause_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_pause_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_photo_camera_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_photo_camera_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_photo_library_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_photo_library_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_play_arrow_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_play_arrow_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_settings_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_skip_next_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_skip_next_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_skip_previous_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_skip_previous_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_videocam_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/ic_videocam_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/mediatab_bg_selected.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/mediatab_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/mediatab_bg_unselected.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_camera_shutter_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/btn_camera_shutter_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_camera_shutter_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/btn_camera_shutter_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_video_shutter_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/btn_video_shutter_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_video_shutter_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/btn_video_shutter_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_video_shutter_recording_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/btn_video_shutter_recording_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_video_shutter_recording_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/btn_video_shutter_recording_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_camera_front_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_camera_front_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_camera_rear_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_camera_rear_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_help_outline_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_help_outline_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_pause_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_pause_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_photo_camera_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_photo_camera_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_photo_library_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_photo_library_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_play_arrow_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_play_arrow_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_settings_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_skip_next_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_skip_next_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_skip_previous_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_skip_previous_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_videocam_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/ic_videocam_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_camera_shutter_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/btn_camera_shutter_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_camera_shutter_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/btn_camera_shutter_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_video_shutter_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/btn_video_shutter_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_video_shutter_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/btn_video_shutter_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_video_shutter_recording_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/btn_video_shutter_recording_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_video_shutter_recording_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/btn_video_shutter_recording_pressed_holo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_camera_front_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_camera_front_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_camera_rear_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_camera_rear_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_help_outline_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_help_outline_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_pause_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_pause_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_photo_camera_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_photo_camera_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_photo_library_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_photo_library_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_play_arrow_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_settings_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_skip_next_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_skip_next_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_skip_previous_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_skip_previous_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_videocam_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xhdpi/ic_videocam_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_camera_front_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_camera_front_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_camera_rear_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_camera_rear_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_help_outline_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_help_outline_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_pause_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_pause_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_photo_camera_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_photo_camera_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_photo_library_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_photo_library_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_settings_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_skip_next_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_skip_next_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_skip_previous_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_skip_previous_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_videocam_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dozingcat/WireGoggles/04b753dae81d40e0b4e738c2d63f33f5c685af84/app/src/main/res/drawable-xxxhdpi/ic_videocam_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/layout/about.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/colorpicker.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | 26 | 31 | 32 | 38 | 47 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/custom_colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 13 |