├── README.markdown
├── android-ffmpeg-prototype.apk
└── android-ffmpeg-prototype
├── .classpath
├── .project
├── AndroidManifest.xml
├── assets
├── bootstrap.amr
├── split.sh
├── xaa
├── xab
└── xac
├── bin
├── android-ffmpeg-prototype.apk
├── classes.dex
├── com
│ └── camundo
│ │ ├── Camundo.class
│ │ ├── FFMPEGPrototype$1.class
│ │ ├── FFMPEGPrototype$2.class
│ │ ├── FFMPEGPrototype.class
│ │ ├── R$attr.class
│ │ ├── R$drawable.class
│ │ ├── R$id.class
│ │ ├── R$layout.class
│ │ ├── R$menu.class
│ │ ├── R$string.class
│ │ └── R.class
└── resources.ap_
├── default.properties
├── etc
├── adpcm.txt
└── nellymoser.txt
├── gen
└── com
│ └── camundo
│ └── R.java
├── proguard.cfg
├── res
├── drawable-hdpi
│ ├── icon.png
│ └── menu_quit.png
├── drawable-ldpi
│ └── icon.png
├── drawable-mdpi
│ └── icon.png
├── layout
│ ├── audio.xml
│ ├── main.xml
│ └── round_rect.xml
├── menu
│ └── main_menu.xml
└── values
│ └── strings.xml
└── src
└── com
└── camundo
├── AudioActivity.java
├── AudioCall.java
├── Camundo.java
├── FFMPEGPrototype.java
├── media
├── AudioPublisher.java
├── AudioSubscriber.java
└── pipe
│ ├── AudioInputPipe.java
│ ├── AudioOutputPipe.java
│ ├── FFMPEGAudioInputPipe.java
│ ├── FFMPEGAudioOutputPipe.java
│ ├── FileAudioOutputPipe.java
│ └── PipeFactory.java
└── util
├── AudioCodec.java
├── FFMPEGBootstrap.java
├── FFMPEGWrapper.java
├── NetworkUtils.java
└── WavInfo.java
/README.markdown:
--------------------------------------------------------------------------------
1 |
Description
2 |
3 |
4 | Little prototype for streaming audio.
5 |
6 |
7 |
8 | Target is the android platform ( APK 8 ).
9 | For the moment it streams audio from the microphone to a RTMP server and can receive it back.
10 | http://www.youtube.com/watch?v=pqUUL0QwuMo
11 |
12 |
13 |
14 |
15 |
16 |
17 | To do
18 |
19 | Latency is approximately 2-3 seconds depending the network.
20 | Add video
21 | Tune FFMPEG build
22 | Streaming from files can be added
23 |
24 |
25 |
26 |
27 |
28 |
29 | FFMPEG
30 | FFMPEG is wrapped and accessed via java using pipes :)
31 |
32 |
33 | Enabled decoders:
34 | aac amrnb h263
35 | adpcm_swf flv nellymoser
36 |
37 | Enabled encoders:
38 | aac h263 pcm_s16le
39 | adpcm_swf nellymoser pcm_u8
40 | flv
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype.apk
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | android-ffmpeg-prototype
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/assets/bootstrap.amr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/assets/bootstrap.amr
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/assets/split.sh:
--------------------------------------------------------------------------------
1 | split --bytes=1MB /home/wouter/applications/ffmpeg-android/ffmpeg-android/ffmpeg/ffmpeg
2 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/assets/xaa:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/assets/xaa
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/assets/xab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/assets/xab
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/assets/xac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/assets/xac
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/android-ffmpeg-prototype.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/android-ffmpeg-prototype.apk
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/classes.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/classes.dex
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/Camundo.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/Camundo.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/FFMPEGPrototype$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/FFMPEGPrototype$1.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/FFMPEGPrototype$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/FFMPEGPrototype$2.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/FFMPEGPrototype.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/FFMPEGPrototype.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/R$attr.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/R$attr.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/R$drawable.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/R$drawable.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/R$id.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/R$id.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/R$layout.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/R$layout.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/R$menu.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/R$menu.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/R$string.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/R$string.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/com/camundo/R.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/com/camundo/R.class
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/bin/resources.ap_:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/bin/resources.ap_
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/default.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "build.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-8
12 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/etc/adpcm.txt:
--------------------------------------------------------------------------------
1 | 03-05 10:02:10.990: INFO/System.out(19726): [ streamToRtmp() ] [/data/data/com.camundo/ffmpeg -analyzeduration 0 -i pipe:0 -re -vn -acodec adpcm_swf -ar 11025 -ac 1 -f flv rtmp://camundo.com:1935/test/kaka]
2 | 03-05 10:02:11.070: DEBUG/FFMPEGInputPipe(19726): [ run() ] os : java.lang.ProcessManager$ProcessOutputStream@44956640
3 | 03-05 10:02:11.150: DEBUG/FFMPEGInputPipe(19726): FFmpeg version git-c3897d7, Copyright (c) 2000-2011 the FFmpeg developers
4 | 03-05 10:02:11.160: DEBUG/FFMPEGInputPipe(19726): built on Mar 5 2011 01:03:24 with gcc 4.4.0
5 | 03-05 10:02:11.400: DEBUG/FFMPEGInputPipe(19726): configuration: --target-os=linux --cross-prefix=arm-eabi- --arch=arm --disable-armvfp --prefix=../build/ffmpeg --disable-shared --disable-encoders --disable-decoders --disable-protocols --enable-muxers --enable-demuxers --enable-parsers --disable-devices --enable-filters --disable-bsfs --enable-encoder=adpcm_swf --enable-decoder=adpcm_swf --enable-decoder=nellymoser --enable-encoder=nellymoser --enable-encoder=flv --enable-protocol=pipe --enable-protocol=file --enable-protocol=rtmp --enable-decoder=amrnb --enable-decoder=flv --enable-encoder=pcm_u8 --enable-encoder=pcm_s16le --enable-encoder=aac --disable-frei0r --disable-demuxer=ea --disable-muxer=mov --disable-demuxer=mov --disable-demuxer=matroska --disable-muxer=matroska --disable-muxer=matroska_audio --disable-demuxer=mpc --disable-demuxer=mpc8 --disable-ffprobe --extra-cflags='-I/home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -march=armv5te -mtune=xscale -msoft-float' --extra-ldflags='-nostdlib /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/libc.so /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/libm.so -Wl,-rpath-link=/home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib -L/home/wouter/applications/android-ndk/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/lib/gcc/arm-eabi/4.4.0' --extra-ldflags='-Wl,-dynamic-linker,/system/bin/linker /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/crtbegin_dynamic.o /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/crtend_android.o' --extra-libs=-lgcc
6 | 03-05 10:02:11.400: DEBUG/FFMPEGInputPipe(19726): libavutil 50.36. 0 / 50.36. 0
7 | 03-05 10:02:11.410: DEBUG/FFMPEGInputPipe(19726): libavcore 0.16. 1 / 0.16. 1
8 | 03-05 10:02:11.420: DEBUG/FFMPEGInputPipe(19726): libavcodec 52.108. 0 / 52.108. 0
9 | 03-05 10:02:11.430: DEBUG/FFMPEGInputPipe(19726): libavformat 52.94. 0 / 52.94. 0
10 | 03-05 10:02:11.440: DEBUG/FFMPEGInputPipe(19726): libavdevice 52. 2. 3 / 52. 2. 3
11 | 03-05 10:02:11.450: DEBUG/FFMPEGInputPipe(19726): libavfilter 1.74. 0 / 1.74. 0
12 | 03-05 10:02:11.450: DEBUG/FFMPEGInputPipe(19726): libswscale 0.12. 0 / 0.12. 0
13 | 03-05 10:02:11.470: INFO/AudioPublisher(19726): [ run() ] input [android.net.LocalSocketImpl$SocketInputStream@44960178]
14 | 03-05 10:02:11.470: DEBUG/FFMPEGInputPipe(19726): [amr @ 0x43cd90] max_analyze_duration reached
15 | 03-05 10:02:11.480: INFO/[FFMPEGPrototype(19726): connected to socket
16 | 03-05 10:02:11.490: DEBUG/FFMPEGInputPipe(19726): [amr @ 0x43cd90] Estimating duration from bitrate, this may be inaccurate
17 | 03-05 10:02:11.500: VERBOSE/MediaProfiles(73): getInstance
18 | 03-05 10:02:11.510: ERROR/audio_input(73): unsupported parameter: x-pvmf/media-input-node/cap-config-interface;valtype=key_specific_value
19 | 03-05 10:02:11.510: ERROR/audio_input(73): VerifyAndSetParameter failed
20 | 03-05 10:02:11.510: DEBUG/FFMPEGInputPipe(19726): Input #0, amr, from 'pipe:0':
21 | 03-05 10:02:11.540: DEBUG/FFMPEGInputPipe(19726): Duration: N/A, bitrate: N/A
22 | 03-05 10:02:11.550: DEBUG/FFMPEGInputPipe(19726): Stream #0.0: Audio: amrnb, 8000 Hz, 1 channels, flt
23 | 03-05 10:02:11.570: ERROR/PVOMXEncNode(73): PVMFOMXEncNode-Audio_AMRNB::DoPrepare(): Got Component OMX.PV.amrencnb handle
24 | 03-05 10:02:11.590: INFO/[FFMPEGPrototype(19726): waiting for capture server to be up
25 | 03-05 10:02:11.710: DEBUG/dalvikvm(255): GC_EXPLICIT freed 523 objects / 23624 bytes in 321ms
26 | 03-05 10:02:11.870: DEBUG/FFMPEGInputPipe(19726): Output #0, flv, to 'rtmp://camundo.com:1935/test/kaka':
27 | 03-05 10:02:11.870: DEBUG/FFMPEGInputPipe(19726): Metadata:
28 | 03-05 10:02:11.880: DEBUG/FFMPEGInputPipe(19726): encoder : Lavf52.94.0
29 | 03-05 10:02:11.900: DEBUG/FFMPEGInputPipe(19726): Stream #0.0: Audio: adpcm_swf, 11025 Hz, 1 channels, s16, 64 kb/s
30 | 03-05 10:02:11.910: DEBUG/FFMPEGInputPipe(19726): Stream mapping:
31 | 03-05 10:02:11.920: DEBUG/FFMPEGInputPipe(19726): Stream #0.0 -> #0.0
32 | 03-05 10:02:11.930: DEBUG/FFMPEGInputPipe(19726): Warning, using s16 intermediate sample format for resampling
33 | 03-05 10:02:12.350: INFO/BatteryStatsImpl(103): notePhoneSignalStrengthLocked: 2->3
34 | 03-05 10:02:12.600: DEBUG/AudioHardwareMSM72XX(73): audpre_index = 0, tx_iir_index = 0
35 | 03-05 10:02:12.600: DEBUG/HTC Acoustic(73): msm72xx_enable_audpre: 0x0003
36 | 03-05 10:02:12.611: INFO/AudioHardwareMSM72XX(73): AudioHardware pcm recording is going to standby.
37 | 03-05 10:02:12.611: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
38 | 03-05 10:02:12.611: INFO/AudioHardwareMSM72XX(73): doAudioRouteOrMute() device 1, mMode 0, mMicMute 1
39 | 03-05 10:02:12.620: DEBUG/HTC Acoustic(73): msm72xx_enable_audpp: 0x0007
40 | 03-05 10:02:12.620: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
41 | 03-05 10:02:12.620: INFO/AudioHardwareMSM72XX(73): doAudioRouteOrMute() device 1, mMode 0, mMicMute 1
42 | 03-05 10:02:12.620: DEBUG/HTC Acoustic(73): msm72xx_enable_audpp: 0x0007
43 | 03-05 10:02:12.630: ERROR/HTC Acoustic(73): Cannot enable/disable VR mode, enable=0
44 | 03-05 10:02:12.630: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
45 | 03-05 10:02:12.640: DEBUG/AudioHardwareMSM72XX(73): audpre_index = 0, tx_iir_index = 0
46 | 03-05 10:02:12.640: DEBUG/HTC Acoustic(73): msm72xx_enable_audpre: 0x0003
47 | 03-05 10:02:12.640: INFO/AudioHardwareMSM72XX(73): do input routing device 40000
48 | 03-05 10:02:12.640: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
49 | 03-05 10:02:12.640: INFO/AudioHardwareMSM72XX(73): doAudioRouteOrMute() device 1, mMode 0, mMicMute 1
50 | 03-05 10:02:12.640: DEBUG/HTC Acoustic(73): msm72xx_enable_audpp: 0x0007
51 | 03-05 10:02:12.740: INFO/AudioHardwareMSM72XX(73): AUDIO_START: start kernel pcm_in driver.
52 | 03-05 10:02:13.854: DEBUG/FFMPEGInputPipe(19726): size= 7kB time=1.21 bitrate= 48.8kbits/s
53 | 03-05 10:02:14.354: DEBUG/FFMPEGInputPipe(19726): size= 12kB time=2.00 bitrate= 48.2kbits/s
54 | 03-05 10:02:14.850: DEBUG/FFMPEGInputPipe(19726): size= 15kB time=2.51 bitrate= 48.1kbits/s
55 | 03-05 10:02:15.380: DEBUG/FFMPEGInputPipe(19726): size= 18kB time=3.02 bitrate= 47.9kbits/s
56 | 03-05 10:02:15.880: DEBUG/FFMPEGInputPipe(19726): size= 21kB time=3.53 bitrate= 47.9kbits/s
57 | 03-05 10:02:16.390: DEBUG/FFMPEGInputPipe(19726): size= 23kB time=3.99 bitrate= 47.8kbits/s
58 | 03-05 10:02:16.920: DEBUG/FFMPEGInputPipe(19726): size= 27kB time=4.55 bitrate= 47.8kbits/s
59 | 03-05 10:02:17.430: DEBUG/FFMPEGInputPipe(19726): size= 29kB time=5.06 bitrate= 47.7kbits/s
60 | 03-05 10:02:17.600: DEBUG/dalvikvm(19272): GC_EXPLICIT freed 169 objects / 11280 bytes in 213ms
61 | 03-05 10:02:17.930: DEBUG/FFMPEGInputPipe(19726): size= 32kB time=5.57 bitrate= 47.7kbits/s
62 | 03-05 10:02:18.460: DEBUG/FFMPEGInputPipe(19726): size= 35kB time=6.08 bitrate= 47.7kbits/s
63 | 03-05 10:02:18.960: DEBUG/FFMPEGInputPipe(19726): size= 38kB time=6.59 bitrate= 47.6kbits/s
64 | 03-05 10:02:19.460: DEBUG/FFMPEGInputPipe(19726): size= 41kB time=7.11 bitrate= 47.6kbits/s
65 | 03-05 10:02:19.980: DEBUG/FFMPEGInputPipe(19726): size= 44kB time=7.62 bitrate= 47.6kbits/s
66 | 03-05 10:02:20.480: DEBUG/FFMPEGInputPipe(19726): size= 47kB time=8.13 bitrate= 47.6kbits/s
67 | 03-05 10:02:20.980: DEBUG/FFMPEGInputPipe(19726): size= 50kB time=8.64 bitrate= 47.6kbits/s
68 | 03-05 10:02:21.490: DEBUG/FFMPEGInputPipe(19726): size= 53kB time=9.10 bitrate= 47.6kbits/s
69 | 03-05 10:02:22.000: DEBUG/FFMPEGInputPipe(19726): size= 56kB time=9.61 bitrate= 47.6kbits/s
70 | 03-05 10:02:22.500: DEBUG/FFMPEGInputPipe(19726): size= 59kB time=10.12 bitrate= 47.5kbits/s
71 | 03-05 10:02:23.020: DEBUG/FFMPEGInputPipe(19726): size= 62kB time=10.63 bitrate= 47.5kbits/s
72 | 03-05 10:02:23.530: DEBUG/FFMPEGInputPipe(19726): size= 65kB time=11.15 bitrate= 47.5kbits/s
73 | 03-05 10:02:24.050: DEBUG/FFMPEGInputPipe(19726): size= 68kB time=11.66 bitrate= 47.5kbits/s
74 | 03-05 10:02:24.550: DEBUG/FFMPEGInputPipe(19726): size= 71kB time=12.17 bitrate= 47.5kbits/s
75 | 03-05 10:02:25.060: DEBUG/FFMPEGInputPipe(19726): size= 74kB time=12.68 bitrate= 47.5kbits/s
76 | 03-05 10:02:25.580: DEBUG/FFMPEGInputPipe(19726): size= 76kB time=13.19 bitrate= 47.5kbits/s
77 | 03-05 10:02:26.090: DEBUG/FFMPEGInputPipe(19726): size= 79kB time=13.70 bitrate= 47.5kbits/s
78 | 03-05 10:02:26.510: DEBUG/dalvikvm(19280): GC_EXPLICIT freed 3558 objects / 184568 bytes in 174ms
79 | 03-05 10:02:26.610: DEBUG/FFMPEGInputPipe(19726): size= 82kB time=14.21 bitrate= 47.5kbits/s
80 | 03-05 10:02:27.120: DEBUG/FFMPEGInputPipe(19726): size= 85kB time=14.72 bitrate= 47.5kbits/s
81 | 03-05 10:02:27.630: DEBUG/FFMPEGInputPipe(19726): size= 89kB time=15.28 bitrate= 47.5kbits/s
82 | 03-05 10:02:28.130: DEBUG/FFMPEGInputPipe(19726): size= 91kB time=15.74 bitrate= 47.5kbits/s
83 | 03-05 10:02:28.650: DEBUG/FFMPEGInputPipe(19726): size= 94kB time=16.25 bitrate= 47.5kbits/s
84 | 03-05 10:02:29.170: DEBUG/FFMPEGInputPipe(19726): size= 97kB time=16.77 bitrate= 47.5kbits/s
85 | 03-05 10:02:29.690: DEBUG/FFMPEGInputPipe(19726): size= 100kB time=17.28 bitrate= 47.5kbits/s
86 | 03-05 10:02:30.200: DEBUG/FFMPEGInputPipe(19726): size= 103kB time=17.79 bitrate= 47.5kbits/s
87 | 03-05 10:02:30.700: DEBUG/FFMPEGInputPipe(19726): size= 106kB time=18.34 bitrate= 47.5kbits/s
88 | 03-05 10:02:31.210: DEBUG/FFMPEGInputPipe(19726): size= 109kB time=18.86 bitrate= 47.5kbits/s
89 | 03-05 10:02:31.730: DEBUG/FFMPEGInputPipe(19726): size= 112kB time=19.32 bitrate= 47.5kbits/s
90 | 03-05 10:02:32.230: DEBUG/FFMPEGInputPipe(19726): size= 115kB time=19.88 bitrate= 47.5kbits/s
91 | 03-05 10:02:32.740: DEBUG/FFMPEGInputPipe(19726): size= 118kB time=20.34 bitrate= 47.5kbits/s
92 | 03-05 10:02:33.270: DEBUG/FFMPEGInputPipe(19726): size= 121kB time=20.90 bitrate= 47.5kbits/s
93 | 03-05 10:02:33.780: DEBUG/FFMPEGInputPipe(19726): size= 124kB time=21.41 bitrate= 47.5kbits/s
94 | 03-05 10:02:34.290: DEBUG/FFMPEGInputPipe(19726): size= 127kB time=21.87 bitrate= 47.5kbits/s
95 | 03-05 10:02:34.790: DEBUG/FFMPEGInputPipe(19726): size= 130kB time=22.43 bitrate= 47.5kbits/s
96 | 03-05 10:02:35.300: DEBUG/FFMPEGInputPipe(19726): size= 133kB time=22.89 bitrate= 47.4kbits/s
97 | 03-05 10:02:35.810: DEBUG/FFMPEGInputPipe(19726): size= 136kB time=23.41 bitrate= 47.4kbits/s
98 | 03-05 10:02:36.330: INFO/BatteryStatsImpl(103): notePhoneSignalStrengthLocked: 3->2
99 | 03-05 10:02:36.350: DEBUG/FFMPEGInputPipe(19726): size= 139kB time=23.92 bitrate= 47.4kbits/s
100 | 03-05 10:02:36.860: DEBUG/FFMPEGInputPipe(19726): size= 141kB time=24.43 bitrate= 47.4kbits/s
101 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/etc/nellymoser.txt:
--------------------------------------------------------------------------------
1 | 03-05 10:07:06.110: INFO/System.out(19780): [ streamToRtmp() ] [/data/data/com.camundo/ffmpeg -analyzeduration 0 -muxdelay 0 -muxpreload 0 -i pipe:0 -re -vn -acodec nellymoser -ar 8000 -ac 1 -f flv rtmp://camundo.com:1935/test/kaka]
2 | 03-05 10:07:06.190: DEBUG/FFMPEGInputPipe(19780): [ run() ] os : java.lang.ProcessManager$ProcessOutputStream@44954fa8
3 | 03-05 10:07:06.280: DEBUG/FFMPEGInputPipe(19780): FFmpeg version git-c3897d7, Copyright (c) 2000-2011 the FFmpeg developers
4 | 03-05 10:07:06.290: DEBUG/FFMPEGInputPipe(19780): built on Mar 5 2011 01:03:24 with gcc 4.4.0
5 | 03-05 10:07:06.590: INFO/AudioPublisher(19780): [ run() ] input [android.net.LocalSocketImpl$SocketInputStream@4495cb10]
6 | 03-05 10:07:06.590: DEBUG/FFMPEGInputPipe(19780): configuration: --target-os=linux --cross-prefix=arm-eabi- --arch=arm --disable-armvfp --prefix=../build/ffmpeg --disable-shared --disable-encoders --disable-decoders --disable-protocols --enable-muxers --enable-demuxers --enable-parsers --disable-devices --enable-filters --disable-bsfs --enable-encoder=adpcm_swf --enable-decoder=adpcm_swf --enable-decoder=nellymoser --enable-encoder=nellymoser --enable-encoder=flv --enable-protocol=pipe --enable-protocol=file --enable-protocol=rtmp --enable-decoder=amrnb --enable-decoder=flv --enable-encoder=pcm_u8 --enable-encoder=pcm_s16le --enable-encoder=aac --disable-frei0r --disable-demuxer=ea --disable-muxer=mov --disable-demuxer=mov --disable-demuxer=matroska --disable-muxer=matroska --disable-muxer=matroska_audio --disable-demuxer=mpc --disable-demuxer=mpc8 --disable-ffprobe --extra-cflags='-I/home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -march=armv5te -mtune=xscale -msoft-float' --extra-ldflags='-nostdlib /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/libc.so /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/libm.so -Wl,-rpath-link=/home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib -L/home/wouter/applications/android-ndk/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86/lib/gcc/arm-eabi/4.4.0' --extra-ldflags='-Wl,-dynamic-linker,/system/bin/linker /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/crtbegin_dynamic.o /home/wouter/applications/android-ndk/platforms/android-8/arch-arm/usr/lib/crtend_android.o' --extra-libs=-lgcc
7 | 03-05 10:07:06.590: INFO/[FFMPEGPrototype(19780): connected to socket
8 | 03-05 10:07:06.620: DEBUG/FFMPEGInputPipe(19780): libavutil 50.36. 0 / 50.36. 0
9 | 03-05 10:07:06.630: VERBOSE/MediaProfiles(73): getInstance
10 | 03-05 10:07:06.630: DEBUG/FFMPEGInputPipe(19780): libavcore 0.16. 1 / 0.16. 1
11 | 03-05 10:07:06.640: DEBUG/FFMPEGInputPipe(19780): libavcodec 52.108. 0 / 52.108. 0
12 | 03-05 10:07:06.640: ERROR/audio_input(73): unsupported parameter: x-pvmf/media-input-node/cap-config-interface;valtype=key_specific_value
13 | 03-05 10:07:06.640: ERROR/audio_input(73): VerifyAndSetParameter failed
14 | 03-05 10:07:06.660: DEBUG/FFMPEGInputPipe(19780): libavformat 52.94. 0 / 52.94. 0
15 | 03-05 10:07:06.690: ERROR/PVOMXEncNode(73): PVMFOMXEncNode-Audio_AMRNB::DoPrepare(): Got Component OMX.PV.amrencnb handle
16 | 03-05 10:07:06.720: INFO/[FFMPEGPrototype(19780): waiting for capture server to be up
17 | 03-05 10:07:06.720: DEBUG/FFMPEGInputPipe(19780): libavdevice 52. 2. 3 / 52. 2. 3
18 | 03-05 10:07:06.720: DEBUG/FFMPEGInputPipe(19780): libavfilter 1.74. 0 / 1.74. 0
19 | 03-05 10:07:06.730: DEBUG/FFMPEGInputPipe(19780): libswscale 0.12. 0 / 0.12. 0
20 | 03-05 10:07:06.740: DEBUG/FFMPEGInputPipe(19780): [amr @ 0x43cd90] max_analyze_duration reached
21 | 03-05 10:07:06.750: DEBUG/FFMPEGInputPipe(19780): [amr @ 0x43cd90] Estimating duration from bitrate, this may be inaccurate
22 | 03-05 10:07:06.760: DEBUG/FFMPEGInputPipe(19780): Input #0, amr, from 'pipe:0':
23 | 03-05 10:07:06.760: DEBUG/FFMPEGInputPipe(19780): Duration: N/A, bitrate: N/A
24 | 03-05 10:07:06.770: DEBUG/FFMPEGInputPipe(19780): Stream #0.0: Audio: amrnb, 8000 Hz, 1 channels, flt
25 | 03-05 10:07:07.030: DEBUG/FFMPEGInputPipe(19780): Output #0, flv, to 'rtmp://camundo.com:1935/test/kaka':
26 | 03-05 10:07:07.070: DEBUG/FFMPEGInputPipe(19780): Metadata:
27 | 03-05 10:07:07.070: DEBUG/FFMPEGInputPipe(19780): encoder : Lavf52.94.0
28 | 03-05 10:07:07.090: DEBUG/FFMPEGInputPipe(19780): Stream #0.0: Audio: nellymoser, 8000 Hz, 1 channels, s16, 64 kb/s
29 | 03-05 10:07:07.090: DEBUG/FFMPEGInputPipe(19780): Stream mapping:
30 | 03-05 10:07:07.110: DEBUG/FFMPEGInputPipe(19780): Stream #0.0 -> #0.0
31 | 03-05 10:07:07.730: DEBUG/AudioHardwareMSM72XX(73): audpre_index = 0, tx_iir_index = 0
32 | 03-05 10:07:07.730: DEBUG/HTC Acoustic(73): msm72xx_enable_audpre: 0x0003
33 | 03-05 10:07:07.740: INFO/AudioHardwareMSM72XX(73): AudioHardware pcm recording is going to standby.
34 | 03-05 10:07:07.740: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
35 | 03-05 10:07:07.740: INFO/AudioHardwareMSM72XX(73): doAudioRouteOrMute() device 1, mMode 0, mMicMute 1
36 | 03-05 10:07:07.740: DEBUG/HTC Acoustic(73): msm72xx_enable_audpp: 0x0007
37 | 03-05 10:07:07.750: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
38 | 03-05 10:07:07.750: INFO/AudioHardwareMSM72XX(73): doAudioRouteOrMute() device 1, mMode 0, mMicMute 1
39 | 03-05 10:07:07.750: DEBUG/HTC Acoustic(73): msm72xx_enable_audpp: 0x0007
40 | 03-05 10:07:07.760: ERROR/HTC Acoustic(73): Cannot enable/disable VR mode, enable=0
41 | 03-05 10:07:07.760: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
42 | 03-05 10:07:07.770: DEBUG/AudioHardwareMSM72XX(73): audpre_index = 0, tx_iir_index = 0
43 | 03-05 10:07:07.770: DEBUG/HTC Acoustic(73): msm72xx_enable_audpre: 0x0003
44 | 03-05 10:07:07.770: INFO/AudioHardwareMSM72XX(73): do input routing device 40000
45 | 03-05 10:07:07.770: INFO/AudioHardwareMSM72XX(73): Routing audio to Speakerphone
46 | 03-05 10:07:07.770: INFO/AudioHardwareMSM72XX(73): doAudioRouteOrMute() device 1, mMode 0, mMicMute 1
47 | 03-05 10:07:07.770: DEBUG/HTC Acoustic(73): msm72xx_enable_audpp: 0x0007
48 | 03-05 10:07:07.874: INFO/AudioHardwareMSM72XX(73): AUDIO_START: start kernel pcm_in driver.
49 | 03-05 10:07:08.070: DEBUG/FFMPEGInputPipe(19780): size= 2kB time=0.54 bitrate= 23.2kbits/s
50 | 03-05 10:07:08.560: DEBUG/FFMPEGInputPipe(19780): size= 3kB time=1.02 bitrate= 21.7kbits/s
51 | 03-05 10:07:08.730: INFO/WindowManager(103): Setting rotation to 1, animFlags=0
52 | 03-05 10:07:08.750: INFO/ActivityManager(103): Config changed: { scale=1.0 imsi=206/1 loc=nl_NL touch=3 keys=1/1/2 nav=3/1 orien=2 layout=17 uiMode=17 seq=208}
53 | 03-05 10:07:09.070: DEBUG/FFMPEGInputPipe(19780): size= 4kB time=1.54 bitrate= 21.1kbits/s
54 | 03-05 10:07:09.390: INFO/BatteryStatsImpl(103): notePhoneSignalStrengthLocked: 2->3
55 | 03-05 10:07:09.580: DEBUG/FFMPEGInputPipe(19780): size= 5kB time=1.98 bitrate= 20.9kbits/s
56 | 03-05 10:07:10.090: DEBUG/FFMPEGInputPipe(19780): size= 6kB time=2.46 bitrate= 20.7kbits/s
57 | 03-05 10:07:10.590: DEBUG/FFMPEGInputPipe(19780): size= 8kB time=3.04 bitrate= 20.6kbits/s
58 | 03-05 10:07:10.730: WARN/WindowManager(103): Window freeze timeout expired.
59 | 03-05 10:07:10.730: WARN/WindowManager(103): Force clearing orientation change: Window{44b5fb10 com.camundo/com.camundo.FFMPEGPrototype paused=false}
60 | 03-05 10:07:11.110: DEBUG/FFMPEGInputPipe(19780): size= 9kB time=3.55 bitrate= 20.5kbits/s
61 | 03-05 10:07:11.620: DEBUG/FFMPEGInputPipe(19780): size= 10kB time=4.06 bitrate= 20.4kbits/s
62 | 03-05 10:07:12.130: DEBUG/FFMPEGInputPipe(19780): size= 11kB time=4.58 bitrate= 20.4kbits/s
63 | 03-05 10:07:12.650: DEBUG/FFMPEGInputPipe(19780): size= 13kB time=5.09 bitrate= 20.3kbits/s
64 | 03-05 10:07:13.170: DEBUG/FFMPEGInputPipe(19780): size= 14kB time=5.60 bitrate= 20.3kbits/s
65 | 03-05 10:07:13.320: DEBUG/dalvikvm(103): GC_EXPLICIT freed 12232 objects / 648512 bytes in 582ms
66 | 03-05 10:07:13.670: DEBUG/FFMPEGInputPipe(19780): size= 15kB time=6.02 bitrate= 20.3kbits/s
67 | 03-05 10:07:14.180: DEBUG/FFMPEGInputPipe(19780): size= 16kB time=6.56 bitrate= 20.3kbits/s
68 | 03-05 10:07:14.690: DEBUG/FFMPEGInputPipe(19780): size= 18kB time=7.14 bitrate= 20.2kbits/s
69 | 03-05 10:07:15.200: DEBUG/FFMPEGInputPipe(19780): size= 19kB time=7.65 bitrate= 20.2kbits/s
70 | 03-05 10:07:15.720: DEBUG/FFMPEGInputPipe(19780): size= 20kB time=8.16 bitrate= 20.2kbits/s
71 | 03-05 10:07:16.220: DEBUG/FFMPEGInputPipe(19780): size= 21kB time=8.67 bitrate= 20.2kbits/s
72 | 03-05 10:07:16.740: DEBUG/FFMPEGInputPipe(19780): size= 23kB time=9.18 bitrate= 20.2kbits/s
73 | 03-05 10:07:17.250: DEBUG/FFMPEGInputPipe(19780): size= 24kB time=9.70 bitrate= 20.2kbits/s
74 | 03-05 10:07:17.770: DEBUG/FFMPEGInputPipe(19780): size= 25kB time=10.21 bitrate= 20.2kbits/s
75 | 03-05 10:07:18.270: DEBUG/FFMPEGInputPipe(19780): size= 26kB time=10.72 bitrate= 20.2kbits/s
76 | 03-05 10:07:18.780: DEBUG/FFMPEGInputPipe(19780): size= 28kB time=11.23 bitrate= 20.2kbits/s
77 | 03-05 10:07:19.300: DEBUG/FFMPEGInputPipe(19780): size= 29kB time=11.74 bitrate= 20.1kbits/s
78 | 03-05 10:07:19.820: DEBUG/FFMPEGInputPipe(19780): size= 30kB time=12.26 bitrate= 20.1kbits/s
79 | 03-05 10:07:20.320: DEBUG/FFMPEGInputPipe(19780): size= 31kB time=12.77 bitrate= 20.1kbits/s
80 | 03-05 10:07:20.830: DEBUG/FFMPEGInputPipe(19780): size= 33kB time=13.28 bitrate= 20.1kbits/s
81 | 03-05 10:07:21.370: DEBUG/FFMPEGInputPipe(19780): size= 34kB time=13.79 bitrate= 20.1kbits/s
82 | 03-05 10:07:21.870: DEBUG/FFMPEGInputPipe(19780): size= 35kB time=14.30 bitrate= 20.1kbits/s
83 | 03-05 10:07:22.380: DEBUG/FFMPEGInputPipe(19780): size= 36kB time=14.85 bitrate= 20.1kbits/s
84 | 03-05 10:07:22.880: DEBUG/FFMPEGInputPipe(19780): size= 38kB time=15.33 bitrate= 20.1kbits/s
85 | 03-05 10:07:23.400: DEBUG/FFMPEGInputPipe(19780): size= 39kB time=15.84 bitrate= 20.1kbits/s
86 | 03-05 10:07:23.910: DEBUG/FFMPEGInputPipe(19780): size= 40kB time=16.35 bitrate= 20.1kbits/s
87 | 03-05 10:07:24.420: DEBUG/FFMPEGInputPipe(19780): size= 41kB time=16.86 bitrate= 20.1kbits/s
88 | 03-05 10:07:24.930: DEBUG/FFMPEGInputPipe(19780): size= 43kB time=17.34 bitrate= 20.1kbits/s
89 | 03-05 10:07:25.440: DEBUG/FFMPEGInputPipe(19780): size= 44kB time=17.89 bitrate= 20.1kbits/s
90 | 03-05 10:07:26.000: DEBUG/FFMPEGInputPipe(19780): size= 45kB time=18.40 bitrate= 20.1kbits/s
91 | 03-05 10:07:26.500: DEBUG/FFMPEGInputPipe(19780): size= 46kB time=18.91 bitrate= 20.1kbits/s
92 | 03-05 10:07:27.020: DEBUG/FFMPEGInputPipe(19780): size= 48kB time=19.49 bitrate= 20.1kbits/s
93 | 03-05 10:07:27.540: DEBUG/FFMPEGInputPipe(19780): size= 49kB time=20.00 bitrate= 20.1kbits/s
94 | 03-05 10:07:28.040: DEBUG/FFMPEGInputPipe(19780): size= 50kB time=20.51 bitrate= 20.1kbits/s
95 | 03-05 10:07:28.560: DEBUG/FFMPEGInputPipe(19780): size= 52kB time=21.02 bitrate= 20.1kbits/s
96 | 03-05 10:07:29.080: DEBUG/FFMPEGInputPipe(19780): size= 53kB time=21.54 bitrate= 20.1kbits/s
97 | 03-05 10:07:29.580: DEBUG/FFMPEGInputPipe(19780): size= 54kB time=22.05 bitrate= 20.1kbits/s
98 | 03-05 10:07:30.100: DEBUG/FFMPEGInputPipe(19780): size= 55kB time=22.56 bitrate= 20.1kbits/s
99 | 03-05 10:07:30.620: DEBUG/FFMPEGInputPipe(19780): size= 57kB time=23.07 bitrate= 20.1kbits/s
100 | 03-05 10:07:31.120: DEBUG/FFMPEGInputPipe(19780): size= 58kB time=23.58 bitrate= 20.1kbits/s
101 | 03-05 10:07:31.620: DEBUG/FFMPEGInputPipe(19780): size= 59kB time=24.10 bitrate= 20.1kbits/s
102 | 03-05 10:07:32.140: DEBUG/FFMPEGInputPipe(19780): size= 60kB time=24.61 bitrate= 20.1kbits/s
103 | 03-05 10:07:32.650: DEBUG/dalvikvm(255): GC_EXPLICIT freed 242 objects / 11552 bytes in 294ms
104 | 03-05 10:07:32.660: DEBUG/FFMPEGInputPipe(19780): size= 62kB time=25.12 bitrate= 20.1kbits/s
105 | 03-05 10:07:33.160: DEBUG/FFMPEGInputPipe(19780): size= 63kB time=25.63 bitrate= 20.1kbits/s
106 | 03-05 10:07:33.680: DEBUG/FFMPEGInputPipe(19780): size= 64kB time=26.14 bitrate= 20.1kbits/s
107 | 03-05 10:07:34.200: DEBUG/FFMPEGInputPipe(19780): size= 65kB time=26.66 bitrate= 20.1kbits/s
108 | 03-05 10:07:34.700: DEBUG/FFMPEGInputPipe(19780): size= 67kB time=27.17 bitrate= 20.1kbits/s
109 | 03-05 10:07:35.220: DEBUG/FFMPEGInputPipe(19780): size= 68kB time=27.68 bitrate= 20.1kbits/s
110 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/gen/com/camundo/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package com.camundo;
9 |
10 | public final class R {
11 | public static final class attr {
12 | }
13 | public static final class drawable {
14 | public static final int icon=0x7f020000;
15 | public static final int menu_quit=0x7f020001;
16 | }
17 | public static final class id {
18 | public static final int ScrollView01=0x7f060000;
19 | public static final int audioActivityButton=0x7f06000a;
20 | public static final int linearLayout1=0x7f060003;
21 | public static final int menu_quit=0x7f06000c;
22 | public static final int publishingTopic=0x7f060004;
23 | public static final int receivedStatusText=0x7f060009;
24 | public static final int rtmpServerUrl=0x7f060002;
25 | public static final int startCaptureButton=0x7f060007;
26 | public static final int stopCaptureButton=0x7f060008;
27 | public static final int subscribingTopic=0x7f060006;
28 | public static final int switchTopicButton=0x7f060005;
29 | public static final int textView1=0x7f060001;
30 | public static final int videoActivityButton=0x7f06000b;
31 | }
32 | public static final class layout {
33 | public static final int audio=0x7f030000;
34 | public static final int main=0x7f030001;
35 | public static final int round_rect=0x7f030002;
36 | }
37 | public static final class menu {
38 | public static final int main_menu=0x7f050000;
39 | }
40 | public static final class string {
41 | public static final int app_name=0x7f040000;
42 | public static final int menu_quit=0x7f040001;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembernames class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembernames class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers enum * {
30 | public static **[] values();
31 | public static ** valueOf(java.lang.String);
32 | }
33 |
34 | -keep class * implements android.os.Parcelable {
35 | public static final android.os.Parcelable$Creator *;
36 | }
37 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/drawable-hdpi/menu_quit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/res/drawable-hdpi/menu_quit.png
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mogo29/Android-RTMP/4a18ef761ce89b1ddaa10d2c566c79a94db12e3f/android-ffmpeg-prototype/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/layout/audio.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
20 |
21 |
22 |
26 |
27 |
28 |
31 |
32 |
39 |
40 |
49 |
50 |
51 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
75 |
76 |
85 |
86 |
87 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
103 |
108 |
109 |
113 |
114 |
115 |
116 |
117 |
122 |
123 |
124 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
13 |
14 |
19 |
20 |
25 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/layout/round_rect.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/menu/main_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 |
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 |
953 |
954 |
955 |
956 |
957 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 |
982 |
983 |
984 |
985 |
986 |
987 |
988 |
989 |
990 |
991 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | camundo.com : FFMPEG prototype
4 | Quit
5 |
6 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/AudioActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo;
20 |
21 | import java.nio.ByteOrder;
22 |
23 | import android.app.Activity;
24 | import android.content.Context;
25 | import android.os.Bundle;
26 | import android.os.PowerManager;
27 | import android.text.Editable;
28 | import android.util.Log;
29 | import android.view.Menu;
30 | import android.view.MenuInflater;
31 | import android.view.MenuItem;
32 | import android.view.View;
33 | import android.view.View.OnClickListener;
34 | import android.view.WindowManager;
35 | import android.widget.Button;
36 | import android.widget.EditText;
37 | import android.widget.TextView;
38 | import android.widget.Toast;
39 |
40 | public class AudioActivity extends Activity {
41 |
42 | public static final String rtmpUrl = "rtmp://camundo.com:1935/test";
43 | public static final String client1 = "client1.a";
44 | public static final String client2 = "client2.a";
45 |
46 | PowerManager.WakeLock wakeLock;
47 |
48 | private boolean capturing = false;
49 | private boolean receiving = false;
50 |
51 | private EditText rtmpServerUrlText;
52 | private EditText publishingTopicText;
53 | private EditText subscribingTopicText;
54 | private Button switchTopicButton;
55 |
56 | private Button startCaptureButton;
57 | private Button stopCaptureButton;
58 |
59 | private TextView receivedStatusText;
60 |
61 | private AudioCall audioCall;
62 |
63 |
64 | private int bytesReceived;
65 | private int bytesPerSecond;
66 | private long bytesReceivedStart;
67 |
68 |
69 | @Override
70 | public boolean onCreateOptionsMenu(Menu menu) {
71 | MenuInflater inflater = getMenuInflater();
72 | inflater.inflate(R.menu.main_menu, menu);
73 | return true;
74 | }
75 |
76 | @Override
77 | public boolean onOptionsItemSelected(MenuItem item) {
78 | // Handle item selection
79 | switch (item.getItemId()) {
80 | case R.id.menu_quit:
81 | if (capturing) {
82 | stopCall();
83 | }
84 | finish();
85 | return true;
86 | default:
87 | return super.onOptionsItemSelected(item);
88 | }
89 | }
90 |
91 | @Override
92 | public void onCreate(Bundle savedInstanceState) {
93 | super.onCreate(savedInstanceState);
94 | setContentView(R.layout.audio);
95 |
96 | this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
97 |
98 | rtmpServerUrlText = (EditText) findViewById(R.id.rtmpServerUrl);
99 | rtmpServerUrlText.setText(rtmpUrl);
100 |
101 | publishingTopicText = (EditText) findViewById(R.id.publishingTopic);
102 | publishingTopicText.setText(client1);
103 |
104 | subscribingTopicText = (EditText) findViewById(R.id.subscribingTopic);
105 | subscribingTopicText.setText(client2);
106 |
107 | receivedStatusText = (TextView) findViewById(R.id.receivedStatusText);
108 |
109 | switchTopicButton = (Button) findViewById(R.id.switchTopicButton);
110 | switchTopicButton.setOnClickListener(new OnClickListener() {
111 | @Override
112 | public void onClick(View v) {
113 | if (!capturing && !receiving) {
114 | Editable text1 = publishingTopicText.getText();
115 | Editable text2 = subscribingTopicText.getText();
116 | publishingTopicText.setText(text2);
117 | subscribingTopicText.setText(text1);
118 | } else {
119 | Toast.makeText(
120 | getBaseContext(),
121 | "stop subscribing and publishing before switching topics",
122 | Toast.LENGTH_SHORT).show();
123 | }
124 | }
125 | });
126 |
127 | startCaptureButton = (Button) findViewById(R.id.startCaptureButton);
128 | startCaptureButton.setOnClickListener(new OnClickListener() {
129 | @Override
130 | public void onClick(View v) {
131 | if (!capturing) {
132 | startCall();
133 | }
134 | }
135 | });
136 |
137 | stopCaptureButton = (Button) findViewById(R.id.stopCaptureButton);
138 | stopCaptureButton.setEnabled(false);
139 | stopCaptureButton.setOnClickListener(new OnClickListener() {
140 | @Override
141 | public void onClick(View v) {
142 | stopCall();
143 | }
144 | });
145 |
146 | PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
147 | wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,
148 | "streamingWakelock");
149 |
150 | Log.d("---------------------->", "" + ByteOrder.nativeOrder());
151 | }
152 |
153 | public void startCall() {
154 |
155 | String rtmp = rtmpServerUrlText.getText().toString().trim();
156 | String pTopic = publishingTopicText.getText().toString().trim();
157 | String sTopic = subscribingTopicText.getText().toString().trim();
158 |
159 | if (audioCall != null) {
160 | audioCall.finish();
161 | }
162 |
163 | audioCall = new AudioCall(this, rtmp, pTopic, sTopic);
164 | wakeLock.acquire();
165 | audioCall.start();
166 |
167 | new Thread(new Runnable() {
168 |
169 | @Override
170 | public void run() {
171 | while (audioCall != null) {
172 | if (audioCall.audioSubscriber != null && audioCall.audioSubscriber.overallBytesReceived != 0) {
173 | bytesReceived = audioCall.audioSubscriber.overallBytesReceived;
174 | if ( bytesReceivedStart == 0 ) {
175 | bytesReceivedStart = System.currentTimeMillis();
176 | }
177 | else {
178 | bytesPerSecond = bytesReceived / (((int)(System.currentTimeMillis() - bytesReceivedStart)) / 1000);
179 | }
180 | runOnUiThread(done);
181 | }
182 | try {
183 | Thread.sleep(3000);
184 | } catch (Exception e) {}
185 | }
186 | }
187 |
188 | Runnable done = new Runnable() {
189 | public void run() {
190 | if (audioCall != null && audioCall.audioSubscriber != null) {
191 | receivedStatusText
192 | .setText("received "
193 | + (audioCall.audioSubscriber.overallBytesReceived / 1024)
194 | + "Kb ( " + (bytesPerSecond / 1025) + "Kb/s )");
195 | }
196 | }
197 | };
198 |
199 | }).start();
200 |
201 | startCaptureButton.setEnabled(false);
202 | stopCaptureButton.setEnabled(true);
203 |
204 | }
205 |
206 | public void stopCall() {
207 | startCaptureButton.setEnabled(true);
208 | stopCaptureButton.setEnabled(false);
209 | wakeLock.release();
210 | if (audioCall != null) {
211 | audioCall.finish();
212 | audioCall = null;
213 | }
214 | }
215 |
216 | }
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/AudioCall.java:
--------------------------------------------------------------------------------
1 | package com.camundo;
2 |
3 | import android.content.Context;
4 | import android.media.MediaRecorder;
5 | import android.media.MediaRecorder.AudioSource;
6 | import android.net.LocalSocket;
7 | import android.net.LocalSocketAddress;
8 | import android.util.Log;
9 | import android.widget.TextView;
10 | import android.widget.Toast;
11 |
12 | import com.camundo.media.AudioPublisher;
13 | import com.camundo.media.AudioSubscriber;
14 | import com.camundo.media.pipe.AudioInputPipe;
15 | import com.camundo.media.pipe.AudioOutputPipe;
16 | import com.camundo.media.pipe.PipeFactory;
17 | import com.camundo.util.AudioCodec;
18 |
19 | public class AudioCall extends Thread {
20 |
21 | private static final String TAG = "AudioCall";
22 |
23 | private Context context;
24 | private String rtmpServerUrl;
25 | private String publishingTopic;
26 | private String subscribingTopic;
27 |
28 | private final String sourceCodec = AudioCodec.Nellymoser.name;
29 |
30 | private LocalSocket localSocket;
31 | private static final String LOCAL_SOCKET_ADDRESS_MIC = "microphoneCapture";
32 |
33 | private MediaRecorder recorder;
34 |
35 | private PipeFactory pipeFactory = new PipeFactory();
36 |
37 | public AudioPublisher audioPublisher;
38 | public AudioSubscriber audioSubscriber;
39 |
40 |
41 |
42 | public AudioCall( Context context, String rtmpUrl, String pTopic, String sTopic ) {
43 | this.context = context;
44 | this.rtmpServerUrl = rtmpUrl;
45 | this.publishingTopic = pTopic;
46 | this.subscribingTopic = sTopic;
47 | }
48 |
49 |
50 |
51 | @Override
52 | public void run() {
53 | startPublish();
54 | startSubscribe();
55 | }
56 |
57 |
58 | public void finish() {
59 | Log.i(TAG, "[finish()]");
60 | try {
61 | stopCapture();
62 | }
63 | catch( Exception e ) {
64 | Log.e(TAG, "can not stop publishing", e);
65 | }
66 |
67 | try {
68 | stopSubscribe();
69 | }
70 | catch( Exception e ) {
71 | Log.e(TAG, "can not stop subscribing", e);
72 | }
73 | }
74 |
75 | public void startPublish() {
76 | try {
77 |
78 | String url = rtmpServerUrl + "/" + publishingTopic;
79 |
80 | //define the pipe
81 | AudioInputPipe pipe = null;
82 | if ( sourceCodec.equals(AudioCodec.Nellymoser.name)) {
83 | pipe = pipeFactory.getNellymoserAudioInputPipe( url );
84 | }
85 | else if ( sourceCodec.equals(AudioCodec.ADPCM_SWF.name) ) {
86 | pipe = pipeFactory.getADPCMAudioInputPipe( url );
87 | }
88 | else if ( sourceCodec.equals(AudioCodec.AAC.name ) ) {
89 | pipe = pipeFactory.getAACAudioInputPipe( url );
90 | }
91 |
92 | //start the publisher
93 | audioPublisher = new AudioPublisher( LOCAL_SOCKET_ADDRESS_MIC, pipe);
94 | audioPublisher.start();
95 | //and wait until it is up
96 | while ( !audioPublisher.up()) {
97 | try {
98 | Log.i( TAG , "waiting for capture server to be up");
99 | Thread.sleep(50);
100 | }
101 | catch( Exception e ){
102 | e.printStackTrace();
103 | }
104 | }
105 |
106 | //connect to the local socket
107 | localSocket = new LocalSocket();
108 | localSocket.connect(new LocalSocketAddress(LOCAL_SOCKET_ADDRESS_MIC));
109 | Log.i( TAG , "connected to socket");
110 | //localSocket.setReceiveBufferSize(64);
111 | //localSocket.setSendBufferSize(64);
112 |
113 | //prepare the mediarecorder
114 | recorder = new MediaRecorder();
115 | recorder.setAudioSource(AudioSource.MIC);
116 | recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
117 | recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
118 | recorder.setOutputFile(localSocket.getFileDescriptor());
119 | recorder.prepare();
120 |
121 | try {
122 | Log.i( TAG , "waiting for capture server to be up");
123 | Thread.sleep(1500);
124 | }
125 | catch( Exception e ){
126 | e.printStackTrace();
127 | }
128 |
129 | recorder.start();
130 |
131 | }
132 | catch( Exception e ) {
133 | e.printStackTrace();
134 | if ( e.getMessage().equalsIgnoreCase("broken pipe")) {
135 | Toast.makeText(context, "can not connect", Toast.LENGTH_SHORT).show();
136 | }
137 | }
138 |
139 | }
140 |
141 |
142 |
143 |
144 | public void stopCapture() {
145 | try {
146 | if ( audioPublisher != null ) {
147 | Log.i( TAG , "shutting down publisher");
148 | audioPublisher.shutdown();
149 | localSocket.close();
150 | audioPublisher = null;
151 | }
152 | recorder.stop();
153 | recorder.release();
154 | }
155 | catch( Exception e ) {
156 | Log.e(TAG, "[stopCapture()]", e);
157 | }
158 |
159 | }
160 |
161 |
162 |
163 |
164 |
165 | public void startSubscribe() {
166 | try {
167 | String url = rtmpServerUrl.trim() + "/" + subscribingTopic.trim();
168 |
169 | //start the publisher
170 | AudioOutputPipe pipe = pipeFactory.getAudioOutputPipe(url, AudioCodec.AUDIO_FILE_FORMAT_WAV, AudioCodec.PCM_S16LE.name, sourceCodec);
171 | //FileAudioOutputPipe pipe = new FileAudioOutputPipe(new File("/data/data/com.camundo/sample.wav"));
172 | audioSubscriber = new AudioSubscriber(pipe);
173 | audioSubscriber.start();
174 |
175 | }
176 | catch( Exception e ) {
177 | Log.e(TAG, "[startSubscribe()]", e);
178 | }
179 | }
180 |
181 |
182 |
183 | public void stopSubscribe() {
184 | try {
185 | if ( audioSubscriber != null ) {
186 | Log.i(TAG , "shutting down subscriber");
187 | audioSubscriber.shutdown();
188 | audioSubscriber = null;
189 | }
190 | }
191 | catch( Exception e ) {
192 | e.printStackTrace();
193 | }
194 | }
195 |
196 |
197 | }
198 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/Camundo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo;
20 |
21 | import android.app.Application;
22 | import android.content.Context;
23 |
24 | public class Camundo extends Application {
25 |
26 | private static Camundo instance;
27 |
28 | public Camundo() {
29 | instance = this;
30 | }
31 |
32 | public static Context getContext() {
33 | return instance;
34 | }
35 |
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/FFMPEGPrototype.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo;
20 |
21 | import java.nio.ByteOrder;
22 |
23 | import android.app.Activity;
24 | import android.content.Context;
25 | import android.content.Intent;
26 | import android.media.MediaRecorder;
27 | import android.media.MediaRecorder.AudioSource;
28 | import android.net.LocalSocket;
29 | import android.net.LocalSocketAddress;
30 | import android.os.Bundle;
31 | import android.os.PowerManager;
32 | import android.text.Editable;
33 | import android.util.Log;
34 | import android.view.Menu;
35 | import android.view.MenuInflater;
36 | import android.view.MenuItem;
37 | import android.view.View;
38 | import android.view.View.OnClickListener;
39 | import android.widget.Button;
40 | import android.widget.EditText;
41 | import android.widget.Toast;
42 |
43 | import com.camundo.media.AudioPublisher;
44 | import com.camundo.media.AudioSubscriber;
45 | import com.camundo.media.pipe.AudioInputPipe;
46 | import com.camundo.media.pipe.AudioOutputPipe;
47 | import com.camundo.media.pipe.PipeFactory;
48 | import com.camundo.util.AudioCodec;
49 | import com.camundo.util.NetworkUtils;
50 |
51 | public class FFMPEGPrototype extends Activity {
52 |
53 |
54 | PowerManager.WakeLock wakeLock;
55 |
56 |
57 | private boolean capturing = false;
58 | private boolean receiving = false;
59 |
60 |
61 | private Button audioActivityButton;
62 | private Button videoActivityButton;
63 |
64 |
65 | @Override
66 | public boolean onCreateOptionsMenu(Menu menu) {
67 | MenuInflater inflater = getMenuInflater();
68 | inflater.inflate(R.menu.main_menu, menu);
69 | return true;
70 | }
71 |
72 |
73 | @Override
74 | public boolean onOptionsItemSelected(MenuItem item) {
75 | // Handle item selection
76 | switch (item.getItemId()) {
77 | case R.id.menu_quit:
78 | if ( capturing ) {
79 | //stopCapture();
80 | }
81 | if ( receiving ) {
82 | //stopSubscribe();
83 | }
84 | finish();
85 | return true;
86 | default:
87 | return super.onOptionsItemSelected(item);
88 | }
89 | }
90 |
91 |
92 | @Override
93 | public void onCreate(Bundle savedInstanceState) {
94 | super.onCreate(savedInstanceState);
95 | setContentView(R.layout.main);
96 |
97 | audioActivityButton = (Button)findViewById(R.id.audioActivityButton);
98 | audioActivityButton.setOnClickListener(new OnClickListener() {
99 | @Override
100 | public void onClick(View v) {
101 | Intent intent = new Intent();
102 | intent.setClass( getBaseContext(), AudioActivity.class);
103 | startActivity(intent);
104 | }
105 | });
106 |
107 |
108 | videoActivityButton = (Button)findViewById(R.id.videoActivityButton);
109 | videoActivityButton.setOnClickListener(new OnClickListener() {
110 | @Override
111 | public void onClick(View v) {
112 |
113 | }
114 | });
115 |
116 | }
117 |
118 |
119 |
120 |
121 |
122 |
123 | }
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/AudioPublisher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media;
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 |
24 | import android.net.LocalServerSocket;
25 | import android.net.LocalSocket;
26 | import android.util.Log;
27 |
28 | import com.camundo.media.pipe.AudioInputPipe;
29 |
30 |
31 |
32 | public class AudioPublisher extends Thread{
33 |
34 | public final static String TAG = "AudioPublisher";
35 |
36 | private String socketAddress;
37 | private AudioInputPipe pipe;
38 |
39 |
40 |
41 | private LocalSocket receiver;
42 | private boolean up = false;
43 |
44 |
45 |
46 | public AudioPublisher( String socketAddress, AudioInputPipe pipe ) {
47 | this.socketAddress = socketAddress;
48 | this.pipe = pipe;
49 | }
50 |
51 | private static final int BUFFER_LENGTH = 64 * 6;//for AMR audio this is ok?
52 |
53 |
54 | @Override
55 | public void run(){
56 | try {
57 | LocalServerSocket server = new LocalServerSocket(socketAddress);
58 | pipe.start();
59 |
60 | while( !pipe.initialized() ) {
61 | Log.i(TAG, "[ run() ] pipe not yet running, waiting.");
62 | try {
63 | Thread.sleep(100);
64 | }
65 | catch( Exception e) {
66 | e.printStackTrace();
67 | }
68 | }
69 | //write bootstrap
70 | pipe.writeBootstrap();
71 |
72 | // its up
73 | up = true;
74 |
75 | while (up) {
76 |
77 | receiver = server.accept();
78 |
79 | //receiver.setReceiveBufferSize(BUFFER_LENGTH);
80 | //receiver.setSendBufferSize(BUFFER_LENGTH);
81 |
82 | if (receiver != null) {
83 | InputStream input = receiver.getInputStream();
84 | Log.i( TAG , "[ run() ] input [" + input + "]");
85 |
86 | int read = -1;
87 | int available;
88 | //ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH);
89 | //buffer.order(ByteOrder.LITTLE_ENDIAN);
90 |
91 | byte[] buffer = new byte[BUFFER_LENGTH];
92 |
93 | while ( (read = input.read()) != -1) {
94 | //Log.d("CameraCaptureServer", "[ run() ] read [" + read + "] buffer empty [" + input.available() + "] receiver [" + receiver + "]" );
95 | pipe.write(read);
96 | while( (available = input.available()) > 0 ) {
97 | if ( available > BUFFER_LENGTH ) {
98 | available = BUFFER_LENGTH;
99 | }
100 | input.read(buffer, 0, available);
101 | pipe.write(buffer, 0, available);
102 | }
103 | }
104 |
105 | // while ( (read = input.read(buffer)) > 0) {
106 | // //Log.d("CameraCaptureServer", "[ run() ] read [" + read + "] buffer empty [" + input.available() + "] receiver [" + receiver + "]" );
107 | // pipe.write(buffer, 0, read);
108 | // }
109 |
110 |
111 | }
112 | else {
113 | Log.i( TAG, "[ run() ] receiver is null!!!");
114 | }
115 | }
116 | if ( pipe != null ) {
117 | Log.i( TAG, "[ run() ] closing pipe");
118 | pipe.close();
119 | }
120 | else {
121 | Log.i( TAG, "[ run() ] closing pipe not necessary, is already null");
122 | }
123 |
124 | if ( receiver != null ) {
125 | Log.i( TAG, "[ run() ] closing receiver");
126 | receiver.close();
127 | }
128 | else {
129 | Log.i( TAG, "[ run() ] closing receiver not necessary, is already null");
130 | }
131 |
132 | Log.i( TAG , "[ run() ] closing server");
133 | server.close();
134 | }
135 | catch (IOException e) {
136 | e.printStackTrace();
137 | }
138 | Log.i( TAG , "[ run() ] done");
139 | }
140 |
141 |
142 |
143 | public void shutdown(){
144 | Log.i( TAG , "[ shutdown() ] up is false");
145 | up = false;
146 | }
147 |
148 |
149 | public boolean up() {
150 | return up;
151 | }
152 |
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/AudioSubscriber.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media;
20 |
21 | import java.io.IOException;
22 | import java.nio.ByteBuffer;
23 | import java.nio.ByteOrder;
24 |
25 | import android.media.AudioManager;
26 | import android.media.AudioTrack;
27 | import android.util.Log;
28 |
29 | import com.camundo.media.pipe.AudioOutputPipe;
30 |
31 |
32 |
33 | public class AudioSubscriber extends Thread{
34 |
35 | private static final String TAG = "AudioSubscriber";
36 |
37 | private AudioOutputPipe pipe;
38 | private AudioTrack audioTrack;
39 |
40 | public int overallBytesReceived = 0;
41 |
42 |
43 | public AudioSubscriber( AudioOutputPipe pipe ) {
44 | this.pipe = pipe;
45 | }
46 |
47 |
48 | @Override
49 | public void run() {
50 | try {
51 | //hmmm can always try
52 | //pipe.setPriority(MAX_PRIORITY);
53 | pipe.start();
54 |
55 | while( !pipe.initialized() ) {
56 | Log.i( TAG, "[ run() ] pipe not yet running, waiting.");
57 | try {
58 | Thread.sleep(1000);
59 | }
60 | catch( Exception e) {
61 | e.printStackTrace();
62 | }
63 | }
64 |
65 | int minBufferSize = AudioTrack.getMinBufferSize( pipe.getSampleRate(), pipe.getChannelConfig(), pipe.getEncoding());
66 |
67 | audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
68 | pipe.getSampleRate(),
69 | pipe.getChannelConfig(),
70 | pipe.getEncoding(),
71 | minBufferSize * 4,
72 | AudioTrack.MODE_STREAM);
73 |
74 |
75 | ByteBuffer buffer = ByteBuffer.allocate(minBufferSize);
76 | buffer.order(ByteOrder.LITTLE_ENDIAN);
77 |
78 | Log.d( TAG, "buffer length [" + minBufferSize + "]");
79 | int len;
80 |
81 | //wait until minimum amount of data ( header is 44 )
82 | pipe.bootstrap();
83 |
84 |
85 | boolean started = false;
86 |
87 | while( (len = pipe.read(buffer.array())) > 0 ) {
88 | //Log.d(NAME, "[ run() ] len [" + len + "] buffer empty [" + pipe.available() + "]" );
89 | overallBytesReceived+= audioTrack.write(buffer.array(), 0, len);
90 | if (!started && overallBytesReceived > minBufferSize ){
91 | audioTrack.play();
92 | started = true;
93 | }
94 | }
95 |
96 | }
97 | catch (IOException e) {
98 | Log.e( TAG, "[ run() ]", e);
99 | }
100 | Log.i( TAG, "[ run() ] done");
101 | }
102 |
103 |
104 | public void shutdown(){
105 | Log.i( TAG , "[ shutdown() ] up is false");
106 | if ( pipe != null ) {
107 | Log.i( TAG , "[ shutdown() ] closing pipe");
108 | pipe.close();
109 | }
110 | if ( audioTrack != null ) {
111 | audioTrack.stop();
112 | audioTrack.release();
113 | }
114 |
115 | }
116 |
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/pipe/AudioInputPipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media.pipe;
20 |
21 | import java.io.IOException;
22 |
23 | public interface AudioInputPipe {
24 |
25 | public void start();
26 |
27 | public boolean initialized() throws IOException;
28 |
29 | public void writeBootstrap();
30 |
31 |
32 | public void write( int oneByte ) throws IOException;
33 | public void write( byte[] buffer, int offset, int length ) throws IOException;
34 |
35 | public void close();
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/pipe/AudioOutputPipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media.pipe;
20 |
21 | import java.io.IOException;
22 |
23 | public interface AudioOutputPipe {
24 |
25 | public void start();
26 |
27 | public boolean initialized() throws IOException;
28 |
29 | public void bootstrap() throws IOException;
30 |
31 | public int read( byte[] buffer, int offset, int length ) throws IOException;
32 | public int read( byte[] buffer ) throws IOException;
33 |
34 | public int available() throws IOException;
35 |
36 | public int getSampleRate();
37 | public int getChannelConfig();
38 | public int getEncoding();
39 |
40 |
41 | public void close();
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/pipe/FFMPEGAudioInputPipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media.pipe;
20 |
21 | import java.io.BufferedReader;
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 | import java.io.InputStreamReader;
25 | import java.io.OutputStream;
26 |
27 | import android.util.Log;
28 |
29 | public class FFMPEGAudioInputPipe extends Thread implements AudioInputPipe {
30 |
31 | private final static String LINE_SEPARATOR = System.getProperty("line.separator");
32 |
33 | private static final String TAG = "FFMPEGAudioInputPipe";
34 |
35 | private static final String IO_ERROR = "I/O error";
36 |
37 | private Process process;
38 | private String command;
39 | private boolean processRunning;
40 | protected boolean processStartFailed;
41 |
42 | private InputstreamReaderThread errorStreamReaderThread;
43 | // private InputstreamReaderThread inputStreamReaderThread;
44 |
45 | private OutputStream outputStream;
46 |
47 | private byte[] bootstrap;
48 |
49 |
50 | public FFMPEGAudioInputPipe( String command ) {
51 | this.command = command;
52 | }
53 |
54 |
55 | public void write( int oneByte ) throws IOException {
56 | outputStream.write(oneByte);
57 | }
58 |
59 |
60 |
61 | public void write( byte[] buffer, int offset, int length ) throws IOException {
62 | outputStream.write(buffer, offset, length);
63 | outputStream.flush();
64 | }
65 |
66 |
67 | public void setBootstrap( byte[] bootstrap ) {
68 | this.bootstrap = bootstrap;
69 | }
70 |
71 | public void writeBootstrap() {
72 | if ( bootstrap != null ){
73 | try {
74 | write( bootstrap, 0, bootstrap.length);
75 | }
76 | catch( Exception e ) {
77 | e.printStackTrace();
78 | }
79 | }
80 | }
81 |
82 |
83 | public void close() {
84 |
85 | if ( process != null ) {
86 | Log.i( TAG , "[ close() ] destroying process");
87 | process.destroy();
88 | process = null;
89 | }
90 | else {
91 | Log.i( TAG , "[ close() ] can not destroy process -> is null");
92 | }
93 |
94 | Log.i( TAG , "[ close() ] closing outputstream");
95 | try {
96 | synchronized (outputStream) {
97 | outputStream.close();
98 | Log.i( TAG , "[ close() ] closing outputstream done");
99 | }
100 | }
101 | catch( Exception e ){
102 | e.printStackTrace();
103 | }
104 | //inputStreamReaderThread.finish();
105 | try {
106 | errorStreamReaderThread.finish();
107 | }
108 | catch( Exception e ) {
109 | e.printStackTrace();
110 | }
111 |
112 | }
113 |
114 |
115 | @Override
116 | public void run () {
117 | try {
118 | process = Runtime.getRuntime().exec( command , null);
119 |
120 | // inputStreamReaderThread = new InputstreamReaderThread(process.getInputStream());
121 | // Log.d("FFMPEGInputPipe", "[ run() ] inputStreamReader created");
122 | errorStreamReaderThread = new InputstreamReaderThread(process.getErrorStream());
123 | // Log.d("FFMPEGInputPipe", "[ run() ] errorStreamReader created");
124 | //
125 | // inputStreamReaderThread.start();
126 | errorStreamReaderThread.start();
127 | outputStream = process.getOutputStream();
128 |
129 | if ( outputStream != null) {
130 | processRunning = true;
131 | }
132 | else {
133 | processStartFailed = true;
134 | }
135 | try {
136 | process.waitFor();
137 | }
138 | catch( Exception e ) {
139 | e.printStackTrace();
140 | }
141 | }
142 | catch (IOException e) {
143 | e.printStackTrace();
144 | }
145 | }
146 |
147 |
148 | @Override
149 | public boolean initialized() throws IOException {
150 | if ( processStartFailed ) {
151 | throw new IOException("Process start failed");
152 | }
153 | return processRunning;
154 | }
155 |
156 |
157 |
158 | class InputstreamReaderThread extends Thread {
159 |
160 | private InputStream inputStream;
161 |
162 | public InputstreamReaderThread( InputStream i ){
163 | this.inputStream = i;
164 | }
165 |
166 | @Override
167 | public void run() {
168 | try {
169 | InputStreamReader isr = new InputStreamReader(inputStream);
170 | BufferedReader br = new BufferedReader(isr, 32);
171 | String line;
172 | while ((line = br.readLine()) != null) {
173 | if ( line.indexOf(IO_ERROR) != -1 ) {
174 | Log.e( TAG , "IOERRRRRORRRRR -> putting to processStartFailed");
175 | processStartFailed = true;
176 | }
177 | //Log.d( TAG , line + LINE_SEPARATOR);
178 | }
179 | }
180 | catch( Exception e ) {
181 | e.printStackTrace();
182 | }
183 | }
184 |
185 | public void finish() {
186 | if ( inputStream != null ) {
187 | try {
188 | inputStream.close();
189 | }
190 | catch( Exception e) {
191 | e.printStackTrace();
192 | }
193 | }
194 | }
195 |
196 | }
197 |
198 |
199 | }
200 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/pipe/FFMPEGAudioOutputPipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media.pipe;
20 |
21 | import java.io.BufferedReader;
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 | import java.io.InputStreamReader;
25 |
26 | import com.camundo.util.AudioCodec;
27 |
28 | import android.media.AudioFormat;
29 | import android.util.Log;
30 |
31 | public class FFMPEGAudioOutputPipe extends Thread implements AudioOutputPipe {
32 |
33 | private static final String TAG = "FFMPEGAudioOutputPipe";
34 |
35 | private static final String IO_ERROR = "I/O error";
36 |
37 | private final static String LINE_SEPARATOR = System.getProperty("line.separator");
38 |
39 |
40 | private Process process;
41 | private String command;
42 |
43 | private boolean processRunning;
44 | protected boolean processStartFailed;
45 |
46 |
47 | private int bootStrapCount = 0;
48 | private final int minSleepBootstrap = 300;
49 | private final int maxSleepBootstrap = 3000;
50 |
51 | private int currentBootstrapSleep = minSleepBootstrap;
52 |
53 |
54 |
55 | private InputstreamReaderThread errorStreamReaderThread;
56 | //private InputstreamReaderThread inputStreamReaderThread;
57 |
58 |
59 | private InputStream inputStream;
60 |
61 |
62 | public FFMPEGAudioOutputPipe( String command ) {
63 | this.command = command;
64 | }
65 |
66 |
67 | public int read() throws IOException {
68 | return inputStream.read();
69 | }
70 |
71 |
72 | public void bootstrap() throws IOException {
73 | Log.i(TAG , "[ bootstrap() ] avl [" + available() + "]");
74 | while ( available() < 100 ) {
75 | Log.i(TAG , "[ bootstrap() ] avl [" + available() + "]");
76 | try {
77 | if ( processStartFailed ) {
78 | close();
79 | throw new IOException("processStartFailed");
80 | }
81 | if ( currentBootstrapSleep < maxSleepBootstrap && bootStrapCount > 10 ) {
82 | currentBootstrapSleep = currentBootstrapSleep + 100;
83 | }
84 | bootStrapCount++;
85 | Thread.sleep(currentBootstrapSleep);
86 | }
87 | catch( Exception e ) {
88 | e.printStackTrace();
89 | }
90 | }
91 | flush();
92 | Log.i(TAG , "[ bootstrap() ] avl after bootstrap read [" + available() + "]");
93 | }
94 |
95 |
96 | private void flush() throws IOException{
97 | int av = inputStream.available();
98 | inputStream.read(new byte[av] , 0, av);
99 | }
100 |
101 |
102 | public int read( byte[] buffer, int offset, int length ) throws IOException {
103 | return inputStream.read(buffer, offset, length);
104 | }
105 |
106 |
107 | public int read( byte[] buffer ) throws IOException {
108 | return inputStream.read(buffer);
109 | }
110 |
111 |
112 |
113 | public int available() throws IOException {
114 | if ( inputStream != null ) {
115 | return inputStream.available();
116 | }
117 | return 0;
118 |
119 | }
120 |
121 | public InputStream getInputStream() {
122 | return inputStream;
123 | }
124 |
125 |
126 |
127 | public void close() {
128 |
129 | if ( process != null ) {
130 | process.destroy();
131 | process = null;
132 | }
133 |
134 | Log.i(TAG , "[ close() ] closing outputstream");
135 | try {
136 | if ( inputStream != null ) {
137 | synchronized( inputStream) {
138 | inputStream.close();
139 | }
140 | }
141 | }
142 | catch( Exception e ){
143 | e.printStackTrace();
144 | }
145 | if ( errorStreamReaderThread != null ) {
146 | errorStreamReaderThread.finish();
147 | }
148 |
149 | }
150 |
151 |
152 | @Override
153 | public void run () {
154 | try {
155 | Log.d( TAG, "[ run() ] command [" + command + "]");
156 | process = Runtime.getRuntime().exec( command , null);
157 |
158 | inputStream = process.getInputStream();
159 | //inputStreamReaderThread = new InputstreamReaderThread(process.getInputStream());
160 | //inputStream = inputStreamReaderThread.inputStream;
161 |
162 | //Log.d( NAME , "[ run() ] inputStream created");
163 | errorStreamReaderThread = new InputstreamReaderThread(process.getErrorStream());
164 | Log.d( TAG, "[ run() ] errorStreamReader created");
165 |
166 | //inputStreamReaderThread.start();
167 | errorStreamReaderThread.start();
168 |
169 | if ( inputStream != null) {
170 | processRunning = true;
171 | }
172 | else {
173 | processStartFailed = true;
174 | }
175 | }
176 | catch (IOException e) {
177 | e.printStackTrace();
178 | }
179 | }
180 |
181 |
182 | @Override
183 | public boolean initialized() throws IOException {
184 | if ( processStartFailed ) {
185 | throw new IOException("startup of the process Failed");
186 | }
187 | return processRunning;
188 | }
189 |
190 |
191 |
192 | class InputstreamReaderThread extends Thread {
193 |
194 | public InputStream inputStream;
195 |
196 | public InputstreamReaderThread( InputStream i ){
197 | this.inputStream = i;
198 | }
199 |
200 | @Override
201 | public void run() {
202 | try {
203 | InputStreamReader isr = new InputStreamReader(inputStream);
204 | BufferedReader br = new BufferedReader(isr, 32);
205 | String line;
206 | while ( br != null && (line = br.readLine()) != null) {
207 | if ( line.indexOf(IO_ERROR) != -1 ) {
208 | Log.e( TAG , "IOERRRRRORRRRR -> putting to processStartFailed");
209 | processStartFailed = true;
210 | }
211 | //Log.d( TAG , line + LINE_SEPARATOR);
212 | }
213 | }
214 | catch( Exception e ) {
215 | Log.e( TAG, "problem closing reader?", e);
216 | }
217 | }
218 |
219 | public void finish() {
220 | if ( inputStream != null ) {
221 | try {
222 | inputStream.close();
223 | }
224 | catch( Exception e) {
225 | Log.e( TAG, "[ finish() ] problem closing inputstream", e);
226 | }
227 | }
228 | }
229 |
230 | }
231 |
232 |
233 | @Override
234 | public int getSampleRate() {
235 | return AudioCodec.PCM_S16LE.RATE_11025;
236 | }
237 |
238 |
239 | @Override
240 | public int getChannelConfig() {
241 | return AudioFormat.CHANNEL_CONFIGURATION_MONO;
242 | }
243 |
244 |
245 | @Override
246 | public int getEncoding() {
247 | return AudioFormat.ENCODING_PCM_16BIT;
248 | }
249 |
250 |
251 | }
252 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/pipe/FileAudioOutputPipe.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media.pipe;
20 |
21 | import java.io.File;
22 | import java.io.FileInputStream;
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 |
26 | import android.media.AudioFormat;
27 | import android.util.Log;
28 |
29 | import com.camundo.util.AudioCodec;
30 | import com.camundo.util.WavInfo;
31 |
32 | public class FileAudioOutputPipe extends Thread implements AudioOutputPipe {
33 |
34 | private static final String TAG = "FileOutputPipe";
35 |
36 | private File file;
37 | private InputStream inputStream;
38 | private int sampleRate;
39 | private int channels;
40 |
41 | private boolean closed = false;
42 |
43 | public FileAudioOutputPipe(File file) {
44 | this.file = file;
45 | }
46 |
47 | public int read() throws IOException {
48 | return inputStream.read();
49 | }
50 |
51 |
52 | public void bootstrap() throws IOException {
53 | Log.i(TAG, "[ bootstrap() ] avl [" + available() + "]");
54 | while (available() < 100) {
55 | Log.i(TAG, "[ bootstrap() ] avl [" + available() + "]");
56 | try {
57 | Thread.sleep(1000);
58 | } catch (Exception e) {
59 | e.printStackTrace();
60 | }
61 | }
62 | flush();
63 | Log.i(TAG, "[ bootstrap() ] avl after bootstrap read [" + available()
64 | + "]");
65 | }
66 |
67 |
68 | private void flush() throws IOException {
69 | int av = 100;
70 | inputStream.read(new byte[av], 0, av);
71 | }
72 |
73 | public int available() throws IOException {
74 | if (inputStream != null) {
75 | return inputStream.available();
76 | }
77 | return 0;
78 |
79 | }
80 |
81 | public int read(byte[] buffer, int offset, int length) throws IOException {
82 | return inputStream.read(buffer, offset, length);
83 | }
84 |
85 | public int read(byte[] buffer) throws IOException {
86 | if (!closed) {
87 | return inputStream.read(buffer);
88 | }
89 | return -1;
90 | }
91 |
92 | public void close() {
93 | try {
94 | if (!closed) {
95 | synchronized (inputStream) {
96 | inputStream.close();
97 | closed = true;
98 | }
99 | }
100 | } catch (Exception e) {
101 | e.printStackTrace();
102 | }
103 | }
104 |
105 | @Override
106 | public void start() {
107 | try {
108 | inputStream = new FileInputStream(file);
109 | WavInfo w = AudioCodec.WaveFile.readHeader(inputStream);
110 | this.sampleRate = w.rate;
111 | this.channels = w.channels;
112 | } catch (IOException e) {
113 | e.printStackTrace();
114 | }
115 | }
116 |
117 | public boolean initialized() {
118 | return true;
119 | }
120 |
121 | @Override
122 | public int getSampleRate() {
123 | return sampleRate;
124 | }
125 |
126 | @Override
127 | public int getChannelConfig() {
128 | if (channels == 1) {
129 | return AudioFormat.CHANNEL_OUT_MONO;
130 | } else if (channels == 2) {
131 | return AudioFormat.CHANNEL_OUT_STEREO;
132 | }
133 | return 0;
134 | }
135 |
136 | @Override
137 | public int getEncoding() {
138 | return AudioFormat.ENCODING_PCM_16BIT;
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/media/pipe/PipeFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.media.pipe;
20 |
21 | import com.camundo.util.AudioCodec;
22 | import com.camundo.util.FFMPEGBootstrap;
23 | import com.camundo.util.FFMPEGWrapper;
24 |
25 | public class PipeFactory {
26 |
27 | private FFMPEGWrapper ffWrapper;
28 | private String ffmpegCommand;
29 |
30 | public PipeFactory() {
31 | ffWrapper = FFMPEGWrapper.getInstance();
32 | ffmpegCommand = ffWrapper.data_location + ffWrapper.ffmpeg;
33 | }
34 |
35 |
36 | public AudioInputPipe getADPCMAudioInputPipe(String publisherString) {
37 | String command = ffmpegCommand
38 | + " -analyzeduration 0 -i pipe:0 -re -vn -acodec "
39 | + AudioCodec.ADPCM_SWF.name + " -ar "
40 | + AudioCodec.ADPCM_SWF.RATE_11025 + " -ac 1 -f flv "
41 | + publisherString;
42 | return newAudioInputPipe(command);
43 | }
44 |
45 |
46 | public AudioInputPipe getNellymoserAudioInputPipe(String publisherString) {
47 | String command = ffmpegCommand
48 | + " -analyzeduration 0 -muxdelay 0 -muxpreload 0 -i pipe:0 -re -vn -acodec "
49 | + AudioCodec.Nellymoser.name
50 | + " -ar 8000 -ac 1 -ab 16k -f flv " + publisherString;
51 | return newAudioInputPipe(command);
52 | }
53 |
54 |
55 | public AudioInputPipe getAACAudioInputPipe(String publisherString)
56 | throws Exception {
57 | // in case of aac, string should start with mp4: to be recognized by
58 | // red5
59 | // if ( publisherString.indexOf("mp4:") == -1) {
60 | // throw new
61 | // Exception("Publisher string should contain 'mp4:' for aac");
62 | // }
63 | String command = ffmpegCommand
64 | + " -strict experimental -analyzeduration 0 -muxdelay 0 -muxpreload 0 -i pipe:0 -re -vn -acodec "
65 | + AudioCodec.AAC.name + " -ac 1 -ar 8000 -ab 16k -f flv "
66 | + publisherString;
67 | return newAudioInputPipe(command);
68 | }
69 |
70 |
71 | public AudioOutputPipe getAudioOutputPipe(String publisherString,
72 | int audioFileFormat, String codecName, String sourceCodec) {
73 | String command;
74 | // add -strict experimental and acodec for AAC
75 | if (sourceCodec.equals(AudioCodec.AAC.name)) {
76 | command = ffmpegCommand
77 | + " -strict experimental -acodec aac -analyzeduration 0 -muxdelay 0 -muxpreload 0 -vn -itsoffset -2 -i "
78 | + publisherString + " -re -vn -acodec ";
79 | } else if (sourceCodec.equals(AudioCodec.Nellymoser.name)) {
80 | command = ffmpegCommand
81 | + " -analyzeduration 0 -vn -itsoffset -5 -acodec nellymoser -ar 8000 -ac 1 -i "
82 | + publisherString + " -re -vn -acodec ";
83 | } else if (sourceCodec.equals(AudioCodec.ADPCM_SWF.name)) {
84 | command = ffmpegCommand
85 | + " -acodec adpcm_swf -analyzeduration 0 -muxdelay 0 -muxpreload 0 -vn -itsoffset -2 -i "
86 | + publisherString + " -re -vn -acodec ";
87 | } else {
88 | throw new UnsupportedOperationException(
89 | "no support dor source codec [" + sourceCodec + "]");
90 | }
91 | if (audioFileFormat == AudioCodec.AUDIO_FILE_FORMAT_WAV) {
92 | if (codecName.equals(AudioCodec.PCM_S16LE.name)) {
93 | command += AudioCodec.PCM_S16LE.name + " -ar "
94 | + AudioCodec.PCM_S16LE.RATE_11025 + " -ac 1";
95 | }
96 | command += " -f wav pipe:1";
97 | }
98 | FFMPEGAudioOutputPipe pipe = new FFMPEGAudioOutputPipe(command);
99 | return pipe;
100 | }
101 |
102 |
103 | private FFMPEGAudioInputPipe newAudioInputPipe(String command) {
104 | FFMPEGAudioInputPipe pipe = new FFMPEGAudioInputPipe(command);
105 | pipe.setBootstrap(FFMPEGBootstrap.AMR_BOOTSTRAP);
106 | return pipe;
107 | }
108 |
109 |
110 | public AudioInputPipe getVideoInputPipe(String publisherString) {
111 | String command = ffmpegCommand
112 | + " -analyzeduration 0 -i pipe:0 -re -an -r 25 -f flv -b 100k -s 320x240 "
113 | + publisherString;
114 | FFMPEGAudioInputPipe pipe = new FFMPEGAudioInputPipe(command);
115 | return pipe;
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/util/AudioCodec.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.util;
20 |
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 | import java.nio.ByteBuffer;
24 | import java.nio.ByteOrder;
25 |
26 |
27 | import android.util.Log;
28 |
29 | public class AudioCodec {
30 |
31 | public static final String TAG = "AudioCodec";
32 |
33 |
34 | static final int WAVE_FORMAT_PCM = 0x0001;
35 | static final int WAVE_FORMAT_IEEE_FLOAT = 0x0003 ;
36 | static final int WAVE_FORMAT_EXTENSIBLE = 0xFFFE;
37 |
38 | static final String title = "RiffRead32 " ;
39 | static final String[] infotype = {"IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM",
40 | "IDPI", "IENG", "IGNR", "IKEY", "ILGT", "IMED", "INAM", "IPLT", "IPRD", "ISBJ",
41 | "ISFT", "ISHP", "ISRC", "ISRF", "ITCH", "ISMP", "IDIT" } ;
42 |
43 | static final String[] infodesc = {"Archival location", "Artist", "Commissioned", "Comments", "Copyright",
44 | "Creation date","Cropped", "Dimensions", "Dots per inch", "Engineer", "Genre", "Keywords",
45 | "Lightness settings", "Medium", "Name of subject", "Palette settings", "Product", "Description",
46 | "Software package", "Sharpness", "Source", "Source form", "Digitizing technician",
47 | "SMPTE time code", "Digitization time"};
48 |
49 |
50 |
51 | public static final int AUDIO_FILE_FORMAT_WAV = 1;
52 |
53 |
54 | public static class ADPCM_SWF {
55 |
56 | public static final String name = "adpcm_swf";
57 |
58 | public static final int RATE_11025 = 11025;
59 | public static final int RATE_22050 = 22050;
60 | public static final int RATE_44100 = 44100;
61 |
62 | }
63 |
64 |
65 | public static class Nellymoser {
66 |
67 | public static final String name = "nellymoser";
68 |
69 | }
70 |
71 | public static class AAC {
72 |
73 | public static final String name = "aac";
74 |
75 | }
76 |
77 |
78 | public static class AMRNB {
79 |
80 | public static final String name = "amrnb";
81 |
82 | public static final int RATE_8000 = 8000;
83 |
84 | //[libopencore_amrnb @ 0x1418930] bitrate not supported: use one of 4.75k, 5.15k, 5.9k, 6.7k, 7.4k, 7.95k, 10.2k or 12.2k
85 | public static final String BITRATE_4_75k = "4.75k";
86 | public static final String BITRATE_5_15k = "5.15k";
87 | public static final String BITRATE_5_9k = "5.9k";
88 | public static final String BITRATE_6_7k = "6.7k";
89 | public static final String BITRATE_7_4k = "7.4k";
90 | public static final String BITRATE_7_95k = "7.95k";
91 | public static final String BITRATE_10_2k = "10.2k";
92 | public static final String BITRATE_12_2k = "12.2k";
93 |
94 | }
95 |
96 |
97 | public static class WaveFile {
98 |
99 | public static final int HEADER_SIZE = 44;
100 |
101 | public static WavInfo readHeader(InputStream wavStream) throws IOException {
102 |
103 | ByteBuffer buffer = ByteBuffer.allocate(HEADER_SIZE);
104 | buffer.order(ByteOrder.LITTLE_ENDIAN);
105 |
106 | wavStream.read(buffer.array(), buffer.arrayOffset(), buffer.capacity());
107 |
108 | buffer.rewind();
109 | buffer.position(buffer.position() + 20);
110 | int format = buffer.getShort();
111 | checkFormat(format == 1, "Unsupported encoding: " + format); // 1 means Linear PCM
112 | int channels = buffer.getShort();
113 | checkFormat(channels == 1 || channels == 2, "Unsupported channels: " + channels);
114 | int rate = buffer.getInt();
115 | checkFormat(rate <= 48000 && rate >= 11025, "Unsupported rate: " + rate);
116 | buffer.position(buffer.position() + 6);
117 | int bits = buffer.getShort();
118 | checkFormat(bits == 16, "Unsupported bits: " + bits);
119 | int dataSize = 0;
120 |
121 | /*
122 | while (buffer.getInt() != 0x61746164) { // "data" marker
123 | Log.d( TAG , "Skipping non-data chunk");
124 | int size = buffer.getInt();
125 | wavStream.skip(size);
126 | buffer.rewind();
127 | wavStream.read(buffer.array(), buffer.arrayOffset(), 8);
128 | buffer.rewind();
129 | }
130 | dataSize = buffer.getInt();
131 | checkFormat(dataSize > 0, "wrong datasize: " + dataSize);*/
132 |
133 | return new WavInfo( rate, channels, dataSize);
134 | }
135 |
136 | private static void checkFormat( boolean b , String s) throws IOException {
137 | if (!b ) {
138 | throw new IOException(s);
139 | }
140 | }
141 |
142 |
143 |
144 | }
145 |
146 |
147 | public static class PCM_S16LE {
148 | public static final String name = "pcm_s16le";
149 | public static final int RATE_8000 = 8000;
150 | public static final int RATE_11025 = 11025;
151 | public static final int RATE_44100 = 44100;
152 |
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/util/FFMPEGBootstrap.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.util;
20 |
21 | import java.io.ByteArrayOutputStream;
22 | import java.io.InputStream;
23 |
24 | import com.camundo.Camundo;
25 |
26 | /**
27 | * Bootstrap makes ffmpeg go faster ( already connects to rtmp e.g. )
28 | * @author wouter
29 | *
30 | */
31 | public class FFMPEGBootstrap {
32 |
33 | static {
34 | try {
35 | InputStream inputStream = Camundo.getContext().getAssets().open("bootstrap.amr");
36 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
37 | byte buf[]=new byte[1024];
38 | int len;
39 | while((len=inputStream.read(buf))>0) {
40 | baos.write(buf,0,len);
41 | }
42 | AMR_BOOTSTRAP = baos.toByteArray();
43 | inputStream.close();
44 | }
45 | catch( Exception e ) {
46 | e.printStackTrace();
47 | }
48 | }
49 |
50 |
51 | public static byte[] AMR_BOOTSTRAP;
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/util/FFMPEGWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.util;
20 |
21 | import java.io.BufferedReader;
22 | import java.io.File;
23 | import java.io.FileOutputStream;
24 | import java.io.IOException;
25 | import java.io.InputStream;
26 | import java.io.InputStreamReader;
27 | import java.io.OutputStream;
28 |
29 | import android.util.Log;
30 |
31 | import com.camundo.Camundo;
32 |
33 | public class FFMPEGWrapper {
34 |
35 | private final static String TAG = "FFMPEGWrapper";
36 |
37 | private static FFMPEGWrapper _instance = null;
38 |
39 | public final String ffmpeg = "ffmpeg";
40 | public final String data_location = "/data/data/com.camundo/";
41 |
42 | private static final String[] ffmpeg_parts = { "xaa", "xab", "xac" };
43 |
44 |
45 | private FFMPEGWrapper() {}
46 |
47 |
48 | public static synchronized FFMPEGWrapper getInstance() {
49 | if ( _instance == null ) {
50 | _instance = new FFMPEGWrapper();
51 | try {
52 | _instance.initialize();
53 | }
54 | catch( Exception e) {
55 | e.printStackTrace();
56 | _instance = null;
57 | }
58 | }
59 | return _instance;
60 | }
61 |
62 |
63 | /**
64 | * Initializes the component
65 | * @throws Exception
66 | */
67 | private void initialize() throws Exception {
68 | File dl = new File(data_location);
69 | if ( !dl.exists() ) {
70 | dl.mkdirs();
71 | }
72 | File target = new File(data_location + ffmpeg);
73 | writeFFMPEGToData( false, target);
74 | }
75 |
76 |
77 |
78 | /**
79 | * Write ffmpeg to data directory and make it executable
80 | * write in parts because assets can not be bigger then 1MB
81 | * TODO make it fetch the parts over http, this way consuming less space on the device but...
82 | * @param overwrite
83 | * @param target
84 | * @throws Exception
85 | */
86 | private void writeFFMPEGToData( boolean overwrite, File target) throws Exception {
87 | if ( !overwrite && target.exists()) {
88 | return;
89 | }
90 | OutputStream out = new FileOutputStream(target);
91 | byte buf[]=new byte[1024];
92 | for ( String p : ffmpeg_parts ) {
93 | InputStream inputStream = Camundo.getContext().getAssets().open(p);
94 | int len;
95 | while((len=inputStream.read(buf))>0) {
96 | out.write(buf,0,len);
97 | }
98 | inputStream.close();
99 | }
100 | out.close();
101 | Log.d( TAG , executeCommand("/system/bin/chmod 744 " + target.getAbsolutePath()));
102 | Log.d( TAG, "File [" + target.getAbsolutePath() + "] is created.");
103 | }
104 |
105 |
106 |
107 |
108 |
109 | private String executeCommand( String command ) {
110 | try {
111 | Process process = Runtime.getRuntime().exec(command);
112 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()), 16);
113 | int read;
114 | char[] buffer = new char[4096];
115 | StringBuffer output = new StringBuffer();
116 | while ((read = reader.read(buffer)) > 0) {
117 | output.append(buffer, 0, read);
118 | }
119 | reader.close();
120 |
121 |
122 | BufferedReader reader2 = new BufferedReader(new InputStreamReader(process.getErrorStream()), 16);
123 | StringBuffer output2 = new StringBuffer();
124 | while ((read = reader2.read(buffer)) > 0) {
125 | output2.append(buffer, 0, read);
126 | }
127 | reader2.close();
128 |
129 | // Waits for the command to finish.
130 | process.waitFor();
131 |
132 | return output.toString() + output2.toString();
133 | }
134 | catch (IOException e) {
135 | throw new RuntimeException(e);
136 | }
137 | catch (InterruptedException e) {
138 | throw new RuntimeException(e);
139 | }
140 | }
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/util/NetworkUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.util;
20 |
21 | import android.content.Context;
22 | import android.net.ConnectivityManager;
23 | import android.net.NetworkInfo;
24 |
25 | public class NetworkUtils {
26 |
27 |
28 | public static boolean isOnline( Context context ) {
29 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
30 | NetworkInfo netInfo = cm.getActiveNetworkInfo();
31 | if (netInfo != null && netInfo.isConnected()) {
32 | return true;
33 | }
34 | return false;
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/android-ffmpeg-prototype/src/com/camundo/util/WavInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Camundo Copyright (C) 2011 Wouter Van der Beken.
3 | *
4 | * This file is part of Camundo.
5 | *
6 | * Camundo is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * Camundo is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with Camundo. If not, see .
18 | */
19 | package com.camundo.util;
20 |
21 | public class WavInfo {
22 |
23 | public int rate;
24 | public int channels;
25 | public int dataSize;
26 |
27 | public WavInfo( int rate, int channels, int dataSize ) {
28 | this.rate = rate;
29 | this.channels = channels;
30 | this.dataSize = dataSize;
31 | }
32 | }
--------------------------------------------------------------------------------