Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95261c1ade | |||
| ca0bb9fd0f | |||
| 12f52514b8 | |||
| 64488a818a | |||
| c7e7cc20ef | |||
| efe1c59a20 | |||
| 4605e778c5 | |||
| ec851d33a3 | |||
| b5565bd359 | |||
| 9229cf50c4 | |||
| 7cf14d21e4 | |||
| 4e92d550fd | |||
| 1157681271 | |||
| 78e5411df9 | |||
| 46b538107b | |||
| fd11dd5004 | |||
| 9da84b3edb | |||
| 639dbb3ccb | |||
| d8b1754272 | |||
| 73e2cc557f | |||
| b70229b9e7 | |||
| 47a9b728d7 | |||
| 32f25905cb | |||
| 35c26b390c | |||
| b9549a04e7 | |||
| c6840985e6 | |||
| 8e671be23d | |||
| 807051ce3c | |||
| c38ebd52b6 | |||
| 37ba9a95c1 | |||
| 99ae2531a4 | |||
| 60accc6233 | |||
| 35fd709066 | |||
| 57ebc9a177 | |||
| dcb1935b57 | |||
| 815b122cef | |||
| f3a279348d | |||
| 920aa583b9 | |||
| 1e7a4bb3f2 | |||
| e92ba21784 | |||
| 0d47a43829 | |||
| 77d4f80ba6 | |||
| ab0ecc624d | |||
| 7d9747789b | |||
| dfdadf656b | |||
| ef03a31d23 | |||
| 8041678c13 | |||
| 283ebe29a4 | |||
| bdbabb5a18 | |||
| 4e078bb9e8 | |||
| 240def7581 | |||
| cc1a5bd4b2 | |||
| 6ae6627d97 | |||
| b151e6ab81 | |||
| e3c0e4d2e7 | |||
| 9dec4e0353 | |||
| 062ca46069 | |||
| 267e8236f5 | |||
| 4f3380c7fe | |||
| 7692c42c64 | |||
| 71a1289c32 | |||
| 911a8f5478 | |||
| 54fe0bd773 | |||
| 7c99fcdeac | |||
| 47c590c2b1 | |||
| 3e307bb4d6 | |||
| feece0ea50 | |||
| 540e180e53 | |||
| 38398cb128 | |||
| a416890244 |
+63
-24
@@ -2,36 +2,32 @@ branches:
|
||||
only:
|
||||
- master
|
||||
- development
|
||||
sudo: false
|
||||
git:
|
||||
quiet: true
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- autoconf
|
||||
- automake
|
||||
- libtool
|
||||
- pkg-config
|
||||
- curl
|
||||
- git
|
||||
- cmake
|
||||
- gcc
|
||||
- gperf
|
||||
- texinfo
|
||||
- yasm
|
||||
- nasm
|
||||
- bison
|
||||
- autogen
|
||||
- patch
|
||||
homebrew:
|
||||
packages:
|
||||
- nasm
|
||||
update: true
|
||||
matrix:
|
||||
jobs:
|
||||
include:
|
||||
- name: "Android Main Build"
|
||||
language: android
|
||||
os: linux
|
||||
dist : trusty
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- autoconf
|
||||
- automake
|
||||
- libtool
|
||||
- pkg-config
|
||||
- curl
|
||||
- git
|
||||
- cmake
|
||||
- gcc
|
||||
- gperf
|
||||
- texinfo
|
||||
- yasm
|
||||
- nasm
|
||||
- bison
|
||||
- autogen
|
||||
- patch
|
||||
android:
|
||||
components:
|
||||
- tools
|
||||
@@ -59,7 +55,26 @@ matrix:
|
||||
- bash ./android.sh --no-output-redirection
|
||||
- name: "Android LTS Build"
|
||||
language: android
|
||||
os: linux
|
||||
dist : trusty
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- autoconf
|
||||
- automake
|
||||
- libtool
|
||||
- pkg-config
|
||||
- curl
|
||||
- git
|
||||
- cmake
|
||||
- gcc
|
||||
- gperf
|
||||
- texinfo
|
||||
- yasm
|
||||
- nasm
|
||||
- bison
|
||||
- autogen
|
||||
- patch
|
||||
android:
|
||||
components:
|
||||
- tools
|
||||
@@ -88,7 +103,13 @@ matrix:
|
||||
- bash ./android.sh --lts --no-output-redirection
|
||||
- name: "iOS Main Build"
|
||||
language: objective-c
|
||||
os: osx
|
||||
osx_image: xcode10.2
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- nasm
|
||||
update: true
|
||||
before_script:
|
||||
- rm -f ./build.log
|
||||
after_success:
|
||||
@@ -101,6 +122,12 @@ matrix:
|
||||
- name: "iOS LTS Build"
|
||||
language: objective-c
|
||||
osx_image: xcode7.3
|
||||
os: osx
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- nasm
|
||||
update: true
|
||||
before_script:
|
||||
- rm -f ./build.log
|
||||
after_success:
|
||||
@@ -112,7 +139,13 @@ matrix:
|
||||
- bash ./ios.sh --lts --no-output-redirection
|
||||
- name: "tvOS Main Build"
|
||||
language: objective-c
|
||||
os: osx
|
||||
osx_image: xcode10.2
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- nasm
|
||||
update: true
|
||||
before_script:
|
||||
- rm -f ./build.log
|
||||
after_success:
|
||||
@@ -124,7 +157,13 @@ matrix:
|
||||
- bash ./tvos.sh --no-output-redirection
|
||||
- name: "tvOS LTS Build"
|
||||
language: objective-c
|
||||
os: osx
|
||||
osx_image: xcode7.3
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- nasm
|
||||
update: true
|
||||
before_script:
|
||||
- rm -f ./build.log
|
||||
after_success:
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
# MobileFFmpeg    [](https://travis-ci.org/tanersener/mobile-ffmpeg)
|
||||
# MobileFFmpeg [](https://opencollective.com/mobile-ffmpeg)    [](https://travis-ci.org/tanersener/mobile-ffmpeg)
|
||||
|
||||
FFmpeg for Android, iOS and tvOS
|
||||
|
||||
<img src="https://github.com/tanersener/mobile-ffmpeg/blob/master/docs/assets/mobile-ffmpeg-logo-v7.png" width="320">
|
||||
|
||||
### 0. Backers via Patreon
|
||||
|
||||
<a href="https://github.com/wjzhangcsu/" target="_blank">
|
||||
<img width="40px" src="https://avatars0.githubusercontent.com/u/11661685?s=460&v=4">
|
||||
</a>
|
||||
|
||||
### 1. Features
|
||||
- Includes both `FFmpeg` and `FFprobe`
|
||||
- Use binaries available at `Github`/`JCenter`/`CocoaPods` or build your own version with external libraries you need
|
||||
- Supports
|
||||
- Android, iOS and tvOS
|
||||
- FFmpeg `v3.4.x`, `v4.0.x`, `v4.1`, `v4.2-dev` and `v4.3-dev` releases
|
||||
- FFmpeg `v3.4.x`, `v4.0.x`, `v4.1`, `v4.2` and `v4.3-dev` releases
|
||||
- 28 external libraries
|
||||
|
||||
`chromaprint`, `fontconfig`, `freetype`, `fribidi`, `gmp`, `gnutls`, `kvazaar`, `lame`, `libaom`, `libass`, `libiconv`, `libilbc`, `libtheora`, `libvorbis`, `libvpx`, `libwebp`, `libxml2`, `opencore-amr`, `openh264`, `opus`, `sdl`, `shine`, `snappy`, `soxr`, `speex`, `tesseract`, `twolame`, `wavpack`
|
||||
@@ -23,6 +18,8 @@ FFmpeg for Android, iOS and tvOS
|
||||
|
||||
`vid.stab`, `x264`, `x265`, `xvidcore`
|
||||
|
||||
- Concurrent execution
|
||||
|
||||
- Exposes both FFmpeg library and MobileFFmpeg wrapper library capabilities
|
||||
- Includes cross-compile instructions for 44 open-source libraries
|
||||
|
||||
@@ -39,8 +36,8 @@ FFmpeg for Android, iOS and tvOS
|
||||
- Supports `API Level 16+`
|
||||
|
||||
#### 1.2 iOS
|
||||
- Builds `armv7`, `armv7s`, `arm64`, `arm64e`, `i386` and `x86_64` architectures
|
||||
- Supports `bzip2`, `zlib` system libraries and `AudioToolbox`, `CoreImage`, `VideoToolbox`, `AVFoundation` system frameworks
|
||||
- Builds `armv7`, `armv7s`, `arm64`, `arm64e`, `i386`, `x86_64` and `x86_64` (Mac Catalyst) architectures
|
||||
- Supports `bzip2`, `iconv`, `libuuid`, `zlib` system libraries and `AudioToolbox`, `CoreImage`, `VideoToolbox`, `AVFoundation` system frameworks
|
||||
- Objective-C API
|
||||
- Camera access
|
||||
- `ARC` enabled library
|
||||
@@ -50,7 +47,7 @@ FFmpeg for Android, iOS and tvOS
|
||||
|
||||
#### 1.3 tvOS
|
||||
- Builds `arm64` and `x86_64` architectures
|
||||
- Supports `bzip2`, `zlib` system libraries and `AudioToolbox`, `CoreImage`, `VideoToolbox` system frameworks
|
||||
- Supports `bzip2`, `zlib`, `iconv` system libraries and `AudioToolbox`, `CoreImage`, `VideoToolbox` system frameworks
|
||||
- Objective-C API
|
||||
- `ARC` enabled library
|
||||
- Built with `-fembed-bitcode` flag
|
||||
@@ -96,11 +93,11 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><sup>ios system libraries</sup></td>
|
||||
<td align="center" colspan=8><sup>zlib</sup><br><sup>AudioToolbox</sup><br><sup>AVFoundation</sup><br><sup>CoreImage</sup><br><sup>VideoToolbox</sup><br><sup>bzip2</sup></td>
|
||||
<td align="center" colspan=8><sup>zlib</sup><br><sup>AudioToolbox</sup><br><sup>AVFoundation</sup><br><sup>CoreImage</sup><br><sup>iconv</sup><br><sup>VideoToolbox</sup><br><sup>bzip2</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><sup>tvos system libraries</sup></td>
|
||||
<td align="center" colspan=8><sup>zlib</sup><br><sup>AudioToolbox</sup><br><sup>CoreImage</sup><br><sup>VideoToolbox</sup><br><sup>bzip2</sup></td>
|
||||
<td align="center" colspan=8><sup>zlib</sup><br><sup>AudioToolbox</sup><br><sup>CoreImage</sup><br><sup>iconv</sup><br><sup>VideoToolbox</sup><br><sup>bzip2</sup></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -116,25 +113,52 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
- Since `v4.2`, `chromaprint`, `sdl` and `tesseract` libraries are not included in binary releases. You can still build them and include in your releases
|
||||
|
||||
- `AVFoundation` is not available on `tvOS`, `VideoToolbox` is not available on `tvOS` LTS releases
|
||||
|
||||
- Since `v4.3.1`, `iOS` and `tvOS` releases started to use `iconv` system library instead of `iconv` external library
|
||||
|
||||
#### 2.1 Android
|
||||
1. Add MobileFFmpeg dependency to your `build.gradle` in `mobile-ffmpeg-<package name>` format
|
||||
```
|
||||
dependencies {
|
||||
implementation 'com.arthenica:mobile-ffmpeg-full:4.3'
|
||||
implementation 'com.arthenica:mobile-ffmpeg-full:4.3.1'
|
||||
}
|
||||
```
|
||||
|
||||
2. Execute commands.
|
||||
2. Execute FFmpeg commands.
|
||||
```
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
|
||||
FFmpeg.execute("-i file1.mp4 -c:v mpeg4 file2.mp4");
|
||||
int rc = FFmpeg.execute("-i file1.mp4 -c:v mpeg4 file2.mp4");
|
||||
|
||||
if (rc == RETURN_CODE_SUCCESS) {
|
||||
Log.i(Config.TAG, "Command execution completed successfully.");
|
||||
} else if (rc == RETURN_CODE_CANCEL) {
|
||||
Log.i(Config.TAG, "Command execution cancelled by user.");
|
||||
} else {
|
||||
Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc));
|
||||
Config.printLastCommandOutput(Log.INFO);
|
||||
}
|
||||
```
|
||||
|
||||
3. Check execution output.
|
||||
3. Execute FFprobe commands.
|
||||
```
|
||||
int rc = FFmpeg.getLastReturnCode();
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFprobe;
|
||||
|
||||
int rc = FFprobe.execute("-i file1.mp4");
|
||||
|
||||
if (rc == RETURN_CODE_SUCCESS) {
|
||||
Log.i(Config.TAG, "Command execution completed successfully.");
|
||||
} else {
|
||||
Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc));
|
||||
Config.printLastCommandOutput(Log.INFO);
|
||||
}
|
||||
```
|
||||
|
||||
4. Check execution output later.
|
||||
```
|
||||
int rc = Config.getLastReturnCode();
|
||||
|
||||
if (rc == RETURN_CODE_SUCCESS) {
|
||||
Log.i(Config.TAG, "Command execution completed successfully.");
|
||||
@@ -142,31 +166,31 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
Log.i(Config.TAG, "Command execution cancelled by user.");
|
||||
} else {
|
||||
Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc));
|
||||
FFmpeg.printLastCommandOutput(Log.INFO);
|
||||
Config.printLastCommandOutput(Log.INFO);
|
||||
}
|
||||
```
|
||||
|
||||
4. Stop an ongoing operation.
|
||||
5. Stop an ongoing FFmpeg operation.
|
||||
```
|
||||
FFmpeg.cancel();
|
||||
```
|
||||
|
||||
5. Get media information for a file.
|
||||
6. Get media information for a file.
|
||||
```
|
||||
MediaInformation info = FFmpeg.getMediaInformation("<file path or uri>");
|
||||
MediaInformation info = FFprobe.getMediaInformation("<file path or uri>");
|
||||
```
|
||||
|
||||
6. Record video using Android camera.
|
||||
7. Record video using Android camera.
|
||||
```
|
||||
FFmpeg.execute("-f android_camera -i 0:0 -r 30 -pixel_format bgr0 -t 00:00:05 <record file path>");
|
||||
```
|
||||
|
||||
7. List enabled external libraries.
|
||||
8. List enabled external libraries.
|
||||
```
|
||||
List<String> externalLibraries = Config.getExternalLibraries();
|
||||
```
|
||||
|
||||
8. Enable log callback.
|
||||
9. Enable log callback.
|
||||
```
|
||||
Config.enableLogCallback(new LogCallback() {
|
||||
public void apply(LogMessage message) {
|
||||
@@ -175,7 +199,7 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
});
|
||||
```
|
||||
|
||||
9. Enable statistics callback.
|
||||
10. Enable statistics callback.
|
||||
```
|
||||
Config.enableStatisticsCallback(new StatisticsCallback() {
|
||||
public void apply(Statistics newStatistics) {
|
||||
@@ -184,12 +208,12 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
});
|
||||
```
|
||||
|
||||
10. Set log level.
|
||||
11. Set log level.
|
||||
```
|
||||
Config.setLogLevel(Level.AV_LOG_FATAL);
|
||||
```
|
||||
|
||||
11. Register custom fonts directory.
|
||||
12. Register custom fonts directory.
|
||||
```
|
||||
Config.setFontDirectory(this, "<folder with fonts>", Collections.EMPTY_MAP);
|
||||
```
|
||||
@@ -199,25 +223,50 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
|
||||
- iOS
|
||||
```
|
||||
pod 'mobile-ffmpeg-full', '~> 4.3'
|
||||
pod 'mobile-ffmpeg-full', '~> 4.3.1'
|
||||
```
|
||||
|
||||
- tvOS
|
||||
```
|
||||
pod 'mobile-ffmpeg-tv-full', '~> 4.3'
|
||||
pod 'mobile-ffmpeg-tvos-full', '~> 4.3.1'
|
||||
```
|
||||
|
||||
2. Execute commands.
|
||||
2. Execute FFmpeg commands.
|
||||
```
|
||||
#import <mobileffmpeg/MobileFFmpegConfig.h>
|
||||
#import <mobileffmpeg/MobileFFmpeg.h>
|
||||
|
||||
[MobileFFmpeg execute: @"-i file1.mp4 -c:v mpeg4 file2.mp4"];
|
||||
int rc = [MobileFFmpeg execute: @"-i file1.mp4 -c:v mpeg4 file2.mp4"];
|
||||
|
||||
if (rc == RETURN_CODE_SUCCESS) {
|
||||
NSLog(@"Command execution completed successfully.\n");
|
||||
} else if (rc == RETURN_CODE_CANCEL) {
|
||||
NSLog(@"Command execution cancelled by user.\n");
|
||||
} else {
|
||||
NSLog(@"Command execution failed with rc=%d and output=%@.\n", rc, [MobileFFmpegConfig getLastCommandOutput]);
|
||||
}
|
||||
```
|
||||
|
||||
3. Check execution output.
|
||||
3. Execute FFprobe commands.
|
||||
```
|
||||
int rc = [MobileFFmpeg getLastReturnCode];
|
||||
NSString *output = [MobileFFmpeg getLastCommandOutput];
|
||||
#import <mobileffmpeg/MobileFFmpegConfig.h>
|
||||
#import <mobileffmpeg/MobileFFprobe.h>
|
||||
|
||||
int rc = [MobileFFprobe execute: @"-i file1.mp4"];
|
||||
|
||||
if (rc == RETURN_CODE_SUCCESS) {
|
||||
NSLog(@"Command execution completed successfully.\n");
|
||||
} else if (rc == RETURN_CODE_CANCEL) {
|
||||
NSLog(@"Command execution cancelled by user.\n");
|
||||
} else {
|
||||
NSLog(@"Command execution failed with rc=%d and output=%@.\n", rc, [MobileFFmpegConfig getLastCommandOutput]);
|
||||
}
|
||||
```
|
||||
|
||||
4. Check execution output later.
|
||||
```
|
||||
int rc = [MobileFFmpegConfig getLastReturnCode];
|
||||
NSString *output = [MobileFFmpegConfig getLastCommandOutput];
|
||||
|
||||
if (rc == RETURN_CODE_SUCCESS) {
|
||||
NSLog(@"Command execution completed successfully.\n");
|
||||
@@ -228,28 +277,28 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
}
|
||||
```
|
||||
|
||||
4. Stop an ongoing operation.
|
||||
5. Stop an ongoing FFmpeg operation.
|
||||
```
|
||||
[MobileFFmpeg cancel];
|
||||
```
|
||||
|
||||
5. Get media information for a file.
|
||||
6. Get media information for a file.
|
||||
```
|
||||
MediaInformation *mediaInformation = [MobileFFmpeg getMediaInformation:@"<file path or uri>"];
|
||||
MediaInformation *mediaInformation = [MobileFFprobe getMediaInformation:@"<file path or uri>"];
|
||||
```
|
||||
|
||||
6. Record video and audio using iOS camera. This operation is not supported on `tvOS` since `AVFoundation` is not available on `tvOS`.
|
||||
7. Record video and audio using iOS camera. This operation is not supported on `tvOS` since `AVFoundation` is not available on `tvOS`.
|
||||
|
||||
```
|
||||
[MobileFFmpeg execute: @"-f avfoundation -r 30 -video_size 1280x720 -pixel_format bgr0 -i 0:0 -vcodec h264_videotoolbox -vsync 2 -f h264 -t 00:00:05 %@", recordFilePath];
|
||||
```
|
||||
|
||||
7. List enabled external libraries.
|
||||
8. List enabled external libraries.
|
||||
```
|
||||
NSArray *externalLibraries = [MobileFFmpegConfig getExternalLibraries];
|
||||
```
|
||||
|
||||
8. Enable log callback.
|
||||
9. Enable log callback.
|
||||
```
|
||||
[MobileFFmpegConfig setLogDelegate:self];
|
||||
|
||||
@@ -260,7 +309,7 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
}
|
||||
```
|
||||
|
||||
9. Enable statistics callback.
|
||||
10. Enable statistics callback.
|
||||
```
|
||||
[MobileFFmpegConfig setStatisticsDelegate:self];
|
||||
|
||||
@@ -271,12 +320,12 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
|
||||
}
|
||||
```
|
||||
|
||||
10. Set log level.
|
||||
11. Set log level.
|
||||
```
|
||||
[MobileFFmpegConfig setLogLevel:AV_LOG_FATAL];
|
||||
```
|
||||
|
||||
11. Register custom fonts directory.
|
||||
12. Register custom fonts directory.
|
||||
```
|
||||
[MobileFFmpegConfig setFontDirectory:@"<folder with fonts>" with:nil];
|
||||
```
|
||||
@@ -313,6 +362,8 @@ Exact version number is obtained using `git describe --tags`.
|
||||
|
||||
| MobileFFmpeg Version | FFmpeg Version | Release Date |
|
||||
| :----: | :----: |:----: |
|
||||
| [4.3.1](https://github.com/tanersener/mobile-ffmpeg/releases/tag/v4.3.1) | 4.3-dev-1944 | Jan 25, 2020 |
|
||||
| [4.3.1.LTS](https://github.com/tanersener/mobile-ffmpeg/releases/tag/v4.3.1.LTS) | 4.3-dev-1944 | Jan 25, 2020 |
|
||||
| [4.3](https://github.com/tanersener/mobile-ffmpeg/releases/tag/v4.3) | 4.3-dev-1181 | Oct 27, 2019 |
|
||||
| [4.2.2](https://github.com/tanersener/mobile-ffmpeg/releases/tag/v4.2.2) | 4.2-dev-1824 | July 3, 2019 |
|
||||
| [4.2.2.LTS](https://github.com/tanersener/mobile-ffmpeg/releases/tag/v4.2.2.LTS) | 4.2-dev-1824 | July 3, 2019 |
|
||||
@@ -448,7 +499,37 @@ CPU optimizations (`ASM`) are enabled for most of the external libraries. Detail
|
||||
|
||||
A more detailed documentation is available at [Wiki](https://github.com/tanersener/mobile-ffmpeg/wiki).
|
||||
|
||||
### 7. License
|
||||
### 7. Contributors
|
||||
|
||||
#### 7.1 Code Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
<a href="https://github.com/tanersener/mobile-ffmpeg/graphs/contributors"><img src="https://opencollective.com/mobile-ffmpeg/contributors.svg?width=890&button=false" /></a>
|
||||
|
||||
#### 7.2 Financial Contributors
|
||||
|
||||
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/mobile-ffmpeg/contribute)]
|
||||
|
||||
##### 7.2.1 Individuals
|
||||
|
||||
<a href="https://opencollective.com/mobile-ffmpeg"><img src="https://opencollective.com/mobile-ffmpeg/individuals.svg?width=890"></a>
|
||||
|
||||
##### 7.2.2 Organizations
|
||||
|
||||
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/mobile-ffmpeg/contribute)]
|
||||
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/0/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/1/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/2/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/3/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/4/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/5/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/6/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/7/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/8/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/mobile-ffmpeg/organization/9/website"><img src="https://opencollective.com/mobile-ffmpeg/organization/9/avatar.svg"></a>
|
||||
|
||||
### 8. License
|
||||
|
||||
This project is licensed under the LGPL v3.0. However, if source code is built using optional `--enable-gpl` flag or
|
||||
prebuilt binaries with `-gpl` postfix are used then MobileFFmpeg is subject to the GPL v3.0 license.
|
||||
@@ -466,11 +547,11 @@ In test applications; embedded fonts are licensed under the [SIL Open Font Licen
|
||||
|
||||
Please visit [License](https://github.com/tanersener/mobile-ffmpeg/wiki/License) page for the details.
|
||||
|
||||
### 8. Contributing
|
||||
### 9. Contributing
|
||||
|
||||
If you have any recommendations or ideas to improve it, please feel free to submit issues or pull requests. Any help is appreciated.
|
||||
|
||||
### 9. See Also
|
||||
### 10. See Also
|
||||
|
||||
- [libav gas-preprocessor](https://github.com/libav/gas-preprocessor/raw/master/gas-preprocessor.pl)
|
||||
- [FFmpeg API Documentation](https://ffmpeg.org/doxygen/4.0/index.html)
|
||||
|
||||
+3
-3
@@ -82,7 +82,7 @@ without any external libraries enabled. Options can be used to disable ABIs and/
|
||||
Please note that GPL libraries (external libraries with GPL license) need --enable-gpl flag to be set explicitly. \
|
||||
When compilation ends an Android Archive (AAR) file is created with enabled platforms inside.\n"
|
||||
|
||||
echo -e "Usage: ./"$COMMAND" [OPTION]...\n"
|
||||
echo -e "Usage: ./"$COMMAND" [OPTION]...\n"
|
||||
|
||||
echo -e "Specify environment variables as VARIABLE=VALUE to override default build options.\n"
|
||||
|
||||
@@ -826,14 +826,14 @@ if [[ ! -z ${ANDROID_ARCHITECTURES} ]]; then
|
||||
|
||||
echo -e -n "\n\nCreating Android archive under prebuilt/android-aar: "
|
||||
|
||||
./gradlew clean build 1>>${BASEDIR}/build.log 2>&1
|
||||
./gradlew app:clean app:assembleRelease app:testReleaseUnitTest 1>>${BASEDIR}/build.log 2>&1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "failed\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp ${BASEDIR}/android/app/build/outputs/aar/mobile-ffmpeg.aar ${MOBILE_FFMPEG_AAR}/mobile-ffmpeg.aar 1>>${BASEDIR}/build.log 2>&1
|
||||
cp ${BASEDIR}/android/app/build/outputs/aar/mobile-ffmpeg-release.aar ${MOBILE_FFMPEG_AAR}/mobile-ffmpeg.aar 1>>${BASEDIR}/build.log 2>&1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "failed\n"
|
||||
|
||||
+6
-8
@@ -1,12 +1,10 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
local.properties
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
build
|
||||
captures
|
||||
.externalNativeBuild
|
||||
/.idea/
|
||||
/obj/
|
||||
/libs/
|
||||
.idea
|
||||
obj
|
||||
libs
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
/build
|
||||
/local.properties
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = "MobileFFmpeg Android API"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 4.3
|
||||
PROJECT_NUMBER = 4.3.1
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 28
|
||||
versionCode 240430
|
||||
versionName "4.3"
|
||||
targetSdkVersion 29
|
||||
versionCode 240431
|
||||
versionName "4.3.1"
|
||||
project.archivesBaseName = "mobile-ffmpeg"
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
@@ -38,7 +38,5 @@ task javadoc(type: Javadoc) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation "androidx.test.ext:junit:1.1.1"
|
||||
}
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.mobileffmpeg;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.arthenica.mobileffmpeg", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,14 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* CHANGES 01.2020
|
||||
* - ffprobe support changes
|
||||
* - (optindex < argc) validation in parse_options() method updated with (optindex >= argc) check
|
||||
*
|
||||
* CHANGES 12.2019
|
||||
* - Concurrent execution support
|
||||
* - log_callback_report method re-added to fix -report option issues
|
||||
*
|
||||
* CHANGES 08.2018
|
||||
* --------------------------------------------------------
|
||||
* - fftools_ prefix added to file name and parent header
|
||||
@@ -85,15 +93,19 @@
|
||||
|
||||
static int init_report(const char *env);
|
||||
extern void mobileffmpeg_log_callback_function(void *ptr, int level, const char* format, va_list vargs);
|
||||
extern void (*report_callback)(int, float, float, int64_t, int, double, double);
|
||||
|
||||
AVDictionary *sws_dict;
|
||||
AVDictionary *swr_opts;
|
||||
AVDictionary *format_opts, *codec_opts, *resample_opts;
|
||||
__thread char *program_name;
|
||||
__thread int program_birth_year;
|
||||
|
||||
static FILE *report_file;
|
||||
static int report_file_level = AV_LOG_DEBUG;
|
||||
int hide_banner = 0;
|
||||
int longjmp_value = 0;
|
||||
__thread AVDictionary *sws_dict;
|
||||
__thread AVDictionary *swr_opts;
|
||||
__thread AVDictionary *format_opts, *codec_opts, *resample_opts;
|
||||
|
||||
FILE *report_file;
|
||||
int report_file_level = AV_LOG_DEBUG;
|
||||
__thread int hide_banner = 0;
|
||||
__thread int longjmp_value = 0;
|
||||
|
||||
enum show_muxdemuxers {
|
||||
SHOW_DEFAULT,
|
||||
@@ -115,9 +127,29 @@ void uninit_opts(void)
|
||||
av_dict_free(&resample_opts);
|
||||
}
|
||||
|
||||
void log_callback_report(void *ptr, int level, const char *fmt, va_list vl)
|
||||
{
|
||||
va_list vl2;
|
||||
char line[1024];
|
||||
static int print_prefix = 1;
|
||||
|
||||
va_copy(vl2, vl);
|
||||
if (report_callback == NULL) {
|
||||
av_log_default_callback(ptr, level, fmt, vl);
|
||||
} else {
|
||||
mobileffmpeg_log_callback_function(ptr, level, fmt, vl);
|
||||
}
|
||||
av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
|
||||
va_end(vl2);
|
||||
if (report_file_level >= level) {
|
||||
fputs(line, report_file);
|
||||
fflush(report_file);
|
||||
}
|
||||
}
|
||||
|
||||
void init_dynload(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#if HAVE_SETDLLDIRECTORY
|
||||
/* Calling SetDllDirectory with the empty string (but not NULL) removes the
|
||||
* current working directory from the DLL search path as a security pre-caution. */
|
||||
SetDllDirectory("");
|
||||
@@ -191,7 +223,7 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
continue;
|
||||
|
||||
if (first) {
|
||||
av_log(NULL, AV_LOG_INFO, "%s\n", msg);
|
||||
av_log(NULL, AV_LOG_STDERR, "%s\n", msg);
|
||||
first = 0;
|
||||
}
|
||||
av_strlcpy(buf, po->name, sizeof(buf));
|
||||
@@ -199,9 +231,9 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
av_strlcat(buf, " ", sizeof(buf));
|
||||
av_strlcat(buf, po->argname, sizeof(buf));
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO, "-%-17s %s\n", buf, po->help);
|
||||
av_log(NULL, AV_LOG_STDERR, "-%-17s %s\n", buf, po->help);
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
|
||||
void show_help_children(const AVClass *class, int flags)
|
||||
@@ -209,7 +241,7 @@ void show_help_children(const AVClass *class, int flags)
|
||||
const AVClass *child = NULL;
|
||||
if (class->option) {
|
||||
av_opt_show2(&class, NULL, flags, 0);
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
|
||||
while ((child = av_opt_child_class_next(class, child)))
|
||||
@@ -401,12 +433,14 @@ void parse_options(void *optctx, int argc, char **argv, const OptionDef *options
|
||||
continue;
|
||||
}
|
||||
opt++;
|
||||
|
||||
if (optindex < argc) {
|
||||
if (optindex >= argc) {
|
||||
if ((ret = parse_option(optctx, opt, NULL, options)) < 0)
|
||||
exit_program(1);
|
||||
} else {
|
||||
if ((ret = parse_option(optctx, opt, argv[optindex], options)) < 0)
|
||||
exit_program(1);
|
||||
optindex += ret;
|
||||
}
|
||||
optindex += ret;
|
||||
} else {
|
||||
if (parse_arg_function)
|
||||
parse_arg_function(optctx, opt);
|
||||
@@ -473,7 +507,7 @@ int locate_option(int argc, char **argv, const OptionDef *options,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_argument(const char *a)
|
||||
void dump_argument(const char *a)
|
||||
{
|
||||
const unsigned char *p;
|
||||
|
||||
@@ -812,7 +846,7 @@ do { \
|
||||
if (optindex < argc) {
|
||||
arg = argv[optindex++];
|
||||
} else {
|
||||
arg = "";
|
||||
arg = NULL;
|
||||
}
|
||||
} else if (po->flags & HAS_ARG) {
|
||||
GET_ARG(arg);
|
||||
@@ -856,8 +890,8 @@ do { \
|
||||
}
|
||||
|
||||
if (octx->cur_group.nb_opts || codec_opts || format_opts || resample_opts)
|
||||
av_log(NULL, AV_LOG_WARNING, "Trailing options were found on the "
|
||||
"commandline.\n");
|
||||
av_log(NULL, AV_LOG_WARNING, "Trailing option(s) found in the "
|
||||
"command: may be ignored.\n");
|
||||
|
||||
av_log(NULL, AV_LOG_DEBUG, "Finished splitting the commandline.\n");
|
||||
|
||||
@@ -983,11 +1017,12 @@ static void expand_filename_template(AVBPrint *bp, const char *template,
|
||||
}
|
||||
}
|
||||
|
||||
static int init_report(const char *env)
|
||||
int init_report(const char *env)
|
||||
{
|
||||
char *filename_template = NULL;
|
||||
char *key, *val;
|
||||
int ret, count = 0;
|
||||
int prog_loglevel, envlevel = 0;
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
AVBPrint filename;
|
||||
@@ -1019,6 +1054,7 @@ static int init_report(const char *env)
|
||||
av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n");
|
||||
exit_program(1);
|
||||
}
|
||||
envlevel = 1;
|
||||
} else {
|
||||
av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key);
|
||||
}
|
||||
@@ -1035,6 +1071,10 @@ static int init_report(const char *env)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
prog_loglevel = av_log_get_level();
|
||||
if (!envlevel)
|
||||
report_file_level = FFMAX(report_file_level, prog_loglevel);
|
||||
|
||||
report_file = fopen(filename.str, "w");
|
||||
if (!report_file) {
|
||||
int ret = AVERROR(errno);
|
||||
@@ -1042,19 +1082,20 @@ static int init_report(const char *env)
|
||||
filename.str, strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
av_log_set_callback(mobileffmpeg_log_callback_function);
|
||||
av_log_set_callback(log_callback_report);
|
||||
av_log(NULL, AV_LOG_INFO,
|
||||
"%s started on %04d-%02d-%02d at %02d:%02d:%02d\n"
|
||||
"Report written to \"%s\"\n",
|
||||
"Report written to \"%s\"\n"
|
||||
"Log level: %d\n",
|
||||
program_name,
|
||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
filename.str);
|
||||
filename.str, report_file_level);
|
||||
av_bprint_finalize(&filename, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int opt_report(const char *opt)
|
||||
int opt_report(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
return init_report(NULL);
|
||||
}
|
||||
@@ -1096,7 +1137,7 @@ void print_error(const char *filename, int err)
|
||||
av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr);
|
||||
}
|
||||
|
||||
static int warned_cfg = 0;
|
||||
__thread int warned_cfg = 0;
|
||||
|
||||
#define INDENT 1
|
||||
#define SHOW_VERSION 2
|
||||
@@ -1196,7 +1237,6 @@ void show_banner(int argc, char **argv, const OptionDef *options)
|
||||
|
||||
int show_version(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
av_log_set_callback(mobileffmpeg_log_callback_function);
|
||||
print_program_info (SHOW_COPYRIGHT, AV_LOG_INFO);
|
||||
print_all_libs_info(SHOW_VERSION, AV_LOG_INFO);
|
||||
|
||||
@@ -1205,7 +1245,6 @@ int show_version(void *optctx, const char *opt, const char *arg)
|
||||
|
||||
int show_buildconf(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
av_log_set_callback(mobileffmpeg_log_callback_function);
|
||||
print_buildconf (INDENT|0, AV_LOG_INFO);
|
||||
|
||||
return 0;
|
||||
@@ -1214,12 +1253,12 @@ int show_buildconf(void *optctx, const char *opt, const char *arg)
|
||||
int show_license(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
#if CONFIG_NONFREE
|
||||
av_log(NULL, AV_LOG_INFO,
|
||||
av_log(NULL, AV_LOG_STDERR,
|
||||
"This version of %s has nonfree parts compiled in.\n"
|
||||
"Therefore it is not legally redistributable.\n",
|
||||
program_name );
|
||||
#elif CONFIG_GPLV3
|
||||
av_log(NULL, AV_LOG_INFO,
|
||||
av_log(NULL, AV_LOG_STDERR,
|
||||
"%s is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License as published by\n"
|
||||
"the Free Software Foundation; either version 3 of the License, or\n"
|
||||
@@ -1234,7 +1273,7 @@ int show_license(void *optctx, const char *opt, const char *arg)
|
||||
"along with %s. If not, see <http://www.gnu.org/licenses/>.\n",
|
||||
program_name, program_name, program_name );
|
||||
#elif CONFIG_GPL
|
||||
av_log(NULL, AV_LOG_INFO,
|
||||
av_log(NULL, AV_LOG_STDERR,
|
||||
"%s is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License as published by\n"
|
||||
"the Free Software Foundation; either version 2 of the License, or\n"
|
||||
@@ -1250,7 +1289,7 @@ int show_license(void *optctx, const char *opt, const char *arg)
|
||||
"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n",
|
||||
program_name, program_name, program_name );
|
||||
#elif CONFIG_LGPLV3
|
||||
av_log(NULL, AV_LOG_INFO,
|
||||
av_log(NULL, AV_LOG_STDERR,
|
||||
"%s is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU Lesser General Public License as published by\n"
|
||||
"the Free Software Foundation; either version 3 of the License, or\n"
|
||||
@@ -1265,7 +1304,7 @@ int show_license(void *optctx, const char *opt, const char *arg)
|
||||
"along with %s. If not, see <http://www.gnu.org/licenses/>.\n",
|
||||
program_name, program_name, program_name );
|
||||
#else
|
||||
av_log(NULL, AV_LOG_INFO,
|
||||
av_log(NULL, AV_LOG_STDERR,
|
||||
"%s is free software; you can redistribute it and/or\n"
|
||||
"modify it under the terms of the GNU Lesser General Public\n"
|
||||
"License as published by the Free Software Foundation; either\n"
|
||||
@@ -1301,7 +1340,7 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
|
||||
const char *last_name;
|
||||
int is_dev;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "%s\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "%s\n"
|
||||
" D. = Demuxing supported\n"
|
||||
" .E = Muxing supported\n"
|
||||
" --\n", device_only ? "Devices:" : "File formats:");
|
||||
@@ -1346,7 +1385,7 @@ static int show_formats_devices(void *optctx, const char *opt, const char *arg,
|
||||
break;
|
||||
last_name = name;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " %s%s %-15s %s\n",
|
||||
av_log(NULL, AV_LOG_STDERR, " %s%s %-15s %s\n",
|
||||
decode ? "D" : " ",
|
||||
encode ? "E" : " ",
|
||||
name,
|
||||
@@ -1379,97 +1418,97 @@ int show_devices(void *optctx, const char *opt, const char *arg)
|
||||
if (codec->field) { \
|
||||
const type *p = codec->field; \
|
||||
\
|
||||
av_log(NULL, AV_LOG_INFO, " Supported " list_name ":"); \
|
||||
av_log(NULL, AV_LOG_STDERR, " Supported " list_name ":"); \
|
||||
while (*p != term) { \
|
||||
get_name(*p); \
|
||||
av_log(NULL, AV_LOG_INFO, " %s", name); \
|
||||
av_log(NULL, AV_LOG_STDERR, " %s", name); \
|
||||
p++; \
|
||||
} \
|
||||
av_log(NULL, AV_LOG_INFO, "\n"); \
|
||||
av_log(NULL, AV_LOG_STDERR, "\n"); \
|
||||
} \
|
||||
|
||||
static void print_codec(const AVCodec *c)
|
||||
{
|
||||
int encoder = av_codec_is_encoder(c);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name,
|
||||
av_log(NULL, AV_LOG_STDERR, "%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name,
|
||||
c->long_name ? c->long_name : "");
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " General capabilities: ");
|
||||
av_log(NULL, AV_LOG_STDERR, " General capabilities: ");
|
||||
if (c->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)
|
||||
av_log(NULL, AV_LOG_INFO, "horizband ");
|
||||
av_log(NULL, AV_LOG_STDERR, "horizband ");
|
||||
if (c->capabilities & AV_CODEC_CAP_DR1)
|
||||
av_log(NULL, AV_LOG_INFO, "dr1 ");
|
||||
av_log(NULL, AV_LOG_STDERR, "dr1 ");
|
||||
if (c->capabilities & AV_CODEC_CAP_TRUNCATED)
|
||||
av_log(NULL, AV_LOG_INFO, "trunc ");
|
||||
av_log(NULL, AV_LOG_STDERR, "trunc ");
|
||||
if (c->capabilities & AV_CODEC_CAP_DELAY)
|
||||
av_log(NULL, AV_LOG_INFO, "delay ");
|
||||
av_log(NULL, AV_LOG_STDERR, "delay ");
|
||||
if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME)
|
||||
av_log(NULL, AV_LOG_INFO, "small ");
|
||||
av_log(NULL, AV_LOG_STDERR, "small ");
|
||||
if (c->capabilities & AV_CODEC_CAP_SUBFRAMES)
|
||||
av_log(NULL, AV_LOG_INFO, "subframes ");
|
||||
av_log(NULL, AV_LOG_STDERR, "subframes ");
|
||||
if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL)
|
||||
av_log(NULL, AV_LOG_INFO, "exp ");
|
||||
av_log(NULL, AV_LOG_STDERR, "exp ");
|
||||
if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF)
|
||||
av_log(NULL, AV_LOG_INFO, "chconf ");
|
||||
av_log(NULL, AV_LOG_STDERR, "chconf ");
|
||||
if (c->capabilities & AV_CODEC_CAP_PARAM_CHANGE)
|
||||
av_log(NULL, AV_LOG_INFO, "paramchange ");
|
||||
av_log(NULL, AV_LOG_STDERR, "paramchange ");
|
||||
if (c->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
|
||||
av_log(NULL, AV_LOG_INFO, "variable ");
|
||||
av_log(NULL, AV_LOG_STDERR, "variable ");
|
||||
if (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS |
|
||||
AV_CODEC_CAP_SLICE_THREADS |
|
||||
AV_CODEC_CAP_AUTO_THREADS))
|
||||
av_log(NULL, AV_LOG_INFO, "threads ");
|
||||
av_log(NULL, AV_LOG_STDERR, "threads ");
|
||||
if (c->capabilities & AV_CODEC_CAP_AVOID_PROBING)
|
||||
av_log(NULL, AV_LOG_INFO, "avoidprobe ");
|
||||
av_log(NULL, AV_LOG_STDERR, "avoidprobe ");
|
||||
if (c->capabilities & AV_CODEC_CAP_INTRA_ONLY)
|
||||
av_log(NULL, AV_LOG_INFO, "intraonly ");
|
||||
av_log(NULL, AV_LOG_STDERR, "intraonly ");
|
||||
if (c->capabilities & AV_CODEC_CAP_LOSSLESS)
|
||||
av_log(NULL, AV_LOG_INFO, "lossless ");
|
||||
av_log(NULL, AV_LOG_STDERR, "lossless ");
|
||||
if (c->capabilities & AV_CODEC_CAP_HARDWARE)
|
||||
av_log(NULL, AV_LOG_INFO, "hardware ");
|
||||
av_log(NULL, AV_LOG_STDERR, "hardware ");
|
||||
if (c->capabilities & AV_CODEC_CAP_HYBRID)
|
||||
av_log(NULL, AV_LOG_INFO, "hybrid ");
|
||||
av_log(NULL, AV_LOG_STDERR, "hybrid ");
|
||||
if (!c->capabilities)
|
||||
av_log(NULL, AV_LOG_INFO, "none");
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "none");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
|
||||
if (c->type == AVMEDIA_TYPE_VIDEO ||
|
||||
c->type == AVMEDIA_TYPE_AUDIO) {
|
||||
av_log(NULL, AV_LOG_INFO, " Threading capabilities: ");
|
||||
av_log(NULL, AV_LOG_STDERR, " Threading capabilities: ");
|
||||
switch (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS |
|
||||
AV_CODEC_CAP_SLICE_THREADS |
|
||||
AV_CODEC_CAP_AUTO_THREADS)) {
|
||||
case AV_CODEC_CAP_FRAME_THREADS |
|
||||
AV_CODEC_CAP_SLICE_THREADS: av_log(NULL, AV_LOG_INFO, "frame and slice"); break;
|
||||
case AV_CODEC_CAP_FRAME_THREADS: av_log(NULL, AV_LOG_INFO, "frame"); break;
|
||||
case AV_CODEC_CAP_SLICE_THREADS: av_log(NULL, AV_LOG_INFO, "slice"); break;
|
||||
case AV_CODEC_CAP_AUTO_THREADS : av_log(NULL, AV_LOG_INFO, "auto"); break;
|
||||
default: av_log(NULL, AV_LOG_INFO, "none"); break;
|
||||
AV_CODEC_CAP_SLICE_THREADS: av_log(NULL, AV_LOG_STDERR, "frame and slice"); break;
|
||||
case AV_CODEC_CAP_FRAME_THREADS: av_log(NULL, AV_LOG_STDERR, "frame"); break;
|
||||
case AV_CODEC_CAP_SLICE_THREADS: av_log(NULL, AV_LOG_STDERR, "slice"); break;
|
||||
case AV_CODEC_CAP_AUTO_THREADS : av_log(NULL, AV_LOG_STDERR, "auto"); break;
|
||||
default: av_log(NULL, AV_LOG_STDERR, "none"); break;
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
|
||||
if (avcodec_get_hw_config(c, 0)) {
|
||||
av_log(NULL, AV_LOG_INFO, " Supported hardware devices: ");
|
||||
av_log(NULL, AV_LOG_STDERR, " Supported hardware devices: ");
|
||||
for (int i = 0;; i++) {
|
||||
const AVCodecHWConfig *config = avcodec_get_hw_config(c, i);
|
||||
if (!config)
|
||||
break;
|
||||
av_log(NULL, AV_LOG_INFO, "%s ", av_hwdevice_get_type_name(config->device_type));
|
||||
av_log(NULL, AV_LOG_STDERR, "%s ", av_hwdevice_get_type_name(config->device_type));
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
|
||||
if (c->supported_framerates) {
|
||||
const AVRational *fps = c->supported_framerates;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " Supported framerates:");
|
||||
av_log(NULL, AV_LOG_STDERR, " Supported framerates:");
|
||||
while (fps->num) {
|
||||
av_log(NULL, AV_LOG_INFO, " %d/%d", fps->num, fps->den);
|
||||
av_log(NULL, AV_LOG_STDERR, " %d/%d", fps->num, fps->den);
|
||||
fps++;
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats",
|
||||
AV_PIX_FMT_NONE, GET_PIX_FMT_NAME);
|
||||
@@ -1544,12 +1583,12 @@ static void print_codecs_for_id(enum AVCodecID id, int encoder)
|
||||
{
|
||||
const AVCodec *codec = NULL;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " (%s: ", encoder ? "encoders" : "decoders");
|
||||
av_log(NULL, AV_LOG_STDERR, " (%s: ", encoder ? "encoders" : "decoders");
|
||||
|
||||
while ((codec = next_codec_for_id(id, codec, encoder)))
|
||||
av_log(NULL, AV_LOG_INFO, "%s ", codec->name);
|
||||
av_log(NULL, AV_LOG_STDERR, "%s ", codec->name);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, ")");
|
||||
av_log(NULL, AV_LOG_STDERR, ")");
|
||||
}
|
||||
|
||||
int show_codecs(void *optctx, const char *opt, const char *arg)
|
||||
@@ -1557,7 +1596,7 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
|
||||
const AVCodecDescriptor **codecs;
|
||||
unsigned i, nb_codecs = get_codecs_sorted(&codecs);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Codecs:\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "Codecs:\n"
|
||||
" D..... = Decoding supported\n"
|
||||
" .E.... = Encoding supported\n"
|
||||
" ..V... = Video codec\n"
|
||||
@@ -1574,16 +1613,16 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
|
||||
if (strstr(desc->name, "_deprecated"))
|
||||
continue;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " ");
|
||||
av_log(NULL, AV_LOG_INFO, avcodec_find_decoder(desc->id) ? "D" : ".");
|
||||
av_log(NULL, AV_LOG_INFO, avcodec_find_encoder(desc->id) ? "E" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, " ");
|
||||
av_log(NULL, AV_LOG_STDERR, avcodec_find_decoder(desc->id) ? "D" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, avcodec_find_encoder(desc->id) ? "E" : ".");
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "%c", get_media_type_char(desc->type));
|
||||
av_log(NULL, AV_LOG_INFO, (desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : ".");
|
||||
av_log(NULL, AV_LOG_INFO, (desc->props & AV_CODEC_PROP_LOSSY) ? "L" : ".");
|
||||
av_log(NULL, AV_LOG_INFO, (desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, "%c", get_media_type_char(desc->type));
|
||||
av_log(NULL, AV_LOG_STDERR, (desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, (desc->props & AV_CODEC_PROP_LOSSY) ? "L" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, (desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : ".");
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " %-20s %s", desc->name, desc->long_name ? desc->long_name : "");
|
||||
av_log(NULL, AV_LOG_STDERR, " %-20s %s", desc->name, desc->long_name ? desc->long_name : "");
|
||||
|
||||
/* print decoders/encoders when there's more than one or their
|
||||
* names are different from codec name */
|
||||
@@ -1601,7 +1640,7 @@ int show_codecs(void *optctx, const char *opt, const char *arg)
|
||||
}
|
||||
}
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
av_free(codecs);
|
||||
return 0;
|
||||
@@ -1612,7 +1651,7 @@ static void print_codecs(int encoder)
|
||||
const AVCodecDescriptor **codecs;
|
||||
unsigned i, nb_codecs = get_codecs_sorted(&codecs);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "%s:\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "%s:\n"
|
||||
" V..... = Video\n"
|
||||
" A..... = Audio\n"
|
||||
" S..... = Subtitle\n"
|
||||
@@ -1628,18 +1667,18 @@ static void print_codecs(int encoder)
|
||||
const AVCodec *codec = NULL;
|
||||
|
||||
while ((codec = next_codec_for_id(desc->id, codec, encoder))) {
|
||||
av_log(NULL, AV_LOG_INFO, " %c", get_media_type_char(desc->type));
|
||||
av_log(NULL, AV_LOG_INFO, (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : ".");
|
||||
av_log(NULL, AV_LOG_INFO, (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : ".");
|
||||
av_log(NULL, AV_LOG_INFO, (codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : ".");
|
||||
av_log(NULL, AV_LOG_INFO, (codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : ".");
|
||||
av_log(NULL, AV_LOG_INFO, (codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, " %c", get_media_type_char(desc->type));
|
||||
av_log(NULL, AV_LOG_STDERR, (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, (codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, (codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : ".");
|
||||
av_log(NULL, AV_LOG_STDERR, (codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : ".");
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " %-20s %s", codec->name, codec->long_name ? codec->long_name : "");
|
||||
av_log(NULL, AV_LOG_STDERR, " %-20s %s", codec->name, codec->long_name ? codec->long_name : "");
|
||||
if (strcmp(codec->name, desc->name))
|
||||
av_log(NULL, AV_LOG_INFO, " (codec %s)", desc->name);
|
||||
av_log(NULL, AV_LOG_STDERR, " (codec %s)", desc->name);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
}
|
||||
av_free(codecs);
|
||||
@@ -1662,10 +1701,10 @@ int show_bsfs(void *optctx, const char *opt, const char *arg)
|
||||
const AVBitStreamFilter *bsf = NULL;
|
||||
void *opaque = NULL;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Bitstream filters:\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "Bitstream filters:\n");
|
||||
while ((bsf = av_bsf_iterate(&opaque)))
|
||||
av_log(NULL, AV_LOG_INFO, "%s\n", bsf->name);
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "%s\n", bsf->name);
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1674,13 +1713,13 @@ int show_protocols(void *optctx, const char *opt, const char *arg)
|
||||
void *opaque = NULL;
|
||||
const char *name;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Supported file protocols:\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "Supported file protocols:\n"
|
||||
"Input:\n");
|
||||
while ((name = avio_enum_protocols(&opaque, 0)))
|
||||
av_log(NULL, AV_LOG_INFO, " %s\n", name);
|
||||
av_log(NULL, AV_LOG_INFO, "Output:\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " %s\n", name);
|
||||
av_log(NULL, AV_LOG_STDERR, "Output:\n");
|
||||
while ((name = avio_enum_protocols(&opaque, 1)))
|
||||
av_log(NULL, AV_LOG_INFO, " %s\n", name);
|
||||
av_log(NULL, AV_LOG_STDERR, " %s\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1693,7 +1732,7 @@ int show_filters(void *optctx, const char *opt, const char *arg)
|
||||
int i, j;
|
||||
const AVFilterPad *pad;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Filters:\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "Filters:\n"
|
||||
" T.. = Timeline support\n"
|
||||
" .S. = Slice threading\n"
|
||||
" ..C = Command support\n"
|
||||
@@ -1719,14 +1758,14 @@ int show_filters(void *optctx, const char *opt, const char *arg)
|
||||
( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|';
|
||||
}
|
||||
*descr_cur = 0;
|
||||
av_log(NULL, AV_LOG_INFO, " %c%c%c %-17s %-10s %s\n",
|
||||
av_log(NULL, AV_LOG_STDERR, " %c%c%c %-17s %-10s %s\n",
|
||||
filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE ? 'T' : '.',
|
||||
filter->flags & AVFILTER_FLAG_SLICE_THREADS ? 'S' : '.',
|
||||
filter->process_command ? 'C' : '.',
|
||||
filter->name, descr, filter->description);
|
||||
}
|
||||
#else
|
||||
av_log(NULL, AV_LOG_INFO, "No filters available: libavfilter disabled\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "No filters available: libavfilter disabled\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -1737,10 +1776,10 @@ int show_colors(void *optctx, const char *opt, const char *arg)
|
||||
const uint8_t *rgb;
|
||||
int i;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "%-32s #RRGGBB\n", "name");
|
||||
av_log(NULL, AV_LOG_STDERR, "%-32s #RRGGBB\n", "name");
|
||||
|
||||
for (i = 0; (name = av_get_known_color_name(i, &rgb)); i++)
|
||||
av_log(NULL, AV_LOG_INFO, "%-32s #%02x%02x%02x\n", name, rgb[0], rgb[1], rgb[2]);
|
||||
av_log(NULL, AV_LOG_STDERR, "%-32s #%02x%02x%02x\n", name, rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1749,7 +1788,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
const AVPixFmtDescriptor *pix_desc = NULL;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Pixel formats:\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "Pixel formats:\n"
|
||||
"I.... = Supported Input format for conversion\n"
|
||||
".O... = Supported Output format for conversion\n"
|
||||
"..H.. = Hardware accelerated format\n"
|
||||
@@ -1765,7 +1804,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg)
|
||||
|
||||
while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) {
|
||||
enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc);
|
||||
av_log(NULL, AV_LOG_INFO, "%c%c%c%c%c %-16s %d %2d\n",
|
||||
av_log(NULL, AV_LOG_STDERR, "%c%c%c%c%c %-16s %d %2d\n",
|
||||
sws_isSupportedInput (pix_fmt) ? 'I' : '.',
|
||||
sws_isSupportedOutput(pix_fmt) ? 'O' : '.',
|
||||
pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL ? 'H' : '.',
|
||||
@@ -1784,24 +1823,24 @@ int show_layouts(void *optctx, const char *opt, const char *arg)
|
||||
uint64_t layout, j;
|
||||
const char *name, *descr;
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Individual channels:\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "Individual channels:\n"
|
||||
"NAME DESCRIPTION\n");
|
||||
for (i = 0; i < 63; i++) {
|
||||
name = av_get_channel_name((uint64_t)1 << i);
|
||||
if (!name)
|
||||
continue;
|
||||
descr = av_get_channel_description((uint64_t)1 << i);
|
||||
av_log(NULL, AV_LOG_INFO, "%-14s %s\n", name, descr);
|
||||
av_log(NULL, AV_LOG_STDERR, "%-14s %s\n", name, descr);
|
||||
}
|
||||
av_log(NULL, AV_LOG_INFO, "\nStandard channel layouts:\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "\nStandard channel layouts:\n"
|
||||
"NAME DECOMPOSITION\n");
|
||||
for (i = 0; !av_get_standard_channel_layout(i, &layout, &name); i++) {
|
||||
if (name) {
|
||||
av_log(NULL, AV_LOG_INFO, "%-14s ", name);
|
||||
av_log(NULL, AV_LOG_STDERR, "%-14s ", name);
|
||||
for (j = 1; j; j <<= 1)
|
||||
if ((layout & j))
|
||||
av_log(NULL, AV_LOG_INFO, "%s%s", (layout & (j - 1)) ? "+" : "", av_get_channel_name(j));
|
||||
av_log(NULL, AV_LOG_INFO, "\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "%s%s", (layout & (j - 1)) ? "+" : "", av_get_channel_name(j));
|
||||
av_log(NULL, AV_LOG_STDERR, "\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -1812,7 +1851,7 @@ int show_sample_fmts(void *optctx, const char *opt, const char *arg)
|
||||
int i;
|
||||
char fmt_str[128];
|
||||
for (i = -1; i < AV_SAMPLE_FMT_NB; i++)
|
||||
av_log(NULL, AV_LOG_INFO, "%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
|
||||
av_log(NULL, AV_LOG_STDERR, "%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1860,10 +1899,10 @@ static void show_help_demuxer(const char *name)
|
||||
return;
|
||||
}
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Demuxer %s [%s]:\n", fmt->name, fmt->long_name);
|
||||
av_log(NULL, AV_LOG_STDERR, "Demuxer %s [%s]:\n", fmt->name, fmt->long_name);
|
||||
|
||||
if (fmt->extensions)
|
||||
av_log(NULL, AV_LOG_INFO, " Common extensions: %s.\n", fmt->extensions);
|
||||
av_log(NULL, AV_LOG_STDERR, " Common extensions: %s.\n", fmt->extensions);
|
||||
|
||||
if (fmt->priv_class)
|
||||
show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM);
|
||||
@@ -1879,23 +1918,23 @@ static void show_help_muxer(const char *name)
|
||||
return;
|
||||
}
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Muxer %s [%s]:\n", fmt->name, fmt->long_name);
|
||||
av_log(NULL, AV_LOG_STDERR, "Muxer %s [%s]:\n", fmt->name, fmt->long_name);
|
||||
|
||||
if (fmt->extensions)
|
||||
av_log(NULL, AV_LOG_INFO, " Common extensions: %s.\n", fmt->extensions);
|
||||
av_log(NULL, AV_LOG_STDERR, " Common extensions: %s.\n", fmt->extensions);
|
||||
if (fmt->mime_type)
|
||||
av_log(NULL, AV_LOG_INFO, " Mime type: %s.\n", fmt->mime_type);
|
||||
av_log(NULL, AV_LOG_STDERR, " Mime type: %s.\n", fmt->mime_type);
|
||||
if (fmt->video_codec != AV_CODEC_ID_NONE &&
|
||||
(desc = avcodec_descriptor_get(fmt->video_codec))) {
|
||||
av_log(NULL, AV_LOG_INFO, " Default video codec: %s.\n", desc->name);
|
||||
av_log(NULL, AV_LOG_STDERR, " Default video codec: %s.\n", desc->name);
|
||||
}
|
||||
if (fmt->audio_codec != AV_CODEC_ID_NONE &&
|
||||
(desc = avcodec_descriptor_get(fmt->audio_codec))) {
|
||||
av_log(NULL, AV_LOG_INFO, " Default audio codec: %s.\n", desc->name);
|
||||
av_log(NULL, AV_LOG_STDERR, " Default audio codec: %s.\n", desc->name);
|
||||
}
|
||||
if (fmt->subtitle_codec != AV_CODEC_ID_NONE &&
|
||||
(desc = avcodec_descriptor_get(fmt->subtitle_codec))) {
|
||||
av_log(NULL, AV_LOG_INFO, " Default subtitle codec: %s.\n", desc->name);
|
||||
av_log(NULL, AV_LOG_STDERR, " Default subtitle codec: %s.\n", desc->name);
|
||||
}
|
||||
|
||||
if (fmt->priv_class)
|
||||
@@ -1917,40 +1956,40 @@ static void show_help_filter(const char *name)
|
||||
return;
|
||||
}
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Filter %s\n", f->name);
|
||||
av_log(NULL, AV_LOG_STDERR, "Filter %s\n", f->name);
|
||||
if (f->description)
|
||||
av_log(NULL, AV_LOG_INFO, " %s\n", f->description);
|
||||
av_log(NULL, AV_LOG_STDERR, " %s\n", f->description);
|
||||
|
||||
if (f->flags & AVFILTER_FLAG_SLICE_THREADS)
|
||||
av_log(NULL, AV_LOG_INFO, " slice threading supported\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " slice threading supported\n");
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " Inputs:\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " Inputs:\n");
|
||||
count = avfilter_pad_count(f->inputs);
|
||||
for (i = 0; i < count; i++) {
|
||||
av_log(NULL, AV_LOG_INFO, " #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i),
|
||||
av_log(NULL, AV_LOG_STDERR, " #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i),
|
||||
media_type_string(avfilter_pad_get_type(f->inputs, i)));
|
||||
}
|
||||
if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)
|
||||
av_log(NULL, AV_LOG_INFO, " dynamic (depending on the options)\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " dynamic (depending on the options)\n");
|
||||
else if (!count)
|
||||
av_log(NULL, AV_LOG_INFO, " none (source filter)\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " none (source filter)\n");
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, " Outputs:\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " Outputs:\n");
|
||||
count = avfilter_pad_count(f->outputs);
|
||||
for (i = 0; i < count; i++) {
|
||||
av_log(NULL, AV_LOG_INFO, " #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i),
|
||||
av_log(NULL, AV_LOG_STDERR, " #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i),
|
||||
media_type_string(avfilter_pad_get_type(f->outputs, i)));
|
||||
}
|
||||
if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS)
|
||||
av_log(NULL, AV_LOG_INFO, " dynamic (depending on the options)\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " dynamic (depending on the options)\n");
|
||||
else if (!count)
|
||||
av_log(NULL, AV_LOG_INFO, " none (sink filter)\n");
|
||||
av_log(NULL, AV_LOG_STDERR, " none (sink filter)\n");
|
||||
|
||||
if (f->priv_class)
|
||||
show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM |
|
||||
AV_OPT_FLAG_AUDIO_PARAM);
|
||||
if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)
|
||||
av_log(NULL, AV_LOG_INFO, "This filter has support for timeline through the 'enable' option.\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "This filter has support for timeline through the 'enable' option.\n");
|
||||
#else
|
||||
av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; "
|
||||
"can not to satisfy request\n");
|
||||
@@ -1970,7 +2009,7 @@ static void show_help_bsf(const char *name)
|
||||
return;
|
||||
}
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Bit stream filter %s\n", bsf->name);
|
||||
av_log(NULL, AV_LOG_STDERR, "Bit stream filter %s\n", bsf->name);
|
||||
PRINT_CODEC_SUPPORTED(bsf, codec_ids, enum AVCodecID, "codecs",
|
||||
AV_CODEC_ID_NONE, GET_CODEC_NAME);
|
||||
if (bsf->priv_class)
|
||||
@@ -1980,7 +2019,6 @@ static void show_help_bsf(const char *name)
|
||||
int show_help(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
char *topic, *par;
|
||||
av_log_set_callback(mobileffmpeg_log_callback_function);
|
||||
|
||||
topic = av_strdup(arg ? arg : "");
|
||||
if (!topic)
|
||||
@@ -1990,7 +2028,11 @@ int show_help(void *optctx, const char *opt, const char *arg)
|
||||
*par++ = 0;
|
||||
|
||||
if (!*topic) {
|
||||
show_help_default(topic, par);
|
||||
if (program_name && !strcmp(program_name, "ffmpeg")) {
|
||||
show_help_default_ffmpeg(topic, par);
|
||||
} else {
|
||||
show_help_default_ffprobe(topic, par);
|
||||
}
|
||||
} else if (!strcmp(topic, "decoder")) {
|
||||
show_help_codec(par, 0);
|
||||
} else if (!strcmp(topic, "encoder")) {
|
||||
@@ -2006,7 +2048,11 @@ int show_help(void *optctx, const char *opt, const char *arg)
|
||||
} else if (!strcmp(topic, "bsf")) {
|
||||
show_help_bsf(par);
|
||||
} else {
|
||||
show_help_default(topic, par);
|
||||
if (program_name && !strcmp(program_name, "ffmpeg")) {
|
||||
show_help_default_ffmpeg(topic, par);
|
||||
} else {
|
||||
show_help_default_ffprobe(topic, par);
|
||||
}
|
||||
}
|
||||
|
||||
av_freep(&topic);
|
||||
@@ -2038,7 +2084,7 @@ FILE *get_preset_file(char *filename, size_t filename_size,
|
||||
av_strlcpy(filename, preset_name, filename_size);
|
||||
f = fopen(filename, "r");
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
#if HAVE_GETMODULEHANDLE
|
||||
char datadir[MAX_PATH], *ls;
|
||||
base[2] = NULL;
|
||||
|
||||
@@ -2206,20 +2252,20 @@ static int print_device_sources(AVInputFormat *fmt, AVDictionary *opts)
|
||||
if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category))
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Auto-detected sources for %s:\n", fmt->name);
|
||||
av_log(NULL, AV_LOG_STDERR, "Auto-detected sources for %s:\n", fmt->name);
|
||||
if (!fmt->get_device_list) {
|
||||
ret = AVERROR(ENOSYS);
|
||||
av_log(NULL, AV_LOG_INFO, "Cannot list sources. Not implemented.\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "Cannot list sources. Not implemented.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) {
|
||||
av_log(NULL, AV_LOG_INFO, "Cannot list sources.\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "Cannot list sources.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < device_list->nb_devices; i++) {
|
||||
av_log(NULL, AV_LOG_INFO, "%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
|
||||
av_log(NULL, AV_LOG_STDERR, "%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
|
||||
device_list->devices[i]->device_name, device_list->devices[i]->device_description);
|
||||
}
|
||||
|
||||
@@ -2236,20 +2282,20 @@ static int print_device_sinks(AVOutputFormat *fmt, AVDictionary *opts)
|
||||
if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category))
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
av_log(NULL, AV_LOG_INFO, "Auto-detected sinks for %s:\n", fmt->name);
|
||||
av_log(NULL, AV_LOG_STDERR, "Auto-detected sinks for %s:\n", fmt->name);
|
||||
if (!fmt->get_device_list) {
|
||||
ret = AVERROR(ENOSYS);
|
||||
av_log(NULL, AV_LOG_INFO, "Cannot list sinks. Not implemented.\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "Cannot list sinks. Not implemented.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) {
|
||||
av_log(NULL, AV_LOG_INFO, "Cannot list sinks.\n");
|
||||
av_log(NULL, AV_LOG_STDERR, "Cannot list sinks.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < device_list->nb_devices; i++) {
|
||||
av_log(NULL, AV_LOG_INFO, "%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
|
||||
av_log(NULL, AV_LOG_STDERR, "%s %s [%s]\n", device_list->default_device == i ? "*" : " ",
|
||||
device_list->devices[i]->device_name, device_list->devices[i]->device_description);
|
||||
}
|
||||
|
||||
@@ -2275,7 +2321,7 @@ static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionar
|
||||
}
|
||||
}
|
||||
} else
|
||||
av_log(NULL, AV_LOG_INFO, "\nDevice name is not provided.\n"
|
||||
av_log(NULL, AV_LOG_STDERR, "\nDevice name is not provided.\n"
|
||||
"You can pass devicename[,opt1=val1[,opt2=val2...]] as an argument.\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* CHANGES 01.2020
|
||||
* - ffprobe support changes
|
||||
* - AV_LOG_STDERR introduced
|
||||
*
|
||||
* CHANGES 12.2019
|
||||
* - Concurrent execution support
|
||||
*
|
||||
* CHANGES 03.2019
|
||||
* --------------------------------------------------------
|
||||
* - config.h include removed
|
||||
@@ -48,22 +55,28 @@
|
||||
#undef main /* We don't want SDL to override our main() */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Defines logs printed to stderr by ffmpeg. They are not filtered and always redirected.
|
||||
*/
|
||||
#define AV_LOG_STDERR -16
|
||||
|
||||
/**
|
||||
* program name, defined by the program for show_version().
|
||||
*/
|
||||
extern const char program_name[];
|
||||
extern __thread char *program_name;
|
||||
|
||||
/**
|
||||
* program birth year, defined by the program for show_banner()
|
||||
*/
|
||||
extern const int program_birth_year;
|
||||
extern __thread int program_birth_year;
|
||||
|
||||
extern AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB];
|
||||
extern AVFormatContext *avformat_opts;
|
||||
extern AVDictionary *sws_dict;
|
||||
extern AVDictionary *swr_opts;
|
||||
extern AVDictionary *format_opts, *codec_opts, *resample_opts;
|
||||
extern int hide_banner;
|
||||
extern __thread AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB];
|
||||
extern __thread AVFormatContext *avformat_opts;
|
||||
extern __thread AVDictionary *sws_dict;
|
||||
extern __thread AVDictionary *swr_opts;
|
||||
extern __thread AVDictionary *format_opts, *codec_opts, *resample_opts;
|
||||
extern __thread int hide_banner;
|
||||
extern __thread int find_stream_info;
|
||||
|
||||
/**
|
||||
* Register a program-specific cleanup routine.
|
||||
@@ -113,7 +126,7 @@ int opt_default(void *optctx, const char *opt, const char *arg);
|
||||
*/
|
||||
int opt_loglevel(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
int opt_report(const char *opt);
|
||||
int opt_report(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
int opt_max_alloc(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
@@ -215,47 +228,6 @@ typedef struct OptionDef {
|
||||
void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
int rej_flags, int alt_flags);
|
||||
|
||||
#if CONFIG_AVDEVICE
|
||||
#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \
|
||||
{ "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \
|
||||
"list sources of the input device", "device" }, \
|
||||
{ "sinks" , OPT_EXIT | HAS_ARG, { .func_arg = show_sinks }, \
|
||||
"list sinks of the output device", "device" }, \
|
||||
|
||||
#else
|
||||
#define CMDUTILS_COMMON_OPTIONS_AVDEVICE
|
||||
#endif
|
||||
|
||||
#define CMDUTILS_COMMON_OPTIONS \
|
||||
{ "L", OPT_EXIT, { .func_arg = show_license }, "show license" }, \
|
||||
{ "h", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "?", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "-help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \
|
||||
{ "version", OPT_EXIT, { .func_arg = show_version }, "show version" }, \
|
||||
{ "buildconf", OPT_EXIT, { .func_arg = show_buildconf }, "show build configuration" }, \
|
||||
{ "formats", OPT_EXIT, { .func_arg = show_formats }, "show available formats" }, \
|
||||
{ "muxers", OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \
|
||||
{ "demuxers", OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \
|
||||
{ "devices", OPT_EXIT, { .func_arg = show_devices }, "show available devices" }, \
|
||||
{ "codecs", OPT_EXIT, { .func_arg = show_codecs }, "show available codecs" }, \
|
||||
{ "decoders", OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" }, \
|
||||
{ "encoders", OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" }, \
|
||||
{ "bsfs", OPT_EXIT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \
|
||||
{ "protocols", OPT_EXIT, { .func_arg = show_protocols }, "show available protocols" }, \
|
||||
{ "filters", OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \
|
||||
{ "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \
|
||||
{ "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \
|
||||
{ "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \
|
||||
{ "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \
|
||||
{ "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
|
||||
{ "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \
|
||||
{ "report", 0, { (void*)opt_report }, "generate a report" }, \
|
||||
{ "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" }, \
|
||||
{ "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" }, \
|
||||
{ "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \
|
||||
CMDUTILS_COMMON_OPTIONS_AVDEVICE \
|
||||
|
||||
/**
|
||||
* Show help for all options with given flags in class and all its
|
||||
* children.
|
||||
@@ -263,10 +235,11 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags,
|
||||
void show_help_children(const AVClass *class, int flags);
|
||||
|
||||
/**
|
||||
* Per-fftool specific help handler. Implemented in each
|
||||
* Per-fftool specific help handlers. Implemented in each
|
||||
* fftool, called by show_help().
|
||||
*/
|
||||
void show_help_default(const char *opt, const char *arg);
|
||||
void show_help_default_ffmpeg(const char *opt, const char *arg);
|
||||
void show_help_default_ffprobe(const char *opt, const char *arg);
|
||||
|
||||
/**
|
||||
* Generic -h handler common to all fftools.
|
||||
@@ -361,7 +334,6 @@ typedef struct OptionParseContext {
|
||||
* Parse an options group and write results into optctx.
|
||||
*
|
||||
* @param optctx an app-specific options context. NULL for global options group
|
||||
* @param g option group
|
||||
*/
|
||||
int parse_optgroup(void *optctx, OptionGroup *g);
|
||||
|
||||
|
||||
@@ -24,6 +24,12 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* CHANGES 01.2020
|
||||
* - ffprobe support changes
|
||||
*
|
||||
* CHANGES 12.2019
|
||||
* - Concurrent execution support
|
||||
*
|
||||
* CHANGES 08.2018
|
||||
* --------------------------------------------------------
|
||||
* - fftools_ prefix added to file name and parent headers
|
||||
@@ -35,10 +41,10 @@
|
||||
*
|
||||
* CHANGES 07.2018
|
||||
* --------------------------------------------------------
|
||||
* - main() function renamed as execute()
|
||||
* - main() function renamed as ffmpeg_execute()
|
||||
* - exit_program() implemented with setjmp
|
||||
* - extern longjmp_value added to access exit code stored in exit_program()
|
||||
* - cleanup() method added
|
||||
* - ffmpeg_var_cleanup() method added
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -126,9 +132,6 @@
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
|
||||
const char program_name[] = "ffmpeg";
|
||||
const int program_birth_year = 2000;
|
||||
|
||||
static FILE *vstats_file;
|
||||
|
||||
const char *const forced_keyframes_const_names[] = {
|
||||
@@ -151,39 +154,85 @@ static BenchmarkTimeStamps get_benchmark_time_stamps(void);
|
||||
static int64_t getmaxrss(void);
|
||||
static int ifilter_has_all_input_formats(FilterGraph *fg);
|
||||
|
||||
static int run_as_daemon = 0;
|
||||
static int nb_frames_dup = 0;
|
||||
static unsigned dup_warning = 1000;
|
||||
static int nb_frames_drop = 0;
|
||||
static int64_t decode_error_stat[2];
|
||||
__thread int run_as_daemon = 0;
|
||||
__thread int nb_frames_dup = 0;
|
||||
__thread unsigned dup_warning = 1000;
|
||||
__thread int nb_frames_drop = 0;
|
||||
__thread int64_t decode_error_stat[2];
|
||||
|
||||
static int want_sdp = 1;
|
||||
__thread int want_sdp = 1;
|
||||
|
||||
static BenchmarkTimeStamps current_time;
|
||||
AVIOContext *progress_avio = NULL;
|
||||
__thread BenchmarkTimeStamps current_time;
|
||||
__thread AVIOContext *progress_avio = NULL;
|
||||
|
||||
static uint8_t *subtitle_out;
|
||||
__thread uint8_t *subtitle_out;
|
||||
|
||||
InputStream **input_streams = NULL;
|
||||
int nb_input_streams = 0;
|
||||
InputFile **input_files = NULL;
|
||||
int nb_input_files = 0;
|
||||
__thread InputStream **input_streams = NULL;
|
||||
__thread int nb_input_streams = 0;
|
||||
__thread InputFile **input_files = NULL;
|
||||
__thread int nb_input_files = 0;
|
||||
|
||||
OutputStream **output_streams = NULL;
|
||||
int nb_output_streams = 0;
|
||||
OutputFile **output_files = NULL;
|
||||
int nb_output_files = 0;
|
||||
__thread OutputStream **output_streams = NULL;
|
||||
__thread int nb_output_streams = 0;
|
||||
__thread OutputFile **output_files = NULL;
|
||||
__thread int nb_output_files = 0;
|
||||
|
||||
FilterGraph **filtergraphs;
|
||||
int nb_filtergraphs;
|
||||
__thread FilterGraph **filtergraphs;
|
||||
__thread int nb_filtergraphs;
|
||||
|
||||
static void (*report_callback)(int, float, float, int64_t, int, double, double) = NULL;
|
||||
void (*report_callback)(int, float, float, int64_t, int, double, double) = NULL;
|
||||
|
||||
extern __thread int file_overwrite;
|
||||
extern __thread int no_file_overwrite;
|
||||
extern __thread int ignore_unknown_streams;
|
||||
extern __thread int copy_unknown_streams;
|
||||
extern int opt_map(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_map_channel(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_recording_timestamp(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_data_frames(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_progress(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_target(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_vsync(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_abort_on(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_qscale(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_profile(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_filter_complex(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_filter_complex_script(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_attach(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_video_frames(void *optctx, const char *opt, const char *arg);
|
||||
extern __thread int intra_only;
|
||||
extern int opt_video_codec(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_sameq(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_timecode(void *optctx, const char *opt, const char *arg);
|
||||
extern __thread int do_psnr;
|
||||
extern int opt_vstats_file(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_vstats(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_video_frames(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_old2new(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_streamid(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_bitrate(void *optctx, const char *opt, const char *arg);
|
||||
extern int show_hwaccels(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_video_filters(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_audio_frames(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_audio_qscale(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_audio_codec(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_channel_layout(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_preset(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_audio_filters(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_subtitle_codec(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_video_channel(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_video_standard(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_sdp_file(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_data_codec(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_init_hw_device(void *optctx, const char *opt, const char *arg);
|
||||
extern int opt_filter_hw_device(void *optctx, const char *opt, const char *arg);
|
||||
extern __thread int input_sync;
|
||||
|
||||
#if HAVE_TERMIOS_H
|
||||
|
||||
/* init terminal so that we can grab keys */
|
||||
static struct termios oldtty;
|
||||
static int restore_tty;
|
||||
__thread struct termios oldtty;
|
||||
__thread int restore_tty;
|
||||
#endif
|
||||
|
||||
#if HAVE_THREADS
|
||||
@@ -353,12 +402,12 @@ void term_exit(void)
|
||||
term_exit_sigsafe();
|
||||
}
|
||||
|
||||
static volatile int received_sigterm = 0;
|
||||
static volatile int received_nb_signals = 0;
|
||||
static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0);
|
||||
static volatile int ffmpeg_exited = 0;
|
||||
static int main_return_code = 0;
|
||||
extern int longjmp_value;
|
||||
volatile int received_sigterm = 0;
|
||||
volatile int received_nb_signals = 0;
|
||||
__thread atomic_int transcode_init_done = ATOMIC_VAR_INIT(0);
|
||||
__thread volatile int ffmpeg_exited = 0;
|
||||
__thread int main_ffmpeg_return_code = 0;
|
||||
extern __thread int longjmp_value;
|
||||
|
||||
static void
|
||||
sigterm_handler(int sig)
|
||||
@@ -496,12 +545,14 @@ static int read_key(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int decode_interrupt_cb(void *ctx)
|
||||
int decode_interrupt_cb(void *ctx);
|
||||
|
||||
int decode_interrupt_cb(void *ctx)
|
||||
{
|
||||
return received_nb_signals > atomic_load(&transcode_init_done);
|
||||
}
|
||||
|
||||
const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
|
||||
__thread const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
|
||||
|
||||
static void ffmpeg_cleanup(int ret)
|
||||
{
|
||||
@@ -590,6 +641,7 @@ static void ffmpeg_cleanup(int ret)
|
||||
ost->audio_channels_mapped = 0;
|
||||
|
||||
av_dict_free(&ost->sws_dict);
|
||||
av_dict_free(&ost->swr_opts);
|
||||
|
||||
avcodec_free_context(&ost->enc_ctx);
|
||||
avcodec_parameters_free(&ost->ref_par);
|
||||
@@ -838,7 +890,7 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u
|
||||
ret = av_interleaved_write_frame(s, pkt);
|
||||
if (ret < 0) {
|
||||
print_error("av_interleaved_write_frame()", ret);
|
||||
main_return_code = 1;
|
||||
main_ffmpeg_return_code = 1;
|
||||
close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED);
|
||||
}
|
||||
av_packet_unref(pkt);
|
||||
@@ -2103,12 +2155,13 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
|
||||
InputFile *f = input_files [ist->file_index];
|
||||
int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
|
||||
int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase);
|
||||
AVPacket opkt = { 0 };
|
||||
|
||||
av_init_packet(&opkt);
|
||||
AVPacket opkt;
|
||||
|
||||
// EOF: flush output bitstream filters.
|
||||
if (!pkt) {
|
||||
av_init_packet(&opkt);
|
||||
opkt.data = NULL;
|
||||
opkt.size = 0;
|
||||
output_packet(of, &opkt, ost, 1);
|
||||
return;
|
||||
}
|
||||
@@ -2147,10 +2200,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
|
||||
if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
ost->sync_opts++;
|
||||
|
||||
if (av_packet_ref(&opkt, pkt) < 0)
|
||||
exit_program(1);
|
||||
|
||||
if (pkt->pts != AV_NOPTS_VALUE)
|
||||
opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time;
|
||||
else
|
||||
opkt.pts = AV_NOPTS_VALUE;
|
||||
|
||||
if (pkt->dts == AV_NOPTS_VALUE)
|
||||
opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase);
|
||||
@@ -2169,18 +2223,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
|
||||
|
||||
opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase);
|
||||
|
||||
opkt.flags = pkt->flags;
|
||||
|
||||
if (pkt->buf) {
|
||||
opkt.buf = av_buffer_ref(pkt->buf);
|
||||
if (!opkt.buf)
|
||||
exit_program(1);
|
||||
}
|
||||
opkt.data = pkt->data;
|
||||
opkt.size = pkt->size;
|
||||
|
||||
av_copy_packet_side_data(&opkt, pkt);
|
||||
|
||||
output_packet(of, &opkt, ost, 0);
|
||||
}
|
||||
|
||||
@@ -2890,7 +2932,7 @@ static void print_sdp(void)
|
||||
av_sdp_create(avc, j, sdp, sizeof(sdp));
|
||||
|
||||
if (!sdp_filename) {
|
||||
av_log(NULL, AV_LOG_INFO, "SDP:\n%s\n", sdp);
|
||||
av_log(NULL, AV_LOG_STDERR, "SDP:\n%s\n", sdp);
|
||||
fflush(stdout);
|
||||
} else {
|
||||
if (avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL) < 0) {
|
||||
@@ -3987,7 +4029,9 @@ static OutputStream *choose_output(void)
|
||||
av_rescale_q(ost->st->cur_dts, ost->st->time_base,
|
||||
AV_TIME_BASE_Q);
|
||||
if (ost->st->cur_dts == AV_NOPTS_VALUE)
|
||||
av_log(NULL, AV_LOG_DEBUG, "cur_dts is invalid (this is harmless if it occurs once at the start per stream)\n");
|
||||
av_log(NULL, AV_LOG_DEBUG,
|
||||
"cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n",
|
||||
ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished);
|
||||
|
||||
if (!ost->initialized && !ost->inputs_done)
|
||||
return ost;
|
||||
@@ -4305,7 +4349,7 @@ static int seek_to_start(InputFile *ifile, AVFormatContext *is)
|
||||
int i, ret, has_audio = 0;
|
||||
int64_t duration = 0;
|
||||
|
||||
ret = av_seek_frame(is, -1, is->start_time, 0);
|
||||
ret = avformat_seek_file(is, -1, INT64_MIN, is->start_time, is->start_time, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -4950,8 +4994,8 @@ static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
|
||||
{
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
main_return_code = 0;
|
||||
void ffmpeg_var_cleanup() {
|
||||
main_ffmpeg_return_code = 0;
|
||||
longjmp_value = 0;
|
||||
received_sigterm = 0;
|
||||
received_nb_signals = 0;
|
||||
@@ -4990,15 +5034,449 @@ void cancel_operation()
|
||||
sigterm_handler(SIGINT);
|
||||
}
|
||||
|
||||
int execute(int argc, char **argv)
|
||||
__thread OptionDef *ffmpeg_options = NULL;
|
||||
|
||||
int ffmpeg_execute(int argc, char **argv)
|
||||
{
|
||||
char _program_name[] = "ffmpeg";
|
||||
program_name = (char*)&_program_name;
|
||||
program_birth_year = 2000;
|
||||
|
||||
#define OFFSET(x) offsetof(OptionsContext, x)
|
||||
OptionDef options[] = {
|
||||
|
||||
/* main options */
|
||||
{ "L", OPT_EXIT, { .func_arg = show_license }, "show license" },
|
||||
{ "h", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" },
|
||||
{ "?", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" },
|
||||
{ "help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" },
|
||||
{ "-help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" },
|
||||
{ "version", OPT_EXIT, { .func_arg = show_version }, "show version" },
|
||||
{ "buildconf", OPT_EXIT, { .func_arg = show_buildconf }, "show build configuration" },
|
||||
{ "formats", OPT_EXIT, { .func_arg = show_formats }, "show available formats" },
|
||||
{ "muxers", OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" },
|
||||
{ "demuxers", OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" },
|
||||
{ "devices", OPT_EXIT, { .func_arg = show_devices }, "show available devices" },
|
||||
{ "codecs", OPT_EXIT, { .func_arg = show_codecs }, "show available codecs" },
|
||||
{ "decoders", OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" },
|
||||
{ "encoders", OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" },
|
||||
{ "bsfs", OPT_EXIT, { .func_arg = show_bsfs }, "show available bit stream filters" },
|
||||
{ "protocols", OPT_EXIT, { .func_arg = show_protocols }, "show available protocols" },
|
||||
{ "filters", OPT_EXIT, { .func_arg = show_filters }, "show available filters" },
|
||||
{ "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" },
|
||||
{ "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" },
|
||||
{ "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" },
|
||||
{ "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" },
|
||||
{ "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" },
|
||||
{ "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" },
|
||||
{ "report", 0, { .func_arg = opt_report }, "generate a report" },
|
||||
{ "max_alloc", HAS_ARG, { .func_arg = opt_max_alloc }, "set maximum size of a single allocated block", "bytes" },
|
||||
{ "cpuflags", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpuflags }, "force specific cpu flags", "flags" },
|
||||
{ "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" },
|
||||
|
||||
#if CONFIG_AVDEVICE
|
||||
{ "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources },
|
||||
"list sources of the input device", "device" },
|
||||
{ "sinks" , OPT_EXIT | HAS_ARG, { .func_arg = show_sinks },
|
||||
"list sinks of the output device", "device" },
|
||||
#endif
|
||||
|
||||
{ "f", HAS_ARG | OPT_STRING | OPT_OFFSET |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(format) },
|
||||
"force format", "fmt" },
|
||||
{ "y", OPT_BOOL, { &file_overwrite },
|
||||
"overwrite output files" },
|
||||
{ "n", OPT_BOOL, { &no_file_overwrite },
|
||||
"never overwrite output files" },
|
||||
{ "ignore_unknown", OPT_BOOL, { &ignore_unknown_streams },
|
||||
"Ignore unknown stream types" },
|
||||
{ "copy_unknown", OPT_BOOL | OPT_EXPERT, { ©_unknown_streams },
|
||||
"Copy unknown stream types" },
|
||||
{ "c", HAS_ARG | OPT_STRING | OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(codec_names) },
|
||||
"codec name", "codec" },
|
||||
{ "codec", HAS_ARG | OPT_STRING | OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(codec_names) },
|
||||
"codec name", "codec" },
|
||||
{ "pre", HAS_ARG | OPT_STRING | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(presets) },
|
||||
"preset name", "preset" },
|
||||
{ "map", HAS_ARG | OPT_EXPERT | OPT_PERFILE |
|
||||
OPT_OUTPUT, { .func_arg = opt_map },
|
||||
"set input stream mapping",
|
||||
"[-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]]" },
|
||||
{ "map_channel", HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_map_channel },
|
||||
"map an audio channel from one stream to another", "file.stream.channel[:syncfile.syncstream]" },
|
||||
{ "map_metadata", HAS_ARG | OPT_STRING | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(metadata_map) },
|
||||
"set metadata information of outfile from infile",
|
||||
"outfile[,metadata]:infile[,metadata]" },
|
||||
{ "map_chapters", HAS_ARG | OPT_INT | OPT_EXPERT | OPT_OFFSET |
|
||||
OPT_OUTPUT, { .off = OFFSET(chapters_input_file) },
|
||||
"set chapters mapping", "input_file_index" },
|
||||
{ "t", HAS_ARG | OPT_TIME | OPT_OFFSET |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(recording_time) },
|
||||
"record or transcode \"duration\" seconds of audio/video",
|
||||
"duration" },
|
||||
{ "to", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(stop_time) },
|
||||
"record or transcode stop time", "time_stop" },
|
||||
{ "fs", HAS_ARG | OPT_INT64 | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(limit_filesize) },
|
||||
"set the limit file size in bytes", "limit_size" },
|
||||
{ "ss", HAS_ARG | OPT_TIME | OPT_OFFSET |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(start_time) },
|
||||
"set the start time offset", "time_off" },
|
||||
{ "sseof", HAS_ARG | OPT_TIME | OPT_OFFSET |
|
||||
OPT_INPUT, { .off = OFFSET(start_time_eof) },
|
||||
"set the start time offset relative to EOF", "time_off" },
|
||||
{ "seek_timestamp", HAS_ARG | OPT_INT | OPT_OFFSET |
|
||||
OPT_INPUT, { .off = OFFSET(seek_timestamp) },
|
||||
"enable/disable seeking by timestamp with -ss" },
|
||||
{ "accurate_seek", OPT_BOOL | OPT_OFFSET | OPT_EXPERT |
|
||||
OPT_INPUT, { .off = OFFSET(accurate_seek) },
|
||||
"enable/disable accurate seeking with -ss" },
|
||||
{ "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET |
|
||||
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(input_ts_offset) },
|
||||
"set the input ts offset", "time_off" },
|
||||
{ "itsscale", HAS_ARG | OPT_DOUBLE | OPT_SPEC |
|
||||
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(ts_scale) },
|
||||
"set the input ts scale", "scale" },
|
||||
{ "timestamp", HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_recording_timestamp },
|
||||
"set the recording timestamp ('now' to set the current time)", "time" },
|
||||
{ "metadata", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(metadata) },
|
||||
"add metadata", "string=string" },
|
||||
{ "program", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(program) },
|
||||
"add program with specified streams", "title=string:st=number..." },
|
||||
{ "dframes", HAS_ARG | OPT_PERFILE | OPT_EXPERT |
|
||||
OPT_OUTPUT, { .func_arg = opt_data_frames },
|
||||
"set the number of data frames to output", "number" },
|
||||
{ "benchmark", OPT_BOOL | OPT_EXPERT, { &do_benchmark },
|
||||
"add timings for benchmarking" },
|
||||
{ "benchmark_all", OPT_BOOL | OPT_EXPERT, { &do_benchmark_all },
|
||||
"add timings for each task" },
|
||||
{ "progress", HAS_ARG | OPT_EXPERT, { .func_arg = opt_progress },
|
||||
"write program-readable progress information", "url" },
|
||||
{ "stdin", OPT_BOOL | OPT_EXPERT, { &stdin_interaction },
|
||||
"enable or disable interaction on standard input" },
|
||||
{ "timelimit", HAS_ARG | OPT_EXPERT, { .func_arg = opt_timelimit },
|
||||
"set max runtime in seconds in CPU user time", "limit" },
|
||||
{ "dump", OPT_BOOL | OPT_EXPERT, { &do_pkt_dump },
|
||||
"dump each input packet" },
|
||||
{ "hex", OPT_BOOL | OPT_EXPERT, { &do_hex_dump },
|
||||
"when dumping packets, also dump the payload" },
|
||||
{ "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
|
||||
OPT_INPUT, { .off = OFFSET(rate_emu) },
|
||||
"read input at native frame rate", "" },
|
||||
{ "target", HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_target },
|
||||
"specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" "
|
||||
"with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" },
|
||||
{ "vsync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vsync },
|
||||
"video sync method", "" },
|
||||
{ "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &frame_drop_threshold },
|
||||
"frame drop threshold", "" },
|
||||
{ "async", HAS_ARG | OPT_INT | OPT_EXPERT, { &audio_sync_method },
|
||||
"audio sync method", "" },
|
||||
{ "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &audio_drift_threshold },
|
||||
"audio drift threshold", "threshold" },
|
||||
{ "copyts", OPT_BOOL | OPT_EXPERT, { ©_ts },
|
||||
"copy timestamps" },
|
||||
{ "start_at_zero", OPT_BOOL | OPT_EXPERT, { &start_at_zero },
|
||||
"shift input timestamps to start at 0 when using copyts" },
|
||||
{ "copytb", HAS_ARG | OPT_INT | OPT_EXPERT, { ©_tb },
|
||||
"copy input stream time base when stream copying", "mode" },
|
||||
{ "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
|
||||
OPT_OUTPUT, { .off = OFFSET(shortest) },
|
||||
"finish encoding within shortest input" },
|
||||
{ "bitexact", OPT_BOOL | OPT_EXPERT | OPT_OFFSET |
|
||||
OPT_OUTPUT | OPT_INPUT, { .off = OFFSET(bitexact) },
|
||||
"bitexact mode" },
|
||||
{ "apad", OPT_STRING | HAS_ARG | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(apad) },
|
||||
"audio pad", "" },
|
||||
{ "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &dts_delta_threshold },
|
||||
"timestamp discontinuity delta threshold", "threshold" },
|
||||
{ "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &dts_error_threshold },
|
||||
"timestamp error delta threshold", "threshold" },
|
||||
{ "xerror", OPT_BOOL | OPT_EXPERT, { &exit_on_error },
|
||||
"exit on error", "error" },
|
||||
{ "abort_on", HAS_ARG | OPT_EXPERT, { .func_arg = opt_abort_on },
|
||||
"abort on the specified condition flags", "flags" },
|
||||
{ "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(copy_initial_nonkeyframes) },
|
||||
"copy initial non-keyframes" },
|
||||
{ "copypriorss", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(copy_prior_start) },
|
||||
"copy or discard frames before start time" },
|
||||
{ "frames", OPT_INT64 | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(max_frames) },
|
||||
"set the number of frames to output", "number" },
|
||||
{ "tag", OPT_STRING | HAS_ARG | OPT_SPEC |
|
||||
OPT_EXPERT | OPT_OUTPUT | OPT_INPUT, { .off = OFFSET(codec_tags) },
|
||||
"force codec tag/fourcc", "fourcc/tag" },
|
||||
{ "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE |
|
||||
OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(qscale) },
|
||||
"use fixed quality scale (VBR)", "q" },
|
||||
{ "qscale", HAS_ARG | OPT_EXPERT | OPT_PERFILE |
|
||||
OPT_OUTPUT, { .func_arg = opt_qscale },
|
||||
"use fixed quality scale (VBR)", "q" },
|
||||
{ "profile", HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_profile },
|
||||
"set profile", "profile" },
|
||||
{ "filter", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) },
|
||||
"set stream filtergraph", "filter_graph" },
|
||||
{ "filter_threads", HAS_ARG | OPT_INT, { &filter_nbthreads },
|
||||
"number of non-complex filter threads" },
|
||||
{ "filter_script", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) },
|
||||
"read stream filtergraph description from a file", "filename" },
|
||||
{ "reinit_filter", HAS_ARG | OPT_INT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(reinit_filters) },
|
||||
"reinit filtergraph on input parameter changes", "" },
|
||||
{ "filter_complex", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex },
|
||||
"create a complex filtergraph", "graph_description" },
|
||||
{ "filter_complex_threads", HAS_ARG | OPT_INT, { &filter_complex_nbthreads },
|
||||
"number of threads for -filter_complex" },
|
||||
{ "lavfi", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex },
|
||||
"create a complex filtergraph", "graph_description" },
|
||||
{ "filter_complex_script", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex_script },
|
||||
"read complex filtergraph description from a file", "filename" },
|
||||
{ "stats", OPT_BOOL, { &print_stats },
|
||||
"print progress report during encoding", },
|
||||
{ "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT |
|
||||
OPT_OUTPUT, { .func_arg = opt_attach },
|
||||
"add an attachment to the output file", "filename" },
|
||||
{ "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC |
|
||||
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(dump_attachment) },
|
||||
"extract an attachment into a file", "filename" },
|
||||
{ "stream_loop", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_INPUT |
|
||||
OPT_OFFSET, { .off = OFFSET(loop) }, "set number of times input stream shall be looped", "loop count" },
|
||||
{ "debug_ts", OPT_BOOL | OPT_EXPERT, { &debug_ts },
|
||||
"print timestamp debugging info" },
|
||||
{ "max_error_rate", HAS_ARG | OPT_FLOAT, { &max_error_rate },
|
||||
"ratio of errors (0.0: no errors, 1.0: 100% errors) above which ffmpeg returns an error instead of success.", "maximum error rate" },
|
||||
{ "discard", OPT_STRING | HAS_ARG | OPT_SPEC |
|
||||
OPT_INPUT, { .off = OFFSET(discard) },
|
||||
"discard", "" },
|
||||
{ "disposition", OPT_STRING | HAS_ARG | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(disposition) },
|
||||
"disposition", "" },
|
||||
{ "thread_queue_size", HAS_ARG | OPT_INT | OPT_OFFSET | OPT_EXPERT | OPT_INPUT,
|
||||
{ .off = OFFSET(thread_queue_size) },
|
||||
"set the maximum number of queued packets from the demuxer" },
|
||||
{ "find_stream_info", OPT_BOOL | OPT_PERFILE | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
|
||||
"read and decode the streams to fill missing information with heuristics" },
|
||||
|
||||
/* video options */
|
||||
{ "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames },
|
||||
"set the number of video frames to output", "number" },
|
||||
{ "r", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_rates) },
|
||||
"set frame rate (Hz value, fraction or abbreviation)", "rate" },
|
||||
{ "s", OPT_VIDEO | HAS_ARG | OPT_SUBTITLE | OPT_STRING | OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_sizes) },
|
||||
"set frame size (WxH or abbreviation)", "size" },
|
||||
{ "aspect", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(frame_aspect_ratios) },
|
||||
"set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
|
||||
{ "pix_fmt", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_pix_fmts) },
|
||||
"set pixel format", "format" },
|
||||
{ "bits_per_raw_sample", OPT_VIDEO | OPT_INT | HAS_ARG, { &frame_bits_per_raw_sample },
|
||||
"set the number of bits per raw sample", "number" },
|
||||
{ "intra", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &intra_only },
|
||||
"deprecated use -g 1" },
|
||||
{ "vn", OPT_VIDEO | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(video_disable) },
|
||||
"disable video" },
|
||||
{ "rc_override", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(rc_overrides) },
|
||||
"rate control override for specific intervals", "override" },
|
||||
{ "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_INPUT |
|
||||
OPT_OUTPUT, { .func_arg = opt_video_codec },
|
||||
"force video codec ('copy' to copy stream)", "codec" },
|
||||
{ "sameq", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_sameq },
|
||||
"Removed" },
|
||||
{ "same_quant", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_sameq },
|
||||
"Removed" },
|
||||
{ "timecode", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_timecode },
|
||||
"set initial TimeCode value.", "hh:mm:ss[:;.]ff" },
|
||||
{ "pass", OPT_VIDEO | HAS_ARG | OPT_SPEC | OPT_INT | OPT_OUTPUT, { .off = OFFSET(pass) },
|
||||
"select the pass number (1 to 3)", "n" },
|
||||
{ "passlogfile", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(passlogfiles) },
|
||||
"select two pass log file name prefix", "prefix" },
|
||||
{ "deinterlace", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_deinterlace },
|
||||
"this option is deprecated, use the yadif filter instead" },
|
||||
{ "psnr", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_psnr },
|
||||
"calculate PSNR of compressed frames" },
|
||||
{ "vstats", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_vstats },
|
||||
"dump video coding statistics to file" },
|
||||
{ "vstats_file", OPT_VIDEO | HAS_ARG | OPT_EXPERT , { .func_arg = opt_vstats_file },
|
||||
"dump video coding statistics to file", "file" },
|
||||
{ "vstats_version", OPT_VIDEO | OPT_INT | HAS_ARG | OPT_EXPERT , { &vstats_version },
|
||||
"Version of the vstats format to use."},
|
||||
{ "vf", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_filters },
|
||||
"set video filters", "filter_graph" },
|
||||
{ "intra_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(intra_matrices) },
|
||||
"specify intra matrix coeffs", "matrix" },
|
||||
{ "inter_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(inter_matrices) },
|
||||
"specify inter matrix coeffs", "matrix" },
|
||||
{ "chroma_intra_matrix", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(chroma_intra_matrices) },
|
||||
"specify intra matrix coeffs", "matrix" },
|
||||
{ "top", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_INT| OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(top_field_first) },
|
||||
"top=1/bottom=0/auto=-1 field first", "" },
|
||||
{ "vtag", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE |
|
||||
OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_old2new },
|
||||
"force video tag/fourcc", "fourcc/tag" },
|
||||
{ "qphist", OPT_VIDEO | OPT_BOOL | OPT_EXPERT , { &qp_hist },
|
||||
"show QP histogram" },
|
||||
{ "force_fps", OPT_VIDEO | OPT_BOOL | OPT_EXPERT | OPT_SPEC |
|
||||
OPT_OUTPUT, { .off = OFFSET(force_fps) },
|
||||
"force the selected framerate, disable the best supported framerate selection" },
|
||||
{ "streamid", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_PERFILE |
|
||||
OPT_OUTPUT, { .func_arg = opt_streamid },
|
||||
"set the value of an outfile streamid", "streamIndex:value" },
|
||||
{ "force_key_frames", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
|
||||
OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(forced_key_frames) },
|
||||
"force key frames at specified timestamps", "timestamps" },
|
||||
{ "ab", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate },
|
||||
"audio bitrate (please use -b:a)", "bitrate" },
|
||||
{ "b", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_bitrate },
|
||||
"video bitrate (please use -b:v)", "bitrate" },
|
||||
{ "hwaccel", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
|
||||
OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccels) },
|
||||
"use HW accelerated decoding", "hwaccel name" },
|
||||
{ "hwaccel_device", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
|
||||
OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_devices) },
|
||||
"select a device for HW acceleration", "devicename" },
|
||||
{ "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
|
||||
OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) },
|
||||
"select output format used with HW accelerated decoding", "format" },
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
{ "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" },
|
||||
#endif
|
||||
{ "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels },
|
||||
"show available HW acceleration methods" },
|
||||
{ "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC |
|
||||
OPT_EXPERT | OPT_INPUT, { .off = OFFSET(autorotate) },
|
||||
"automatically insert correct rotate filters" },
|
||||
|
||||
/* audio options */
|
||||
{ "aframes", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_frames },
|
||||
"set the number of audio frames to output", "number" },
|
||||
{ "aq", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_qscale },
|
||||
"set audio quality (codec-specific)", "quality", },
|
||||
{ "ar", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(audio_sample_rate) },
|
||||
"set audio sampling rate (in Hz)", "rate" },
|
||||
{ "ac", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC |
|
||||
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(audio_channels) },
|
||||
"set number of audio channels", "channels" },
|
||||
{ "an", OPT_AUDIO | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(audio_disable) },
|
||||
"disable audio" },
|
||||
{ "acodec", OPT_AUDIO | HAS_ARG | OPT_PERFILE |
|
||||
OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_audio_codec },
|
||||
"force audio codec ('copy' to copy stream)", "codec" },
|
||||
{ "atag", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE |
|
||||
OPT_OUTPUT, { .func_arg = opt_old2new },
|
||||
"force audio tag/fourcc", "fourcc/tag" },
|
||||
{ "vol", OPT_AUDIO | HAS_ARG | OPT_INT, { &audio_volume },
|
||||
"change audio volume (256=normal)" , "volume" },
|
||||
{ "sample_fmt", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC |
|
||||
OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(sample_fmts) },
|
||||
"set sample format", "format" },
|
||||
{ "channel_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE |
|
||||
OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_channel_layout },
|
||||
"set channel layout", "layout" },
|
||||
{ "af", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_filters },
|
||||
"set audio filters", "filter_graph" },
|
||||
{ "guess_layout_max", OPT_AUDIO | HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(guess_layout_max) },
|
||||
"set the maximum number of channels to try to guess the channel layout" },
|
||||
|
||||
/* subtitle options */
|
||||
{ "sn", OPT_SUBTITLE | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(subtitle_disable) },
|
||||
"disable subtitle" },
|
||||
{ "scodec", OPT_SUBTITLE | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_subtitle_codec },
|
||||
"force subtitle codec ('copy' to copy stream)", "codec" },
|
||||
{ "stag", OPT_SUBTITLE | HAS_ARG | OPT_EXPERT | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new }
|
||||
, "force subtitle tag/fourcc", "fourcc/tag" },
|
||||
{ "fix_sub_duration", OPT_BOOL | OPT_EXPERT | OPT_SUBTITLE | OPT_SPEC | OPT_INPUT, { .off = OFFSET(fix_sub_duration) },
|
||||
"fix subtitles duration" },
|
||||
{ "canvas_size", OPT_SUBTITLE | HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFFSET(canvas_sizes) },
|
||||
"set canvas size (WxH or abbreviation)", "size" },
|
||||
|
||||
/* grab options */
|
||||
{ "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_channel },
|
||||
"deprecated, use -channel", "channel" },
|
||||
{ "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_standard },
|
||||
"deprecated, use -standard", "standard" },
|
||||
{ "isync", OPT_BOOL | OPT_EXPERT, { &input_sync }, "this option is deprecated and does nothing", "" },
|
||||
|
||||
/* muxer options */
|
||||
{ "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_max_delay) },
|
||||
"set the maximum demux-decode delay", "seconds" },
|
||||
{ "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_preload) },
|
||||
"set the initial demux-decode delay", "seconds" },
|
||||
{ "sdp_file", HAS_ARG | OPT_EXPERT | OPT_OUTPUT, { .func_arg = opt_sdp_file },
|
||||
"specify a file in which to print sdp information", "file" },
|
||||
|
||||
{ "time_base", HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(time_bases) },
|
||||
"set the desired time base hint for output stream (1:24, 1:48000 or 0.04166, 2.0833e-5)", "ratio" },
|
||||
{ "enc_time_base", HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(enc_time_bases) },
|
||||
"set the desired time base for the encoder (1:24, 1:48000 or 0.04166, 2.0833e-5). "
|
||||
"two special values are defined - "
|
||||
"0 = use frame rate (video) or sample rate (audio),"
|
||||
"-1 = match source time base", "ratio" },
|
||||
|
||||
{ "bsf", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(bitstream_filters) },
|
||||
"A comma-separated list of bitstream filters", "bitstream_filters" },
|
||||
{ "absf", HAS_ARG | OPT_AUDIO | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new },
|
||||
"deprecated", "audio bitstream_filters" },
|
||||
{ "vbsf", OPT_VIDEO | HAS_ARG | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_old2new },
|
||||
"deprecated", "video bitstream_filters" },
|
||||
|
||||
{ "apre", HAS_ARG | OPT_AUDIO | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_preset },
|
||||
"set the audio options to the indicated preset", "preset" },
|
||||
{ "vpre", OPT_VIDEO | HAS_ARG | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_preset },
|
||||
"set the video options to the indicated preset", "preset" },
|
||||
{ "spre", HAS_ARG | OPT_SUBTITLE | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_preset },
|
||||
"set the subtitle options to the indicated preset", "preset" },
|
||||
{ "fpre", HAS_ARG | OPT_EXPERT| OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_preset },
|
||||
"set options from indicated preset file", "filename" },
|
||||
|
||||
{ "max_muxing_queue_size", HAS_ARG | OPT_INT | OPT_SPEC | OPT_EXPERT | OPT_OUTPUT, { .off = OFFSET(max_muxing_queue_size) },
|
||||
"maximum number of packets that can be buffered while waiting for all streams to initialize", "packets" },
|
||||
|
||||
/* data codec support */
|
||||
{ "dcodec", HAS_ARG | OPT_DATA | OPT_PERFILE | OPT_EXPERT | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_data_codec },
|
||||
"force data codec ('copy' to copy stream)", "codec" },
|
||||
{ "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(data_disable) },
|
||||
"disable data" },
|
||||
|
||||
#if CONFIG_VAAPI
|
||||
{ "vaapi_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vaapi_device },
|
||||
"set VAAPI hardware device (DRM path or X11 display name)", "device" },
|
||||
#endif
|
||||
|
||||
#if CONFIG_QSV
|
||||
{ "qsv_device", HAS_ARG | OPT_STRING | OPT_EXPERT, { &qsv_device },
|
||||
"set QSV hardware device (DirectX adapter index, DRM path or X11 display name)", "device"},
|
||||
#endif
|
||||
|
||||
{ "init_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_init_hw_device },
|
||||
"initialise hardware device", "args" },
|
||||
{ "filter_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_hw_device },
|
||||
"set hardware device used when filtering", "device" },
|
||||
|
||||
{ NULL, },
|
||||
};
|
||||
|
||||
ffmpeg_options = options;
|
||||
|
||||
int i, ret;
|
||||
BenchmarkTimeStamps ti;
|
||||
|
||||
int savedCode = setjmp(ex_buf__);
|
||||
if (savedCode == 0) {
|
||||
|
||||
cleanup();
|
||||
ffmpeg_var_cleanup();
|
||||
|
||||
init_dynload();
|
||||
|
||||
@@ -5063,11 +5541,11 @@ int execute(int argc, char **argv)
|
||||
if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1])
|
||||
exit_program(69);
|
||||
|
||||
exit_program(received_nb_signals ? 255 : main_return_code);
|
||||
exit_program(received_nb_signals ? 255 : main_ffmpeg_return_code);
|
||||
|
||||
} else {
|
||||
main_return_code = longjmp_value;
|
||||
main_ffmpeg_return_code = longjmp_value;
|
||||
}
|
||||
|
||||
return main_return_code;
|
||||
return main_ffmpeg_return_code;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* CHANGES 01.2020
|
||||
* - ffprobe support changes
|
||||
*
|
||||
* CHANGES 12.2019
|
||||
* - Concurrent execution support
|
||||
*
|
||||
* CHANGES 03.2019
|
||||
* --------------------------------------------------------
|
||||
* - config.h include removed
|
||||
@@ -86,7 +92,7 @@ typedef struct HWAccel {
|
||||
} HWAccel;
|
||||
|
||||
typedef struct HWDevice {
|
||||
char *name;
|
||||
const char *name;
|
||||
enum AVHWDeviceType type;
|
||||
AVBufferRef *device_ref;
|
||||
} HWDevice;
|
||||
@@ -578,63 +584,61 @@ typedef struct OutputFile {
|
||||
int header_written;
|
||||
} OutputFile;
|
||||
|
||||
extern InputStream **input_streams;
|
||||
extern int nb_input_streams;
|
||||
extern InputFile **input_files;
|
||||
extern int nb_input_files;
|
||||
extern __thread InputStream **input_streams;
|
||||
extern __thread int nb_input_streams;
|
||||
extern __thread InputFile **input_files;
|
||||
extern __thread int nb_input_files;
|
||||
|
||||
extern OutputStream **output_streams;
|
||||
extern int nb_output_streams;
|
||||
extern OutputFile **output_files;
|
||||
extern int nb_output_files;
|
||||
extern __thread OutputStream **output_streams;
|
||||
extern __thread int nb_output_streams;
|
||||
extern __thread OutputFile **output_files;
|
||||
extern __thread int nb_output_files;
|
||||
|
||||
extern FilterGraph **filtergraphs;
|
||||
extern int nb_filtergraphs;
|
||||
extern __thread FilterGraph **filtergraphs;
|
||||
extern __thread int nb_filtergraphs;
|
||||
|
||||
extern char *vstats_filename;
|
||||
extern char *sdp_filename;
|
||||
extern __thread char *vstats_filename;
|
||||
extern __thread char *sdp_filename;
|
||||
|
||||
extern float audio_drift_threshold;
|
||||
extern float dts_delta_threshold;
|
||||
extern float dts_error_threshold;
|
||||
extern __thread float audio_drift_threshold;
|
||||
extern __thread float dts_delta_threshold;
|
||||
extern __thread float dts_error_threshold;
|
||||
|
||||
extern int audio_volume;
|
||||
extern int audio_sync_method;
|
||||
extern int video_sync_method;
|
||||
extern float frame_drop_threshold;
|
||||
extern int do_benchmark;
|
||||
extern int do_benchmark_all;
|
||||
extern int do_deinterlace;
|
||||
extern int do_hex_dump;
|
||||
extern int do_pkt_dump;
|
||||
extern int copy_ts;
|
||||
extern int start_at_zero;
|
||||
extern int copy_tb;
|
||||
extern int debug_ts;
|
||||
extern int exit_on_error;
|
||||
extern int abort_on_flags;
|
||||
extern int print_stats;
|
||||
extern int qp_hist;
|
||||
extern int stdin_interaction;
|
||||
extern int frame_bits_per_raw_sample;
|
||||
extern AVIOContext *progress_avio;
|
||||
extern float max_error_rate;
|
||||
extern char *videotoolbox_pixfmt;
|
||||
extern __thread int audio_volume;
|
||||
extern __thread int audio_sync_method;
|
||||
extern __thread int video_sync_method;
|
||||
extern __thread float frame_drop_threshold;
|
||||
extern __thread int do_benchmark;
|
||||
extern __thread int do_benchmark_all;
|
||||
extern __thread int do_deinterlace;
|
||||
extern __thread int do_hex_dump;
|
||||
extern __thread int do_pkt_dump;
|
||||
extern __thread int copy_ts;
|
||||
extern __thread int start_at_zero;
|
||||
extern __thread int copy_tb;
|
||||
extern __thread int debug_ts;
|
||||
extern __thread int exit_on_error;
|
||||
extern __thread int abort_on_flags;
|
||||
extern __thread int print_stats;
|
||||
extern __thread int qp_hist;
|
||||
extern __thread int stdin_interaction;
|
||||
extern __thread int frame_bits_per_raw_sample;
|
||||
extern __thread AVIOContext *progress_avio;
|
||||
extern __thread float max_error_rate;
|
||||
extern __thread char *videotoolbox_pixfmt;
|
||||
|
||||
extern int filter_nbthreads;
|
||||
extern int filter_complex_nbthreads;
|
||||
extern int vstats_version;
|
||||
extern __thread int filter_nbthreads;
|
||||
extern __thread int filter_complex_nbthreads;
|
||||
extern __thread int vstats_version;
|
||||
|
||||
extern const AVIOInterruptCB int_cb;
|
||||
extern __thread const AVIOInterruptCB int_cb;
|
||||
|
||||
extern const OptionDef options[];
|
||||
extern const HWAccel hwaccels[];
|
||||
extern AVBufferRef *hw_device_ctx;
|
||||
extern __thread AVBufferRef *hw_device_ctx;
|
||||
#if CONFIG_QSV
|
||||
extern char *qsv_device;
|
||||
extern __thread char *qsv_device;
|
||||
#endif
|
||||
extern HWDevice *filter_hw_device;
|
||||
|
||||
extern __thread HWDevice *filter_hw_device;
|
||||
|
||||
void term_init(void);
|
||||
void term_exit(void);
|
||||
@@ -683,4 +687,75 @@ void set_report_callback(void (*callback)(int, float, float, int64_t, int, doubl
|
||||
|
||||
void cancel_operation();
|
||||
|
||||
int opt_map(void *optctx, const char *opt, const char *arg);
|
||||
int opt_map_channel(void *optctx, const char *opt, const char *arg);
|
||||
int opt_recording_timestamp(void *optctx, const char *opt, const char *arg);
|
||||
int opt_data_frames(void *optctx, const char *opt, const char *arg);
|
||||
int opt_progress(void *optctx, const char *opt, const char *arg);
|
||||
int opt_target(void *optctx, const char *opt, const char *arg);
|
||||
int opt_vsync(void *optctx, const char *opt, const char *arg);
|
||||
int opt_abort_on(void *optctx, const char *opt, const char *arg);
|
||||
int opt_qscale(void *optctx, const char *opt, const char *arg);
|
||||
int opt_profile(void *optctx, const char *opt, const char *arg);
|
||||
int opt_filter_complex(void *optctx, const char *opt, const char *arg);
|
||||
int opt_filter_complex_script(void *optctx, const char *opt, const char *arg);
|
||||
int opt_attach(void *optctx, const char *opt, const char *arg);
|
||||
int opt_video_frames(void *optctx, const char *opt, const char *arg);
|
||||
int opt_video_codec(void *optctx, const char *opt, const char *arg);
|
||||
int opt_sameq(void *optctx, const char *opt, const char *arg);
|
||||
int opt_timecode(void *optctx, const char *opt, const char *arg);
|
||||
|
||||
int opt_vstats_file(void *optctx, const char *opt, const char *arg);
|
||||
int opt_vstats(void *optctx, const char *opt, const char *arg);
|
||||
int opt_video_frames(void *optctx, const char *opt, const char *arg);
|
||||
int opt_old2new(void *optctx, const char *opt, const char *arg);
|
||||
int opt_streamid(void *optctx, const char *opt, const char *arg);
|
||||
int opt_bitrate(void *optctx, const char *opt, const char *arg);
|
||||
int show_hwaccels(void *optctx, const char *opt, const char *arg);
|
||||
int opt_video_filters(void *optctx, const char *opt, const char *arg);
|
||||
int opt_audio_frames(void *optctx, const char *opt, const char *arg);
|
||||
int opt_audio_qscale(void *optctx, const char *opt, const char *arg);
|
||||
int opt_audio_codec(void *optctx, const char *opt, const char *arg);
|
||||
int opt_channel_layout(void *optctx, const char *opt, const char *arg);
|
||||
int opt_preset(void *optctx, const char *opt, const char *arg);
|
||||
int opt_audio_filters(void *optctx, const char *opt, const char *arg);
|
||||
int opt_subtitle_codec(void *optctx, const char *opt, const char *arg);
|
||||
int opt_video_channel(void *optctx, const char *opt, const char *arg);
|
||||
int opt_video_standard(void *optctx, const char *opt, const char *arg);
|
||||
int opt_sdp_file(void *optctx, const char *opt, const char *arg);
|
||||
int opt_data_codec(void *optctx, const char *opt, const char *arg);
|
||||
int opt_init_hw_device(void *optctx, const char *opt, const char *arg);
|
||||
int opt_filter_hw_device(void *optctx, const char *opt, const char *arg);
|
||||
void add_input_streams(OptionsContext *o, AVFormatContext *ic);
|
||||
void assert_file_overwrite(const char *filename);
|
||||
void dump_attachment(AVStream *st, const char *filename);
|
||||
uint8_t *get_line(AVIOContext *s);
|
||||
void uninit_options(OptionsContext *o);
|
||||
void init_options(OptionsContext *o);
|
||||
AVDictionary *strip_specifiers(AVDictionary *dict);
|
||||
void parse_meta_type(char *arg, char *type, int *index, const char **stream_spec);
|
||||
int fftools_copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o);
|
||||
AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder);
|
||||
AVCodec *choose_decoder(OptionsContext *o, AVFormatContext *s, AVStream *st);
|
||||
int open_input_file(OptionsContext *o, const char *filename);
|
||||
int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s);
|
||||
int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputStream *ost);
|
||||
OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index);
|
||||
void parse_matrix_coeffs(uint16_t *dest, const char *str);
|
||||
uint8_t *fftools_read_file(const char *filename);
|
||||
char *get_ost_filters(OptionsContext *o, AVFormatContext *oc, OutputStream *ost);
|
||||
void check_streamcopy_filters(OptionsContext *o, AVFormatContext *oc, const OutputStream *ost, enum AVMediaType type);
|
||||
OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index);
|
||||
OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, int source_index);
|
||||
OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int source_index);
|
||||
OutputStream *new_unknown_stream(OptionsContext *o, AVFormatContext *oc, int source_index);
|
||||
OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index);
|
||||
OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, int source_index);
|
||||
int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata);
|
||||
void init_output_filter(OutputFilter *ofilter, OptionsContext *o, AVFormatContext *oc);
|
||||
int init_complex_filters(void);
|
||||
int open_output_file(OptionsContext *o, const char *filename);
|
||||
int opt_default_new(OptionsContext *o, const char *opt, const char *arg);
|
||||
int open_files(OptionGroupList *l, const char *inout, int (*open_file)(OptionsContext*, const char*));
|
||||
|
||||
#endif /* FFTOOLS_FFMPEG_H */
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* CHANGES 12.2019
|
||||
* - Concurrent execution support
|
||||
*
|
||||
* CHANGES 08.2018
|
||||
* --------------------------------------------------------
|
||||
* - fftools_ prefix added to file name and parent header
|
||||
@@ -28,8 +31,8 @@
|
||||
|
||||
#include "fftools_ffmpeg.h"
|
||||
|
||||
static int nb_hw_devices;
|
||||
static HWDevice **hw_devices;
|
||||
__thread int nb_hw_devices;
|
||||
__thread HWDevice **hw_devices;
|
||||
|
||||
static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type)
|
||||
{
|
||||
@@ -105,7 +108,7 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
|
||||
// -> av_hwdevice_ctx_create_derived()
|
||||
|
||||
AVDictionary *options = NULL;
|
||||
char *type_name = NULL, *name = NULL, *device = NULL;
|
||||
const char *type_name = NULL, *name = NULL, *device = NULL;
|
||||
enum AVHWDeviceType type;
|
||||
HWDevice *dev, *src;
|
||||
AVBufferRef *device_ref = NULL;
|
||||
@@ -161,11 +164,13 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
|
||||
++p;
|
||||
q = strchr(p, ',');
|
||||
if (q) {
|
||||
if (q - p > 0) {
|
||||
device = av_strndup(p, q - p);
|
||||
if (!device) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
err = av_dict_parse_string(&options, q + 1, "=", ",", 0);
|
||||
if (err < 0) {
|
||||
errmsg = "failed to parse options";
|
||||
@@ -174,7 +179,8 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
|
||||
}
|
||||
|
||||
err = av_hwdevice_ctx_create(&device_ref, type,
|
||||
device ? device : p, options, 0);
|
||||
q ? device : p[0] ? p : NULL,
|
||||
options, 0);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@
|
||||
* CHANGES 08.2019
|
||||
* --------------------------------------------------------
|
||||
* - lastCommandOutput methods introduced
|
||||
* - AV_LOG_STDERR introduced
|
||||
*
|
||||
* CHANGES 04.2019
|
||||
* --------------------------------------------------------
|
||||
@@ -53,6 +54,7 @@
|
||||
#include "libavutil/bprint.h"
|
||||
#include "fftools_ffmpeg.h"
|
||||
#include "mobileffmpeg.h"
|
||||
#include "mobileffprobe.h"
|
||||
|
||||
/** Callback data structure */
|
||||
struct CallbackData {
|
||||
@@ -119,21 +121,24 @@ JNINativeMethod configMethods[] = {
|
||||
{"getNativeLogLevel", "()I", (void*) Java_com_arthenica_mobileffmpeg_Config_getNativeLogLevel},
|
||||
{"getNativeFFmpegVersion", "()Ljava/lang/String;", (void*) Java_com_arthenica_mobileffmpeg_Config_getNativeFFmpegVersion},
|
||||
{"getNativeVersion", "()Ljava/lang/String;", (void*) Java_com_arthenica_mobileffmpeg_Config_getNativeVersion},
|
||||
{"nativeExecute", "([Ljava/lang/String;)I", (void*) Java_com_arthenica_mobileffmpeg_Config_nativeExecute},
|
||||
{"nativeCancel", "()V", (void*) Java_com_arthenica_mobileffmpeg_Config_nativeCancel},
|
||||
{"nativeFFmpegExecute", "([Ljava/lang/String;)I", (void*) Java_com_arthenica_mobileffmpeg_Config_nativeFFmpegExecute},
|
||||
{"nativeFFmpegCancel", "()V", (void*) Java_com_arthenica_mobileffmpeg_Config_nativeFFmpegCancel},
|
||||
{"nativeFFprobeExecute", "([Ljava/lang/String;)I", (void*) Java_com_arthenica_mobileffmpeg_Config_nativeFFprobeExecute},
|
||||
{"registerNewNativeFFmpegPipe", "(Ljava/lang/String;)I", (void*) Java_com_arthenica_mobileffmpeg_Config_registerNewNativeFFmpegPipe},
|
||||
{"getNativeBuildDate", "()Ljava/lang/String;", (void*) Java_com_arthenica_mobileffmpeg_Config_getNativeBuildDate},
|
||||
{"setNativeEnvironmentVariable", "(Ljava/lang/String;Ljava/lang/String;)I", (void*) Java_com_arthenica_mobileffmpeg_Config_setNativeEnvironmentVariable}
|
||||
};
|
||||
|
||||
/** Forward declaration for function defined in fftools_ffmpeg.c */
|
||||
int execute(int argc, char **argv);
|
||||
int ffmpeg_execute(int argc, char **argv);
|
||||
|
||||
/** DEFINES LINE SIZE USED FOR LOGGING */
|
||||
#define LOG_LINE_SIZE 1024
|
||||
|
||||
static const char *avutil_log_get_level_str(int level) {
|
||||
switch (level) {
|
||||
case AV_LOG_STDERR:
|
||||
return "stderr";
|
||||
case AV_LOG_QUIET:
|
||||
return "quiet";
|
||||
case AV_LOG_DEBUG:
|
||||
@@ -462,7 +467,9 @@ void mobileffmpeg_log_callback_function(void *ptr, int level, const char* format
|
||||
level &= 0xff;
|
||||
}
|
||||
int activeLogLevel = av_log_get_level();
|
||||
if ((activeLogLevel == AV_LOG_QUIET) || (level > activeLogLevel)) {
|
||||
|
||||
// AV_LOG_STDERR logs are always redirected
|
||||
if ((activeLogLevel == AV_LOG_QUIET && level != AV_LOG_STDERR) || (level > activeLogLevel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -584,7 +591,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if ((*env)->RegisterNatives(env, localConfigClass, configMethods, 11) < 0) {
|
||||
if ((*env)->RegisterNatives(env, localConfigClass, configMethods, 12) < 0) {
|
||||
LOGE("OnLoad failed to RegisterNatives for class %s.\n", configClassName);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
@@ -730,14 +737,14 @@ JNIEXPORT jstring JNICALL Java_com_arthenica_mobileffmpeg_Config_getNativeVersio
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously executes FFmpeg command natively with arguments provided.
|
||||
* Synchronously executes FFmpeg natively with arguments provided.
|
||||
*
|
||||
* @param env pointer to native method interface
|
||||
* @param object reference to the class on which this method is invoked
|
||||
* @param stringArray reference to the object holding FFmpeg command arguments
|
||||
* @return zero on successful execution, non-zero on error
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeExecute(JNIEnv *env, jclass object, jobjectArray stringArray) {
|
||||
JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeFFmpegExecute(JNIEnv *env, jclass object, jobjectArray stringArray) {
|
||||
jstring *tempArray = NULL;
|
||||
int argumentCount = 1;
|
||||
char **argv = NULL;
|
||||
@@ -771,7 +778,7 @@ JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeExecute(JNIE
|
||||
clearLastCommandOutput();
|
||||
|
||||
// RUN
|
||||
int retCode = execute(argumentCount, argv);
|
||||
int retCode = ffmpeg_execute(argumentCount, argv);
|
||||
|
||||
// CLEANUP
|
||||
if (tempArray != NULL) {
|
||||
@@ -788,12 +795,12 @@ JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeExecute(JNIE
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels an ongoing operation natively.
|
||||
* Cancels an ongoing FFmpeg operation natively.
|
||||
*
|
||||
* @param env pointer to native method interface
|
||||
* @param object reference to the class on which this method is invoked
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeCancel(JNIEnv *env, jclass object) {
|
||||
JNIEXPORT void JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeFFmpegCancel(JNIEnv *env, jclass object) {
|
||||
cancel_operation();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "libavutil/ffversion.h"
|
||||
|
||||
/** Library version string */
|
||||
#define MOBILE_FFMPEG_VERSION "4.3"
|
||||
#define MOBILE_FFMPEG_VERSION "4.3.1"
|
||||
|
||||
/** Defines tag used for Android logging. */
|
||||
#define LIB_NAME "mobile-ffmpeg"
|
||||
@@ -91,17 +91,17 @@ JNIEXPORT jstring JNICALL Java_com_arthenica_mobileffmpeg_Config_getNativeVersio
|
||||
|
||||
/*
|
||||
* Class: com_arthenica_mobileffmpeg_Config
|
||||
* Method: nativeExecute
|
||||
* Method: nativeFFmpegExecute
|
||||
* Signature: ([Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeExecute(JNIEnv *, jclass, jobjectArray);
|
||||
JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeFFmpegExecute(JNIEnv *, jclass, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: com_arthenica_mobileffmpeg_Config
|
||||
* Method: nativeCancel
|
||||
* Method: nativeFFmpegCancel
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeCancel(JNIEnv *, jclass);
|
||||
JNIEXPORT void JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeFFmpegCancel(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: com_arthenica_mobileffmpeg_Config
|
||||
|
||||
+6
-18
@@ -13,24 +13,12 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.mobileffmpeg.test;
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
/** Holds information to implement exception handling. */
|
||||
__thread jmp_buf ex_buf__;
|
||||
@@ -24,6 +24,6 @@
|
||||
#include <setjmp.h>
|
||||
|
||||
/** Holds information to implement exception handling. */
|
||||
jmp_buf ex_buf__;
|
||||
extern __thread jmp_buf ex_buf__;
|
||||
|
||||
#endif // MOBILE_FFMPEG_EXCEPTION_H
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "libavcodec/jni.h"
|
||||
#include "libavutil/bprint.h"
|
||||
#include "mobileffmpeg.h"
|
||||
|
||||
/** Forward declaration for function defined in fftools_ffprobe.c */
|
||||
int ffprobe_execute(int argc, char **argv);
|
||||
|
||||
/** Forward declaration for function defined in mobileffmpeg.c */
|
||||
void clearLastCommandOutput();
|
||||
|
||||
/**
|
||||
* Synchronously executes FFprobe natively with arguments provided.
|
||||
*
|
||||
* @param env pointer to native method interface
|
||||
* @param object reference to the class on which this method is invoked
|
||||
* @param stringArray reference to the object holding FFprobe command arguments
|
||||
* @return zero on successful execution, non-zero on error
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeFFprobeExecute(JNIEnv *env, jclass object, jobjectArray stringArray) {
|
||||
jstring *tempArray = NULL;
|
||||
int argumentCount = 1;
|
||||
char **argv = NULL;
|
||||
|
||||
if (stringArray != NULL) {
|
||||
int programArgumentCount = (*env)->GetArrayLength(env, stringArray);
|
||||
argumentCount = programArgumentCount + 1;
|
||||
|
||||
tempArray = (jstring *) av_malloc(sizeof(jstring) * programArgumentCount);
|
||||
}
|
||||
|
||||
/* PRESERVE USAGE FORMAT
|
||||
*
|
||||
* ffprobe <arguments>
|
||||
*/
|
||||
argv = (char **)av_malloc(sizeof(char*) * (argumentCount));
|
||||
argv[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
|
||||
strcpy(argv[0], LIB_NAME);
|
||||
|
||||
// PREPARE
|
||||
if (stringArray != NULL) {
|
||||
for (int i = 0; i < (argumentCount - 1); i++) {
|
||||
tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
|
||||
if (tempArray[i] != NULL) {
|
||||
argv[i + 1] = (char *) (*env)->GetStringUTFChars(env, tempArray[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LAST COMMAND OUTPUT SHOULD BE CLEARED BEFORE STARTING A NEW EXECUTION
|
||||
clearLastCommandOutput();
|
||||
|
||||
// RUN
|
||||
int retCode = ffprobe_execute(argumentCount, argv);
|
||||
|
||||
// CLEANUP
|
||||
if (tempArray != NULL) {
|
||||
for (int i = 0; i < (argumentCount - 1); i++) {
|
||||
(*env)->ReleaseStringUTFChars(env, tempArray[i], argv[i + 1]);
|
||||
}
|
||||
|
||||
av_free(tempArray);
|
||||
}
|
||||
av_free(argv[0]);
|
||||
av_free(argv);
|
||||
|
||||
return retCode;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MOBILE_FFPROBE_H
|
||||
#define MOBILE_FFPROBE_H
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
/*
|
||||
* Class: com_arthenica_mobileffmpeg_Config
|
||||
* Method: nativeFFprobeExecute
|
||||
* Signature: ([Ljava/lang/String;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_com_arthenica_mobileffmpeg_Config_nativeFFprobeExecute(JNIEnv *, jclass, jobjectArray);
|
||||
|
||||
#endif /* MOBILE_FFPROBE_H */
|
||||
@@ -31,35 +31,36 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.getBuildDate;
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.getVersion;
|
||||
|
||||
/**
|
||||
* <p>This class is used to configure MobileFFmpeg library utilities/tools.
|
||||
*
|
||||
* <p>1. {@link LogCallback}: By default this class redirects FFmpeg output to Logcat. As another
|
||||
* option, it is possible not to print messages to Logcat and pass them to a {@link LogCallback}
|
||||
* function. This function can decide whether to print these logs, show them inside another
|
||||
* container or ignore them.
|
||||
* <p>1. {@link LogCallback}: This class redirects FFmpeg/FFprobe output to Logcat by default. As
|
||||
* an alternative, it is possible not to print messages to Logcat and pass them to a
|
||||
* {@link LogCallback} function. This function can decide whether to print these logs, show them
|
||||
* inside another container or ignore them.
|
||||
*
|
||||
* <p>2. {@link #setLogLevel(Level)}/{@link #getLogLevel()}: Use this methods to see/control FFmpeg
|
||||
* log severity.
|
||||
* <p>2. {@link #setLogLevel(Level)}/{@link #getLogLevel()}: Use this methods to set/get
|
||||
* FFmpeg/FFprobe log severity.
|
||||
*
|
||||
* <p>3. {@link StatisticsCallback}: It is possible to receive statistics about ongoing operation by
|
||||
* defining a {@link StatisticsCallback} function or by calling {@link #getLastReceivedStatistics()}
|
||||
* method.
|
||||
* <p>3. {@link StatisticsCallback}: It is possible to receive statistics about an ongoing
|
||||
* operation by defining a {@link StatisticsCallback} function or by calling
|
||||
* {@link #getLastReceivedStatistics()} method.
|
||||
*
|
||||
* <p>4. Font configuration: It is possible to register custom fonts with
|
||||
* {@link #setFontconfigConfigurationPath(String)} and
|
||||
* {@link #setFontDirectory(Context, String, Map)} methods.
|
||||
*
|
||||
* <p>PS: This class is introduced in v2.1 as an enhanced version of older <code>Log</code> class.
|
||||
*
|
||||
* @author Taner Sener
|
||||
* @since v2.1
|
||||
*/
|
||||
public class Config {
|
||||
|
||||
public static final int RETURN_CODE_SUCCESS = 0;
|
||||
|
||||
public static final int RETURN_CODE_CANCEL = 255;
|
||||
|
||||
private static int lastReturnCode = 0;
|
||||
|
||||
/**
|
||||
* Defines tag used for logging.
|
||||
*/
|
||||
@@ -75,10 +76,6 @@ public class Config {
|
||||
|
||||
private static Statistics lastReceivedStatistics;
|
||||
|
||||
private static final AtomicReference<StringBuffer> systemCommandOutputReference;
|
||||
|
||||
private static boolean runningSystemCommand;
|
||||
|
||||
private static int lastCreatedPipeIndex;
|
||||
|
||||
static {
|
||||
@@ -105,6 +102,7 @@ public class Config {
|
||||
/* ALL MOBILE-FFMPEG LIBRARIES LOADED AT STARTUP */
|
||||
Abi.class.getName();
|
||||
FFmpeg.class.getName();
|
||||
FFprobe.class.getName();
|
||||
|
||||
/*
|
||||
* NEON supported arm-v7a library has a different name
|
||||
@@ -140,12 +138,8 @@ public class Config {
|
||||
|
||||
lastReceivedStatistics = new Statistics();
|
||||
|
||||
Config.enableRedirection();
|
||||
enableRedirection();
|
||||
|
||||
systemCommandOutputReference = new AtomicReference<>();
|
||||
systemCommandOutputReference.set(new StringBuffer());
|
||||
|
||||
runningSystemCommand = false;
|
||||
lastCreatedPipeIndex = 0;
|
||||
}
|
||||
|
||||
@@ -157,14 +151,15 @@ public class Config {
|
||||
|
||||
/**
|
||||
* <p>Enables log and statistics redirection.
|
||||
* <p>When redirection is not enabled FFmpeg logs are printed to stderr. By enabling redirection, they are routed
|
||||
* to Logcat and can be routed further to a callback function.
|
||||
* <p>Statistics redirection behaviour is similar. Statistics are not printed at all if redirection is not enabled.
|
||||
* If it is enabled then it is possible to define a statistics callback function but if you don't, they are not
|
||||
* printed anywhere and only saved as <code>lastReceivedStatistics</code> data which can be polled with
|
||||
* <p>When redirection is not enabled FFmpeg/FFprobe logs are printed to stderr. By enabling
|
||||
* redirection, they are routed to Logcat and can be routed further to a callback function.
|
||||
* <p>Statistics redirection behaviour is similar. Statistics are not printed at all if
|
||||
* redirection is not enabled. If it is enabled then it is possible to define a statistics
|
||||
* callback function but if you don't, they are not printed anywhere and only saved as
|
||||
* <code>lastReceivedStatistics</code> data which can be polled with
|
||||
* {@link #getLastReceivedStatistics()}.
|
||||
* <p>Note that redirection is enabled by default. If you do not want to use its functionality please use
|
||||
* {@link #disableRedirection()} to disable it.
|
||||
* <p>Note that redirection is enabled by default. If you do not want to use its functionality
|
||||
* please use {@link #disableRedirection()} to disable it.
|
||||
*/
|
||||
public static void enableRedirection() {
|
||||
enableNativeRedirection();
|
||||
@@ -199,7 +194,7 @@ public class Config {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets a callback function to redirect FFmpeg logs.
|
||||
* <p>Sets a callback function to redirect FFmpeg/FFprobe logs.
|
||||
*
|
||||
* @param newLogCallback new log callback function or NULL to disable a previously defined callback
|
||||
*/
|
||||
@@ -226,16 +221,8 @@ public class Config {
|
||||
final Level level = Level.from(levelValue);
|
||||
final String text = new String(logMessage);
|
||||
|
||||
if (runningSystemCommand) {
|
||||
|
||||
// REDIRECT SYSTEM OUTPUT
|
||||
if (activeLogLevel != Level.AV_LOG_QUIET && levelValue <= activeLogLevel.getValue()) {
|
||||
systemCommandOutputReference.get().append(text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeLogLevel == Level.AV_LOG_QUIET || levelValue > activeLogLevel.getValue()) {
|
||||
// AV_LOG_STDERR logs are always redirected
|
||||
if ((activeLogLevel == Level.AV_LOG_QUIET && levelValue != Level.AV_LOG_STDERR.getValue()) || levelValue > activeLogLevel.getValue()) {
|
||||
// LOG NEITHER PRINTED NOR FORWARDED
|
||||
return;
|
||||
}
|
||||
@@ -257,6 +244,7 @@ public class Config {
|
||||
android.util.Log.d(TAG, text);
|
||||
}
|
||||
break;
|
||||
case AV_LOG_STDERR:
|
||||
case AV_LOG_VERBOSE: {
|
||||
android.util.Log.v(TAG, text);
|
||||
}
|
||||
@@ -332,7 +320,7 @@ public class Config {
|
||||
* @return zero on success, non-zero on error
|
||||
*/
|
||||
public static int setFontconfigConfigurationPath(final String path) {
|
||||
return Config.setNativeEnvironmentVariable("FONTCONFIG_PATH", path);
|
||||
return setNativeEnvironmentVariable("FONTCONFIG_PATH", path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,69 +466,6 @@ public class Config {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes system command. System command is not logged to output.
|
||||
*
|
||||
* @param arguments command arguments
|
||||
* @param commandOutputEndPatternList list of patterns which will indicate that operation has ended
|
||||
* @param successPattern success pattern
|
||||
* @param timeout execution timeout
|
||||
* @return return code
|
||||
*/
|
||||
static int systemExecute(final String[] arguments, final List<String> commandOutputEndPatternList, final String successPattern, final long timeout) {
|
||||
if (successPattern != null) {
|
||||
commandOutputEndPatternList.add(successPattern);
|
||||
}
|
||||
systemCommandOutputReference.set(new StringBuffer());
|
||||
runningSystemCommand = true;
|
||||
|
||||
int rc = Config.nativeExecute(arguments);
|
||||
|
||||
long totalWaitTime = 0;
|
||||
|
||||
try {
|
||||
while (!systemCommandOutputContainsPattern(commandOutputEndPatternList) && (totalWaitTime < timeout)) {
|
||||
synchronized (systemCommandOutputReference) {
|
||||
systemCommandOutputReference.wait(20);
|
||||
}
|
||||
totalWaitTime += 20;
|
||||
}
|
||||
} catch (final InterruptedException e) {
|
||||
Log.w(TAG, "systemExecute operation interrupted.", e);
|
||||
}
|
||||
|
||||
runningSystemCommand = false;
|
||||
|
||||
nativeCancel();
|
||||
|
||||
StringBuffer stringBuffer = systemCommandOutputReference.get();
|
||||
if ((successPattern != null) && (stringBuffer != null) && stringBuffer.toString().contains(successPattern)) {
|
||||
return 0;
|
||||
} else {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean systemCommandOutputContainsPattern(final List<String> patternList) {
|
||||
String string = systemCommandOutputReference.get().toString();
|
||||
for (String pattern : patternList) {
|
||||
if (string.contains(pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns output of last executed system command.
|
||||
*
|
||||
* @return output of last executed system command
|
||||
*/
|
||||
static String getSystemCommandOutput() {
|
||||
return systemCommandOutputReference.get().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of camera ids supported.
|
||||
*
|
||||
@@ -557,6 +482,119 @@ public class Config {
|
||||
return detectedCameraIdList;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns FFmpeg version bundled within the library.
|
||||
*
|
||||
* @return FFmpeg version
|
||||
*/
|
||||
public static String getFFmpegVersion() {
|
||||
return getNativeFFmpegVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns MobileFFmpeg library version.
|
||||
*
|
||||
* @return MobileFFmpeg version
|
||||
*/
|
||||
public static String getVersion() {
|
||||
if (AbiDetect.isNativeLTSBuild()) {
|
||||
return String.format("%s-lts", getNativeVersion());
|
||||
} else {
|
||||
return getNativeVersion();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns whether MobileFFmpeg release is a long term release or not.
|
||||
*
|
||||
* @return YES or NO
|
||||
*/
|
||||
public static boolean isLTSBuild() {
|
||||
return AbiDetect.isNativeLTSBuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns MobileFFmpeg library build date.
|
||||
*
|
||||
* @return MobileFFmpeg library build date
|
||||
*/
|
||||
public static String getBuildDate() {
|
||||
return getNativeBuildDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns return code of last executed command.
|
||||
*
|
||||
* @return return code of last executed command
|
||||
* @since 3.0
|
||||
*/
|
||||
public static int getLastReturnCode() {
|
||||
return lastReturnCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns log output of last executed single FFmpeg/FFprobe command.
|
||||
*
|
||||
* <p>This method does not support executing multiple concurrent commands. If you execute
|
||||
* multiple commands at the same time, this method will return output from all executions.
|
||||
*
|
||||
* <p>Please note that disabling redirection using {@link Config#disableRedirection()} method
|
||||
* also disables this functionality.
|
||||
*
|
||||
* @return output of the last executed command
|
||||
* @since 3.0
|
||||
*/
|
||||
public static String getLastCommandOutput() {
|
||||
String nativeLastCommandOutput = getNativeLastCommandOutput();
|
||||
if (nativeLastCommandOutput != null) {
|
||||
|
||||
// REPLACING CH(13) WITH CH(10)
|
||||
nativeLastCommandOutput = nativeLastCommandOutput.replace('\r', '\n');
|
||||
}
|
||||
return nativeLastCommandOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Prints the output of the last executed FFmpeg/FFprobe command to the Logcat at the
|
||||
* specified priority.
|
||||
*
|
||||
* <p>This method does not support executing multiple concurrent commands. If you execute
|
||||
* multiple commands at the same time, this method will print output from all executions.
|
||||
*
|
||||
* @param logPriority one of {@link Log#VERBOSE}, {@link Log#DEBUG}, {@link Log#INFO},
|
||||
* {@link Log#WARN}, {@link Log#ERROR}, {@link Log#ASSERT}
|
||||
* @since 4.3
|
||||
*/
|
||||
public static void printLastCommandOutput(int logPriority) {
|
||||
final int LOGGER_ENTRY_MAX_LEN = 4 * 1000;
|
||||
|
||||
String buffer = getLastCommandOutput();
|
||||
do {
|
||||
if (buffer.length() <= LOGGER_ENTRY_MAX_LEN) {
|
||||
Log.println(logPriority, Config.TAG, buffer);
|
||||
buffer = "";
|
||||
} else {
|
||||
final int index = buffer.substring(0, LOGGER_ENTRY_MAX_LEN).lastIndexOf('\n');
|
||||
if (index < 0) {
|
||||
Log.println(logPriority, Config.TAG, buffer.substring(0, LOGGER_ENTRY_MAX_LEN));
|
||||
buffer = buffer.substring(LOGGER_ENTRY_MAX_LEN);
|
||||
} else {
|
||||
Log.println(logPriority, Config.TAG, buffer.substring(0, index));
|
||||
buffer = buffer.substring(index);
|
||||
}
|
||||
}
|
||||
} while (buffer.length() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates return code value for the last executed command.
|
||||
*
|
||||
* @param newLastReturnCode new last return code value
|
||||
*/
|
||||
static void setLastReturnCode(int newLastReturnCode) {
|
||||
lastReturnCode = newLastReturnCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Enables native redirection. Necessary for log and statistics callback functions.
|
||||
*/
|
||||
@@ -601,13 +639,21 @@ public class Config {
|
||||
* @param arguments FFmpeg command options/arguments as string array
|
||||
* @return zero on successful execution, 255 on user cancel and non-zero on error
|
||||
*/
|
||||
native static int nativeExecute(final String[] arguments);
|
||||
native static int nativeFFmpegExecute(final String[] arguments);
|
||||
|
||||
/**
|
||||
* <p>Cancels an ongoing operation natively. This function does not wait for termination to
|
||||
* complete and returns immediately.
|
||||
* <p>Cancels an ongoing FFmpeg operation natively. This function does not wait for termination
|
||||
* to complete and returns immediately.
|
||||
*/
|
||||
native static void nativeCancel();
|
||||
native static void nativeFFmpegCancel();
|
||||
|
||||
/**
|
||||
* <p>Synchronously executes FFprobe natively with arguments provided.
|
||||
*
|
||||
* @param arguments FFprobe command options/arguments as string array
|
||||
* @return zero on successful execution, 255 on user cancel and non-zero on error
|
||||
*/
|
||||
native static int nativeFFprobeExecute(final String[] arguments);
|
||||
|
||||
/**
|
||||
* <p>Creates natively a new named pipe to use in <code>FFmpeg</code> operations.
|
||||
@@ -633,12 +679,12 @@ public class Config {
|
||||
* @param variableValue environment variable value
|
||||
* @return zero on success, non-zero on error
|
||||
*/
|
||||
native static int setNativeEnvironmentVariable(final String variableName, final String variableValue);
|
||||
public native static int setNativeEnvironmentVariable(final String variableName, final String variableValue);
|
||||
|
||||
/**
|
||||
* <p>Returns log output of the last executed command natively.
|
||||
* <p>Returns log output of the last executed single command natively.
|
||||
*
|
||||
* @return output of the last executed command
|
||||
* @return output of the last executed single command
|
||||
*/
|
||||
native static String getNativeLastCommandOutput();
|
||||
|
||||
|
||||
@@ -19,18 +19,14 @@
|
||||
|
||||
package com.arthenica.mobileffmpeg;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* <p>Main class for FFmpeg operations. Provides {@link #execute(String...)} method to execute
|
||||
* FFmpeg commands.
|
||||
* <pre>
|
||||
* int rc = FFmpeg.execute("-i", "file1.mp4", "-c:v", "libxvid", "file1.avi");
|
||||
* int rc = FFmpeg.execute("-i file1.mp4 -c:v libxvid file1.avi");
|
||||
* Log.i(Config.TAG, String.format("Command execution %s.", (rc == 0?"completed successfully":"failed with rc=" + rc));
|
||||
* </pre>
|
||||
*
|
||||
@@ -39,16 +35,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*/
|
||||
public class FFmpeg {
|
||||
|
||||
public static final int RETURN_CODE_SUCCESS = 0;
|
||||
|
||||
public static final int RETURN_CODE_CANCEL = 255;
|
||||
|
||||
public static final int RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED = 300;
|
||||
|
||||
private static int lastReturnCode = 0;
|
||||
|
||||
private static final AtomicBoolean started = new AtomicBoolean(false);
|
||||
|
||||
static {
|
||||
AbiDetect.class.getName();
|
||||
Config.class.getName();
|
||||
@@ -60,28 +46,6 @@ public class FFmpeg {
|
||||
private FFmpeg() {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns FFmpeg version bundled within the library.
|
||||
*
|
||||
* @return FFmpeg version
|
||||
*/
|
||||
public static String getFFmpegVersion() {
|
||||
return Config.getNativeFFmpegVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns MobileFFmpeg library version.
|
||||
*
|
||||
* @return MobileFFmpeg version
|
||||
*/
|
||||
public static String getVersion() {
|
||||
if (AbiDetect.isNativeLTSBuild()) {
|
||||
return String.format("%s-lts", Config.getNativeVersion());
|
||||
} else {
|
||||
return Config.getNativeVersion();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Synchronously executes FFmpeg with arguments provided.
|
||||
*
|
||||
@@ -89,13 +53,9 @@ public class FFmpeg {
|
||||
* @return zero on successful execution, 255 on user cancel and non-zero on error
|
||||
*/
|
||||
public static int execute(final String[] arguments) {
|
||||
if (started.compareAndSet(false, true)) {
|
||||
lastReturnCode = Config.nativeExecute(arguments);
|
||||
started.compareAndSet(true, false);
|
||||
} else {
|
||||
Log.e(Config.TAG, "execute cancelled. Multiple executions not supported.");
|
||||
lastReturnCode = RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED;
|
||||
}
|
||||
final int lastReturnCode = Config.nativeFFmpegExecute(arguments);
|
||||
|
||||
Config.setLastReturnCode(lastReturnCode);
|
||||
|
||||
return lastReturnCode;
|
||||
}
|
||||
@@ -118,7 +78,8 @@ public class FFmpeg {
|
||||
|
||||
/**
|
||||
* <p>Synchronously executes FFmpeg command provided. Space character is used to split command
|
||||
* into arguments.
|
||||
* into arguments. You can use single and double quote characters to specify arguments inside
|
||||
* your command.
|
||||
*
|
||||
* @param command FFmpeg command
|
||||
* @return zero on successful execution, 255 on user cancel and non-zero on error
|
||||
@@ -132,89 +93,7 @@ public class FFmpeg {
|
||||
* returns immediately.
|
||||
*/
|
||||
public static void cancel() {
|
||||
Config.nativeCancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns return code of last executed command.
|
||||
*
|
||||
* @return return code of last executed command
|
||||
* @since 3.0
|
||||
*/
|
||||
public static int getLastReturnCode() {
|
||||
return lastReturnCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns log output of the last executed command. Please note that disabling redirection
|
||||
* using {@link Config#disableRedirection()} method also disables this functionality.
|
||||
*
|
||||
* @return output of the last executed command
|
||||
* @since 3.0
|
||||
*/
|
||||
public static String getLastCommandOutput() {
|
||||
String nativeLastCommandOutput = Config.getNativeLastCommandOutput();
|
||||
if (nativeLastCommandOutput != null) {
|
||||
|
||||
// REPLACING CH(13) WITH CH(10)
|
||||
nativeLastCommandOutput = nativeLastCommandOutput.replace('\r', '\n');
|
||||
}
|
||||
return nativeLastCommandOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns media information for given file.
|
||||
*
|
||||
* @param path path or uri of media file
|
||||
* @return media information
|
||||
* @since 3.0
|
||||
*/
|
||||
public static MediaInformation getMediaInformation(final String path) {
|
||||
return getMediaInformation(path, 10000L);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns media information for given file.
|
||||
*
|
||||
* @param path path or uri of media file
|
||||
* @param timeout complete timeout
|
||||
* @return media information
|
||||
* @since 3.0
|
||||
*/
|
||||
public static MediaInformation getMediaInformation(final String path, final Long timeout) {
|
||||
final int rc;
|
||||
if (started.compareAndSet(false, true)) {
|
||||
rc = Config.systemExecute(new String[]{"-v", "info", "-hide_banner", "-i", path}, new ArrayList<>(Arrays.asList("Press [q] to stop, [?] for help", "No such file or directory", "Input/output error", "Conversion failed", "HTTP error")), "At least one output file must be specified", timeout);
|
||||
started.compareAndSet(true, false);
|
||||
} else {
|
||||
Log.e(Config.TAG, "getMediaInformation cancelled. Multiple executions not supported.");
|
||||
rc = RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
return MediaInformationParser.from(Config.getSystemCommandOutput());
|
||||
} else {
|
||||
Log.i(Config.TAG, Config.getSystemCommandOutput());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns whether MobileFFmpeg release is a long term release or not.
|
||||
*
|
||||
* @return YES or NO
|
||||
*/
|
||||
public static boolean isLTSBuild() {
|
||||
return AbiDetect.isNativeLTSBuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns MobileFFmpeg library build date.
|
||||
*
|
||||
* @return MobileFFmpeg library build date
|
||||
*/
|
||||
public static String getBuildDate() {
|
||||
return Config.getNativeBuildDate();
|
||||
Config.nativeFFmpegCancel();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,32 +153,4 @@ public class FFmpeg {
|
||||
return argumentList.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Prints the output of the last executed command to the logcat at the specified priority.
|
||||
*
|
||||
* @param logPriority one of {@link Log#VERBOSE}, {@link Log#DEBUG}, {@link Log#INFO},
|
||||
* {@link Log#WARN}, {@link Log#ERROR}, {@link Log#ASSERT}
|
||||
* @since 4.3
|
||||
*/
|
||||
public static void printLastCommandOutput(int logPriority) {
|
||||
final int LOGGER_ENTRY_MAX_LEN = 4 * 1000;
|
||||
|
||||
String buffer = FFmpeg.getLastCommandOutput();
|
||||
do {
|
||||
if (buffer.length() <= LOGGER_ENTRY_MAX_LEN) {
|
||||
Log.println(logPriority, Config.TAG, buffer);
|
||||
buffer = "";
|
||||
} else {
|
||||
final int index = buffer.substring(0, LOGGER_ENTRY_MAX_LEN).lastIndexOf('\n');
|
||||
if (index < 0) {
|
||||
Log.println(logPriority, Config.TAG, buffer.substring(0, LOGGER_ENTRY_MAX_LEN));
|
||||
buffer = buffer.substring(LOGGER_ENTRY_MAX_LEN);
|
||||
} else {
|
||||
Log.println(logPriority, Config.TAG, buffer.substring(0, index));
|
||||
buffer = buffer.substring(index);
|
||||
}
|
||||
}
|
||||
} while (buffer.length() > 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.mobileffmpeg;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* <p>Main class for FFprobe operations. Provides {@link #execute(String...)} method to execute
|
||||
* FFprobe commands.
|
||||
* <pre>
|
||||
* int rc = FFprobe.execute("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4");
|
||||
* Log.i(Config.TAG, String.format("Command execution %s.", (rc == 0?"completed successfully":"failed with rc=" + rc));
|
||||
* </pre>
|
||||
*
|
||||
* @author Taner Sener
|
||||
* @since v4.3.1
|
||||
*/
|
||||
public class FFprobe {
|
||||
|
||||
static {
|
||||
AbiDetect.class.getName();
|
||||
Config.class.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor hidden.
|
||||
*/
|
||||
private FFprobe() {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Synchronously executes FFprobe with arguments provided.
|
||||
*
|
||||
* @param arguments FFprobe command options/arguments as string array
|
||||
* @return zero on successful execution, 255 on user cancel and non-zero on error
|
||||
*/
|
||||
public static int execute(final String[] arguments) {
|
||||
final int lastReturnCode = Config.nativeFFprobeExecute(arguments);
|
||||
|
||||
Config.setLastReturnCode(lastReturnCode);
|
||||
|
||||
return lastReturnCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Synchronously executes FFprobe command provided. Space character is used to split command
|
||||
* into arguments. You can use single and double quote characters to specify arguments inside
|
||||
* your command.
|
||||
*
|
||||
* @param command FFprobe command
|
||||
* @return zero on successful execution, 255 on user cancel and non-zero on error
|
||||
*/
|
||||
public static int execute(final String command) {
|
||||
return execute(FFmpeg.parseArguments(command));
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns media information for given file.
|
||||
*
|
||||
* <p>This method does not support executing multiple concurrent operations. If you execute
|
||||
* multiple operations (execute or getMediaInformation) at the same time, the response of this
|
||||
* method is not predictable.
|
||||
*
|
||||
* @param path path or uri of media file
|
||||
* @return media information
|
||||
* @since 3.0
|
||||
*/
|
||||
public static MediaInformation getMediaInformation(final String path) {
|
||||
final int rc = execute(new String[]{"-v", "info", "-hide_banner", "-i", path});
|
||||
|
||||
if (rc == 0) {
|
||||
return MediaInformationParser.from(Config.getLastCommandOutput());
|
||||
} else {
|
||||
Log.i(Config.TAG, Config.getLastCommandOutput());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns media information for given file.
|
||||
*
|
||||
* <p>This method does not support executing multiple concurrent operations. If you execute
|
||||
* multiple operations (execute or getMediaInformation) at the same time, the response of this
|
||||
* method is not predictable.
|
||||
*
|
||||
* @param path path or uri of media file
|
||||
* @param timeout complete timeout
|
||||
* @return media information
|
||||
* @since 3.0
|
||||
* @deprecated this method is deprecated since v4.3.1. You can still use this method but
|
||||
* <code>timeout</code> parameter is not effective anymore.
|
||||
*/
|
||||
public static MediaInformation getMediaInformation(final String path, final Long timeout) {
|
||||
return getMediaInformation(path);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,14 @@ package com.arthenica.mobileffmpeg;
|
||||
*/
|
||||
public enum Level {
|
||||
|
||||
/**
|
||||
* This log level is defined by MobileFFmpeg. It is used to specify logs printed to stderr by
|
||||
* ffmpeg. Logs that has this level are not filtered and always redirected.
|
||||
*
|
||||
* @since 4.3.1
|
||||
*/
|
||||
AV_LOG_STDERR(-16),
|
||||
|
||||
/**
|
||||
* Print no output.
|
||||
*/
|
||||
@@ -85,7 +93,9 @@ public enum Level {
|
||||
* @return enumeration defined by value
|
||||
*/
|
||||
public static Level from(final int value) {
|
||||
if (value == AV_LOG_QUIET.getValue()) {
|
||||
if (value == AV_LOG_STDERR.getValue()) {
|
||||
return AV_LOG_STDERR;
|
||||
} else if (value == AV_LOG_QUIET.getValue()) {
|
||||
return AV_LOG_QUIET;
|
||||
} else if (value == AV_LOG_PANIC.getValue()) {
|
||||
return AV_LOG_PANIC;
|
||||
|
||||
+10
-8
@@ -21,25 +21,27 @@ package com.arthenica.mobileffmpeg.util;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
|
||||
public class AsyncExecuteTask extends AsyncTask<String, Integer, Integer> {
|
||||
public class AsyncSingleFFmpegExecuteTask extends AsyncTask<String, Integer, Integer> {
|
||||
private final String command;
|
||||
private final SingleExecuteCallback singleExecuteCallback;
|
||||
|
||||
private final ExecuteCallback executeCallback;
|
||||
|
||||
public AsyncExecuteTask(final ExecuteCallback executeCallback) {
|
||||
this.executeCallback = executeCallback;
|
||||
public AsyncSingleFFmpegExecuteTask(final String command, final SingleExecuteCallback singleExecuteCallback) {
|
||||
this.command = command;
|
||||
this.singleExecuteCallback = singleExecuteCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(final String... arguments) {
|
||||
return FFmpeg.execute(arguments[0]);
|
||||
return FFmpeg.execute(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer rc) {
|
||||
if (executeCallback != null) {
|
||||
executeCallback.apply(rc, FFmpeg.getLastCommandOutput());
|
||||
if (singleExecuteCallback != null) {
|
||||
singleExecuteCallback.apply(rc, Config.getLastCommandOutput());
|
||||
}
|
||||
}
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.mobileffmpeg.util;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFprobe;
|
||||
|
||||
public class AsyncSingleFFprobeExecuteTask extends AsyncTask<String, Integer, Integer> {
|
||||
private final String command;
|
||||
private final SingleExecuteCallback singleExecuteCallback;
|
||||
|
||||
public AsyncSingleFFprobeExecuteTask(final String command, final SingleExecuteCallback singleExecuteCallback) {
|
||||
this.command = command;
|
||||
this.singleExecuteCallback = singleExecuteCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(final String... arguments) {
|
||||
return FFprobe.execute(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer rc) {
|
||||
if (singleExecuteCallback != null) {
|
||||
singleExecuteCallback.apply(rc, Config.getLastCommandOutput());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+10
-9
@@ -21,26 +21,27 @@ package com.arthenica.mobileffmpeg.util;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
import com.arthenica.mobileffmpeg.FFprobe;
|
||||
import com.arthenica.mobileffmpeg.MediaInformation;
|
||||
|
||||
public class AsyncGetMediaInformationTask extends AsyncTask<String, MediaInformation, MediaInformation> {
|
||||
public class AsyncSingleGetMediaInformationTask extends AsyncTask<String, MediaInformation, MediaInformation> {
|
||||
private final String path;
|
||||
private final SingleGetMediaInformationCallback singleGetMediaInformationCallback;
|
||||
|
||||
private final GetMediaInformationCallback getMediaInformationCallback;
|
||||
|
||||
public AsyncGetMediaInformationTask(final GetMediaInformationCallback getMediaInformationCallback) {
|
||||
this.getMediaInformationCallback = getMediaInformationCallback;
|
||||
public AsyncSingleGetMediaInformationTask(final String path, final SingleGetMediaInformationCallback singleGetMediaInformationCallback) {
|
||||
this.path = path;
|
||||
this.singleGetMediaInformationCallback = singleGetMediaInformationCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MediaInformation doInBackground(final String... arguments) {
|
||||
return FFmpeg.getMediaInformation(arguments[0]);
|
||||
return FFprobe.getMediaInformation(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final MediaInformation mediaInformation) {
|
||||
if (getMediaInformationCallback != null) {
|
||||
getMediaInformationCallback.apply(mediaInformation);
|
||||
if (singleGetMediaInformationCallback != null) {
|
||||
singleGetMediaInformationCallback.apply(mediaInformation);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,13 +20,13 @@
|
||||
package com.arthenica.mobileffmpeg.util;
|
||||
|
||||
/**
|
||||
* <p>Represents a callback function to receive execution result.
|
||||
* <p>Represents a callback function to receive a single execution result.
|
||||
*
|
||||
* @author Taner Sener
|
||||
* @since v2.1
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ExecuteCallback {
|
||||
public interface SingleExecuteCallback {
|
||||
|
||||
void apply(int returnCode, String executeOutput);
|
||||
|
||||
+2
-2
@@ -22,12 +22,12 @@ package com.arthenica.mobileffmpeg.util;
|
||||
import com.arthenica.mobileffmpeg.MediaInformation;
|
||||
|
||||
/**
|
||||
* <p>Represents a callback function to receive getMediaInformation result.
|
||||
* <p>Represents a callback function to receive a single getMediaInformation result.
|
||||
*
|
||||
* @author Taner Sener
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface GetMediaInformationCallback {
|
||||
public interface SingleGetMediaInformationCallback {
|
||||
|
||||
void apply(MediaInformation mediaInformation);
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
</resources>
|
||||
@@ -1,11 +0,0 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -19,8 +19,7 @@
|
||||
|
||||
package com.arthenica.mobileffmpeg;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -138,7 +137,7 @@ public class ConfigTest {
|
||||
Collections.sort(enabledList);
|
||||
|
||||
Assert.assertNotNull(enabledList);
|
||||
Assert.assertTrue(enabledList.size() == 1);
|
||||
Assert.assertEquals(1, enabledList.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,8 +22,7 @@ package com.arthenica.mobileffmpeg;
|
||||
import com.arthenica.mobileffmpeg.util.Pair;
|
||||
import com.arthenica.mobileffmpeg.util.Trio;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MediaInformationTest {
|
||||
@@ -82,16 +81,16 @@ public class MediaInformationTest {
|
||||
|
||||
@Test
|
||||
public void parseVideoStreamDisplayAspectRatio() {
|
||||
Assert.assertEquals(null, MediaInformationParser.parseVideoStreamDisplayAspectRatio(""));
|
||||
Assert.assertEquals(null, MediaInformationParser.parseVideoStreamDisplayAspectRatio("544x184"));
|
||||
Assert.assertNull(MediaInformationParser.parseVideoStreamDisplayAspectRatio(""));
|
||||
Assert.assertNull(MediaInformationParser.parseVideoStreamDisplayAspectRatio("544x184"));
|
||||
Assert.assertEquals("640:427", MediaInformationParser.parseVideoStreamDisplayAspectRatio("2560x1708 [SAR 1:1 DAR 640:427]"));
|
||||
Assert.assertEquals("8:9", MediaInformationParser.parseVideoStreamDisplayAspectRatio("3840x4320 [SAR 1:1 DAR 8:9]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseVideoStreamSampleAspectRatio() {
|
||||
Assert.assertEquals(null, MediaInformationParser.parseVideoStreamSampleAspectRatio(""));
|
||||
Assert.assertEquals(null, MediaInformationParser.parseVideoStreamSampleAspectRatio("544x184"));
|
||||
Assert.assertNull(MediaInformationParser.parseVideoStreamSampleAspectRatio(""));
|
||||
Assert.assertNull(MediaInformationParser.parseVideoStreamSampleAspectRatio("544x184"));
|
||||
Assert.assertEquals("1:1", MediaInformationParser.parseVideoStreamSampleAspectRatio("2560x1708 [SAR 1:1 DAR 640:427]"));
|
||||
Assert.assertEquals("1:1", MediaInformationParser.parseVideoStreamSampleAspectRatio("3840x4320 [SAR 1:1 DAR 8:9]"));
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.2'
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -44,7 +44,13 @@ include $(BUILD_SHARED_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_ARM_MODE := $(MY_ARM_MODE)
|
||||
LOCAL_MODULE := mobileffmpeg
|
||||
LOCAL_SRC_FILES := $(MY_PATH)/mobileffmpeg.c $(MY_PATH)/fftools_cmdutils.c $(MY_PATH)/fftools_ffmpeg.c $(MY_PATH)/fftools_ffmpeg_opt.c $(MY_PATH)/fftools_ffmpeg_hw.c $(MY_PATH)/fftools_ffmpeg_filter.c
|
||||
ifeq ($(TARGET_PLATFORM),android-16)
|
||||
LOCAL_SRC_FILES := $(MY_PATH)/mobileffmpeg.c $(MY_PATH)/mobileffprobe.c $(MY_PATH)/android_lts_support.c $(MY_PATH)/mobileffmpeg_exception.c $(MY_PATH)/fftools_cmdutils.c $(MY_PATH)/fftools_ffmpeg.c $(MY_PATH)/fftools_ffprobe.c $(MY_PATH)/fftools_ffmpeg_opt.c $(MY_PATH)/fftools_ffmpeg_hw.c $(MY_PATH)/fftools_ffmpeg_filter.c
|
||||
else ifeq ($(TARGET_PLATFORM),android-17)
|
||||
LOCAL_SRC_FILES := $(MY_PATH)/mobileffmpeg.c $(MY_PATH)/mobileffprobe.c $(MY_PATH)/android_lts_support.c $(MY_PATH)/mobileffmpeg_exception.c $(MY_PATH)/fftools_cmdutils.c $(MY_PATH)/fftools_ffmpeg.c $(MY_PATH)/fftools_ffprobe.c $(MY_PATH)/fftools_ffmpeg_opt.c $(MY_PATH)/fftools_ffmpeg_hw.c $(MY_PATH)/fftools_ffmpeg_filter.c
|
||||
else
|
||||
LOCAL_SRC_FILES := $(MY_PATH)/mobileffmpeg.c $(MY_PATH)/mobileffprobe.c $(MY_PATH)/mobileffmpeg_exception.c $(MY_PATH)/fftools_cmdutils.c $(MY_PATH)/fftools_ffmpeg.c $(MY_PATH)/fftools_ffprobe.c $(MY_PATH)/fftools_ffmpeg_opt.c $(MY_PATH)/fftools_ffmpeg_hw.c $(MY_PATH)/fftools_ffmpeg_filter.c
|
||||
endif
|
||||
LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -Wno-switch -Wno-sign-compare -I${LOCAL_PATH}/../../prebuilt/android-$(TARGET_ARCH)/ffmpeg/include
|
||||
LOCAL_LDLIBS := -llog -lz -landroid
|
||||
LOCAL_SHARED_LIBRARIES := c++_shared libavfilter libavformat libavcodec libavutil libswresample libavdevice libswscale
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
/build
|
||||
/.idea/
|
||||
/local.properties
|
||||
@@ -9,13 +9,13 @@ android {
|
||||
keyPassword 'android'
|
||||
}
|
||||
}
|
||||
compileSdkVersion 28
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "com.arthenica.mobileffmpeg.test"
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 28
|
||||
versionCode 240430
|
||||
versionName "4.3"
|
||||
targetSdkVersion 29
|
||||
versionCode 240431
|
||||
versionName "4.3.1"
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
@@ -51,12 +51,8 @@ android.applicationVariants.all { variant ->
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.arthenica:mobile-ffmpeg-full:4.3'
|
||||
// implementation project(':app')
|
||||
testImplementation 'junit:junit:4.12'
|
||||
implementation 'com.android.support:support-v4:28.0.0'
|
||||
implementation 'com.android.support:design:28.0.0'
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
implementation 'com.arthenica:mobile-ffmpeg-full:4.3.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,5 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Taner Sener
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.mobileffmpeg.test;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.arthenica.mobileffmpeg.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,7 @@
|
||||
android:largeHeap="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<activity android:name="com.arthenica.mobileffmpeg.test.MainActivity"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name="com.arthenica.mobileffmpeg.test.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
+39
-51
@@ -21,93 +21,81 @@ package com.arthenica.mobileffmpeg.test;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
import com.arthenica.mobileffmpeg.LogCallback;
|
||||
import com.arthenica.mobileffmpeg.LogMessage;
|
||||
import com.arthenica.mobileffmpeg.util.ExecuteCallback;
|
||||
import com.arthenica.mobileffmpeg.util.DialogUtil;
|
||||
import com.arthenica.mobileffmpeg.util.SingleExecuteCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.Config.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.test.MainActivity.TAG;
|
||||
|
||||
public class AudioTabFragment extends Fragment implements AdapterView.OnItemSelectedListener {
|
||||
|
||||
private MainActivity mainActivity;
|
||||
private AlertDialog progressDialog;
|
||||
private Button encodeButton;
|
||||
private TextView outputText;
|
||||
private String selectedCodec;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_audio_tab, container, false);
|
||||
public AudioTabFragment() {
|
||||
super(R.layout.fragment_audio_tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getView() != null) {
|
||||
Spinner audioCodecSpinner = getView().findViewById(R.id.audioCodecSpinner);
|
||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mainActivity,
|
||||
R.array.audio_codec, R.layout.spinner_item);
|
||||
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
|
||||
audioCodecSpinner.setAdapter(adapter);
|
||||
audioCodecSpinner.setOnItemSelectedListener(this);
|
||||
Spinner audioCodecSpinner = view.findViewById(R.id.audioCodecSpinner);
|
||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(requireContext(),
|
||||
R.array.audio_codec, R.layout.spinner_item);
|
||||
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
|
||||
audioCodecSpinner.setAdapter(adapter);
|
||||
audioCodecSpinner.setOnItemSelectedListener(this);
|
||||
|
||||
encodeButton = getView().findViewById(R.id.encodeButton);
|
||||
encodeButton.setOnClickListener(new View.OnClickListener() {
|
||||
encodeButton = view.findViewById(R.id.encodeButton);
|
||||
encodeButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
encodeAudio();
|
||||
// encodeChromaprint();
|
||||
}
|
||||
});
|
||||
encodeButton.setEnabled(false);
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
encodeAudio();
|
||||
// encodeChromaprint();
|
||||
}
|
||||
});
|
||||
encodeButton.setEnabled(false);
|
||||
|
||||
outputText = getView().findViewById(R.id.outputText);
|
||||
outputText.setMovementMethod(new ScrollingMovementMethod());
|
||||
}
|
||||
outputText = view.findViewById(R.id.outputText);
|
||||
outputText.setMovementMethod(new ScrollingMovementMethod());
|
||||
|
||||
progressDialog = mainActivity.createProgressDialog("Encoding audio");
|
||||
progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding audio");
|
||||
|
||||
selectedCodec = getResources().getStringArray(R.array.audio_codec)[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
setActive();
|
||||
}
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setActive();
|
||||
}
|
||||
|
||||
public void setMainActivity(MainActivity mainActivity) {
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
public static AudioTabFragment newInstance(final MainActivity mainActivity) {
|
||||
final AudioTabFragment fragment = new AudioTabFragment();
|
||||
fragment.setMainActivity(mainActivity);
|
||||
return fragment;
|
||||
public static AudioTabFragment newInstance() {
|
||||
return new AudioTabFragment();
|
||||
}
|
||||
|
||||
public void enableLogCallback() {
|
||||
@@ -159,7 +147,7 @@ public class AudioTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
|
||||
android.util.Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'", ffmpegCommand));
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
@@ -172,10 +160,10 @@ public class AudioTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
@Override
|
||||
public Object call() {
|
||||
if (returnCode == RETURN_CODE_SUCCESS) {
|
||||
Popup.show(mainActivity, "Encode completed successfully.");
|
||||
Popup.show(requireContext(), "Encode completed successfully.");
|
||||
android.util.Log.d(TAG, "Encode completed successfully.");
|
||||
} else {
|
||||
Popup.show(mainActivity, "Encode failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Encode failed. Please check log for the details.");
|
||||
android.util.Log.d(TAG, String.format("Encode failed with rc=%d", returnCode));
|
||||
}
|
||||
|
||||
@@ -218,7 +206,7 @@ public class AudioTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
android.util.Log.d(TAG, "AUDIO sample created");
|
||||
} else {
|
||||
android.util.Log.d(TAG, String.format("Creating AUDIO sample failed with rc=%d", result));
|
||||
Popup.show(mainActivity, "Creating AUDIO sample failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Creating AUDIO sample failed. Please check log for the details.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,11 +248,11 @@ public class AudioTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
}
|
||||
|
||||
final String audio = "audio." + extension;
|
||||
return new File(mainActivity.getFilesDir(), audio);
|
||||
return new File(requireContext().getFilesDir(), audio);
|
||||
}
|
||||
|
||||
public File getAudioSampleFile() {
|
||||
return new File(mainActivity.getFilesDir(), "audio-sample.wav");
|
||||
return new File(requireContext().getFilesDir(), "audio-sample.wav");
|
||||
}
|
||||
|
||||
public void setActive() {
|
||||
@@ -272,7 +260,7 @@ public class AudioTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
disableLogCallback();
|
||||
createAudioSample();
|
||||
enableLogCallback();
|
||||
Popup.show(mainActivity, Tooltip.AUDIO_TEST_TOOLTIP_TEXT);
|
||||
Popup.show(requireContext(), Tooltip.AUDIO_TEST_TOOLTIP_TEXT);
|
||||
}
|
||||
|
||||
public void appendLog(final String logMessage) {
|
||||
|
||||
+46
-70
@@ -20,84 +20,72 @@
|
||||
package com.arthenica.mobileffmpeg.test;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.view.LayoutInflater;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
import com.arthenica.mobileffmpeg.FFprobe;
|
||||
import com.arthenica.mobileffmpeg.LogCallback;
|
||||
import com.arthenica.mobileffmpeg.LogMessage;
|
||||
import com.arthenica.mobileffmpeg.util.ExecuteCallback;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class CommandTabFragment extends Fragment {
|
||||
|
||||
private MainActivity mainActivity;
|
||||
private EditText commandText;
|
||||
private TextView outputText;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_command_tab, container, false);
|
||||
public CommandTabFragment() {
|
||||
super(R.layout.fragment_command_tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getView() != null) {
|
||||
commandText = getView().findViewById(R.id.commandText);
|
||||
commandText = view.findViewById(R.id.commandText);
|
||||
|
||||
View runButton = getView().findViewById(R.id.runButton);
|
||||
runButton.setOnClickListener(new View.OnClickListener() {
|
||||
View runFFmpegButton = view.findViewById(R.id.runFFmpegButton);
|
||||
runFFmpegButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
runFFmpeg();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
runFFmpeg();
|
||||
}
|
||||
});
|
||||
|
||||
View runAsyncButton = getView().findViewById(R.id.runAsyncButton);
|
||||
runAsyncButton.setOnClickListener(new View.OnClickListener() {
|
||||
View runFFprobeButton = view.findViewById(R.id.runFFprobeButton);
|
||||
runFFprobeButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
runFFmpegAsync();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
runFFprobe();
|
||||
}
|
||||
});
|
||||
|
||||
outputText = getView().findViewById(R.id.outputText);
|
||||
outputText.setMovementMethod(new ScrollingMovementMethod());
|
||||
}
|
||||
outputText = view.findViewById(R.id.outputText);
|
||||
outputText.setMovementMethod(new ScrollingMovementMethod());
|
||||
|
||||
android.util.Log.d(MainActivity.TAG, "Last command output was: " + FFmpeg.getLastCommandOutput());
|
||||
Log.d(MainActivity.TAG, "Last command output was: " + Config.getLastCommandOutput());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
setActive();
|
||||
}
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setActive();
|
||||
}
|
||||
|
||||
public void setMainActivity(MainActivity mainActivity) {
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
public static CommandTabFragment newInstance(final MainActivity mainActivity) {
|
||||
final CommandTabFragment fragment = new CommandTabFragment();
|
||||
fragment.setMainActivity(mainActivity);
|
||||
return fragment;
|
||||
public static CommandTabFragment newInstance() {
|
||||
return new CommandTabFragment();
|
||||
}
|
||||
|
||||
public void enableLogCallback() {
|
||||
@@ -122,9 +110,9 @@ public class CommandTabFragment extends Fragment {
|
||||
public void runFFmpeg() {
|
||||
clearLog();
|
||||
|
||||
final String ffmpegCommand = String.format("-hide_banner %s", commandText.getText().toString());
|
||||
final String ffmpegCommand = String.format("%s", commandText.getText().toString());
|
||||
|
||||
android.util.Log.d(MainActivity.TAG, "Testing COMMAND synchronously.");
|
||||
android.util.Log.d(MainActivity.TAG, "Testing FFmpeg COMMAND synchronously.");
|
||||
|
||||
android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process started with arguments\n\'%s\'", ffmpegCommand));
|
||||
|
||||
@@ -133,44 +121,32 @@ public class CommandTabFragment extends Fragment {
|
||||
android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process exited with rc %d", result));
|
||||
|
||||
if (result != 0) {
|
||||
Popup.show(mainActivity, "Command failed. Please check output for the details.");
|
||||
Popup.show(requireContext(), "Command failed. Please check output for the details.");
|
||||
}
|
||||
}
|
||||
|
||||
public void runFFmpegAsync() {
|
||||
public void runFFprobe() {
|
||||
clearLog();
|
||||
|
||||
final String ffmpegCommand = String.format("-hide_banner %s", commandText.getText().toString());
|
||||
final String ffprobeCommand = String.format("%s", commandText.getText().toString());
|
||||
|
||||
android.util.Log.d(MainActivity.TAG, "Testing COMMAND asynchronously.");
|
||||
android.util.Log.d(MainActivity.TAG, "Testing FFprobe COMMAND synchronously.");
|
||||
|
||||
android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process started with arguments\n\'%s\'", ffmpegCommand));
|
||||
android.util.Log.d(MainActivity.TAG, String.format("FFprobe process started with arguments\n\'%s\'", ffprobeCommand));
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
int result = FFprobe.execute(ffprobeCommand);
|
||||
|
||||
@Override
|
||||
public void apply(int result, final String commandOutput) {
|
||||
android.util.Log.d(MainActivity.TAG, String.format("FFprobe process exited with rc %d", result));
|
||||
|
||||
android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process exited with rc %d", result));
|
||||
|
||||
if (result != 0) {
|
||||
MainActivity.addUIAction(new Callable() {
|
||||
@Override
|
||||
public Object call() {
|
||||
Popup.show(mainActivity, "Command failed. Please check output for the details.");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}, ffmpegCommand);
|
||||
if (result != 0) {
|
||||
Popup.show(requireContext(), "Command failed. Please check output for the details.");
|
||||
}
|
||||
}
|
||||
|
||||
public void setActive() {
|
||||
android.util.Log.i(MainActivity.TAG, "Command Tab Activated");
|
||||
private void setActive() {
|
||||
Log.i(MainActivity.TAG, "Command Tab Activated");
|
||||
enableLogCallback();
|
||||
Popup.show(mainActivity, Tooltip.COMMAND_TEST_TOOLTIP_TEXT);
|
||||
Popup.show(requireContext(), Tooltip.COMMAND_TEST_TOOLTIP_TEXT);
|
||||
}
|
||||
|
||||
public void appendLog(final String logMessage) {
|
||||
|
||||
+26
-38
@@ -20,18 +20,18 @@
|
||||
package com.arthenica.mobileffmpeg.test;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.method.ScrollingMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
import com.arthenica.mobileffmpeg.FFprobe;
|
||||
import com.arthenica.mobileffmpeg.LogCallback;
|
||||
import com.arthenica.mobileffmpeg.LogMessage;
|
||||
import com.arthenica.mobileffmpeg.MediaInformation;
|
||||
@@ -45,52 +45,40 @@ public class HttpsTabFragment extends Fragment {
|
||||
|
||||
public static final String HTTPS_TEST_DEFAULT_URL = "https://download.blender.org/peach/trailer/trailer_1080p.ogg";
|
||||
|
||||
private MainActivity mainActivity;
|
||||
private EditText urlText;
|
||||
private TextView outputText;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_https_tab, container, false);
|
||||
public HttpsTabFragment() {
|
||||
super(R.layout.fragment_https_tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getView() != null) {
|
||||
urlText = getView().findViewById(R.id.urlText);
|
||||
urlText = view.findViewById(R.id.urlText);
|
||||
|
||||
View getInfoButton = getView().findViewById(R.id.getInfoButton);
|
||||
getInfoButton.setOnClickListener(new View.OnClickListener() {
|
||||
View getInfoButton = view.findViewById(R.id.getInfoButton);
|
||||
getInfoButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
getInfo();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
getInfo();
|
||||
}
|
||||
});
|
||||
|
||||
outputText = getView().findViewById(R.id.outputText);
|
||||
outputText.setMovementMethod(new ScrollingMovementMethod());
|
||||
}
|
||||
outputText = view.findViewById(R.id.outputText);
|
||||
outputText.setMovementMethod(new ScrollingMovementMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
setActive();
|
||||
}
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setActive();
|
||||
}
|
||||
|
||||
public void setMainActivity(MainActivity mainActivity) {
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
public static HttpsTabFragment newInstance(final MainActivity mainActivity) {
|
||||
final HttpsTabFragment fragment = new HttpsTabFragment();
|
||||
fragment.setMainActivity(mainActivity);
|
||||
return fragment;
|
||||
public static HttpsTabFragment newInstance() {
|
||||
return new HttpsTabFragment();
|
||||
}
|
||||
|
||||
public void enableLogCallback() {
|
||||
@@ -123,7 +111,7 @@ public class HttpsTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
// HTTPS COMMAND ARGUMENTS
|
||||
MediaInformation information = FFmpeg.getMediaInformation(testUrl);
|
||||
MediaInformation information = FFprobe.getMediaInformation(testUrl);
|
||||
if (information == null) {
|
||||
appendLog("Get media information failed\n");
|
||||
} else {
|
||||
@@ -220,9 +208,9 @@ public class HttpsTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void setActive() {
|
||||
android.util.Log.i(MainActivity.TAG, "Https Tab Activated");
|
||||
Log.i(MainActivity.TAG, "Https Tab Activated");
|
||||
enableLogCallback();
|
||||
Popup.show(mainActivity, Tooltip.HTTPS_TEST_TOOLTIP_TEXT);
|
||||
Popup.show(requireContext(), Tooltip.HTTPS_TEST_TOOLTIP_TEXT);
|
||||
}
|
||||
|
||||
public void appendLog(final String logMessage) {
|
||||
|
||||
@@ -20,34 +20,25 @@
|
||||
package com.arthenica.mobileffmpeg.test;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.ActionBar;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.view.PagerTabStrip;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.viewpager.widget.PagerTabStrip;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.util.AsyncExecuteTask;
|
||||
import com.arthenica.mobileffmpeg.util.ExecuteCallback;
|
||||
import com.arthenica.mobileffmpeg.util.AsyncSingleFFmpegExecuteTask;
|
||||
import com.arthenica.mobileffmpeg.util.ResourcesUtil;
|
||||
import com.arthenica.mobileffmpeg.util.SingleExecuteCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
@@ -96,12 +87,6 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
android.support.v7.app.ActionBar supportActionBar = getSupportActionBar();
|
||||
if (supportActionBar != null) {
|
||||
supportActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
|
||||
supportActionBar.setCustomView(R.layout.action_bar);
|
||||
}
|
||||
|
||||
PagerTabStrip pagerTabStrip = findViewById(R.id.pagerTabStrip);
|
||||
if (pagerTabStrip != null) {
|
||||
pagerTabStrip.setDrawFullUnderline(false);
|
||||
@@ -110,7 +95,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
final ViewPager viewPager = findViewById(R.id.pager);
|
||||
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager(), this, 7));
|
||||
viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager(), this));
|
||||
|
||||
waitForUIAction();
|
||||
|
||||
@@ -153,14 +138,14 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Starts a new asynchronous FFmpeg operation with arguments provided.
|
||||
* <p>Starts a new asynchronous FFmpeg operation with command provided.
|
||||
*
|
||||
* @param executeCallback callback function to receive result of this execution
|
||||
* @param arguments FFmpeg command options/arguments
|
||||
* @param singleExecuteCallback callback function to receive result of this execution
|
||||
* @param command FFmpeg command
|
||||
*/
|
||||
public static void executeAsync(final ExecuteCallback executeCallback, final String arguments) {
|
||||
final AsyncExecuteTask asyncCommandTask = new AsyncExecuteTask(executeCallback);
|
||||
asyncCommandTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, arguments);
|
||||
public static void executeAsync(final SingleExecuteCallback singleExecuteCallback, final String command) {
|
||||
final AsyncSingleFFmpegExecuteTask asyncCommandTask = new AsyncSingleFFmpegExecuteTask(command, singleExecuteCallback);
|
||||
asyncCommandTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public static void waitForUIAction() {
|
||||
@@ -171,84 +156,12 @@ public class MainActivity extends AppCompatActivity {
|
||||
actionQueue.add(callable);
|
||||
}
|
||||
|
||||
public AlertDialog createProgressDialog(final String text) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
if (inflater != null) {
|
||||
View dialogView = inflater.inflate(R.layout.progress_dialog_layout, null);
|
||||
builder.setView(dialogView);
|
||||
|
||||
TextView textView = dialogView.findViewById(R.id.progressDialogText);
|
||||
if (textView != null) {
|
||||
textView.setText(text);
|
||||
}
|
||||
}
|
||||
builder.setCancelable(false);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
public AlertDialog createCancellableProgressDialog(final String text, final View.OnClickListener onClickListener) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
if (inflater != null) {
|
||||
View dialogView = inflater.inflate(R.layout.cancellable_progress_dialog_layout, null);
|
||||
builder.setView(dialogView);
|
||||
|
||||
TextView textView = dialogView.findViewById(R.id.progressDialogText);
|
||||
if (textView != null) {
|
||||
textView.setText(text);
|
||||
}
|
||||
Button cancelButton = dialogView.findViewById(R.id.cancelButton);
|
||||
if (cancelButton != null) {
|
||||
cancelButton.setOnClickListener(onClickListener);
|
||||
}
|
||||
}
|
||||
builder.setCancelable(false);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
protected void resourceToFile(final int resourceId, final File file) throws IOException {
|
||||
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resourceId);
|
||||
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
|
||||
FileOutputStream outputStream = new FileOutputStream(file);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
protected void rawResourceToFile(final int resourceId, final File file) throws IOException {
|
||||
final InputStream inputStream = getResources().openRawResource(resourceId);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
final FileOutputStream outputStream = new FileOutputStream(file);
|
||||
|
||||
try {
|
||||
final byte[] buffer = new byte[1024];
|
||||
int readSize;
|
||||
|
||||
while ((readSize = inputStream.read(buffer)) > 0) {
|
||||
outputStream.write(buffer, 0, readSize);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
Log.e(TAG, "Saving raw resource failed.", e);
|
||||
} finally {
|
||||
inputStream.close();
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerAppFont() throws IOException {
|
||||
final File cacheDirectory = getCacheDir();
|
||||
|
||||
// SAVE FONTS
|
||||
rawResourceToFile(R.raw.doppioone_regular, new File(cacheDirectory, "doppioone_regular.ttf"));
|
||||
rawResourceToFile(R.raw.truenorg, new File(cacheDirectory, "truenorg.otf"));
|
||||
ResourcesUtil.rawResourceToFile(getResources(), R.raw.doppioone_regular, new File(cacheDirectory, "doppioone_regular.ttf"));
|
||||
ResourcesUtil.rawResourceToFile(getResources(), R.raw.truenorg, new File(cacheDirectory, "truenorg.otf"));
|
||||
|
||||
final HashMap<String, String> fontNameMapping = new HashMap<>();
|
||||
fontNameMapping.put("MyFontName", "Doppio One");
|
||||
|
||||
@@ -19,44 +19,45 @@
|
||||
|
||||
package com.arthenica.mobileffmpeg.test;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
|
||||
public class PagerAdapter extends FragmentPagerAdapter {
|
||||
private final MainActivity mainActivity;
|
||||
private int numberOfTabs;
|
||||
private static final int NUMBER_OF_TABS = 7;
|
||||
|
||||
PagerAdapter(final FragmentManager fragmentManager, final MainActivity mainActivity, final int numberOfTabs) {
|
||||
super(fragmentManager);
|
||||
private final Context context;
|
||||
|
||||
this.mainActivity = mainActivity;
|
||||
this.numberOfTabs = numberOfTabs;
|
||||
PagerAdapter(FragmentManager fragmentManager, Context context) {
|
||||
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(final int position) {
|
||||
switch (position) {
|
||||
case 0: {
|
||||
return CommandTabFragment.newInstance(mainActivity);
|
||||
return CommandTabFragment.newInstance();
|
||||
}
|
||||
case 1: {
|
||||
return VideoTabFragment.newInstance(mainActivity);
|
||||
return VideoTabFragment.newInstance();
|
||||
}
|
||||
case 2: {
|
||||
return HttpsTabFragment.newInstance(mainActivity);
|
||||
return HttpsTabFragment.newInstance();
|
||||
}
|
||||
case 3: {
|
||||
return AudioTabFragment.newInstance(mainActivity);
|
||||
return AudioTabFragment.newInstance();
|
||||
}
|
||||
case 4: {
|
||||
return SubtitleTabFragment.newInstance(mainActivity);
|
||||
return SubtitleTabFragment.newInstance();
|
||||
}
|
||||
case 5: {
|
||||
return VidStabTabFragment.newInstance(mainActivity);
|
||||
return VidStabTabFragment.newInstance();
|
||||
}
|
||||
case 6: {
|
||||
return PipeTabFragment.newInstance(mainActivity);
|
||||
return PipeTabFragment.newInstance();
|
||||
}
|
||||
default: {
|
||||
return null;
|
||||
@@ -66,32 +67,32 @@ public class PagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return numberOfTabs;
|
||||
return NUMBER_OF_TABS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(final int position) {
|
||||
switch (position) {
|
||||
case 0: {
|
||||
return mainActivity.getString(R.string.command_tab);
|
||||
return context.getString(R.string.command_tab);
|
||||
}
|
||||
case 1: {
|
||||
return mainActivity.getString(R.string.video_tab);
|
||||
return context.getString(R.string.video_tab);
|
||||
}
|
||||
case 2: {
|
||||
return mainActivity.getString(R.string.https_tab);
|
||||
return context.getString(R.string.https_tab);
|
||||
}
|
||||
case 3: {
|
||||
return mainActivity.getString(R.string.audio_tab);
|
||||
return context.getString(R.string.audio_tab);
|
||||
}
|
||||
case 4: {
|
||||
return mainActivity.getString(R.string.subtitle_tab);
|
||||
return context.getString(R.string.subtitle_tab);
|
||||
}
|
||||
case 5: {
|
||||
return mainActivity.getString(R.string.vidstab_tab);
|
||||
return context.getString(R.string.vidstab_tab);
|
||||
}
|
||||
case 6: {
|
||||
return mainActivity.getString(R.string.pipe_tab);
|
||||
return context.getString(R.string.pipe_tab);
|
||||
}
|
||||
default: {
|
||||
return null;
|
||||
|
||||
+42
-53
@@ -24,83 +24,72 @@ import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.MediaController;
|
||||
import android.widget.TextView;
|
||||
import android.widget.VideoView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.LogCallback;
|
||||
import com.arthenica.mobileffmpeg.LogMessage;
|
||||
import com.arthenica.mobileffmpeg.Statistics;
|
||||
import com.arthenica.mobileffmpeg.StatisticsCallback;
|
||||
import com.arthenica.mobileffmpeg.util.AsyncCatImageTask;
|
||||
import com.arthenica.mobileffmpeg.util.ExecuteCallback;
|
||||
import com.arthenica.mobileffmpeg.util.DialogUtil;
|
||||
import com.arthenica.mobileffmpeg.util.ResourcesUtil;
|
||||
import com.arthenica.mobileffmpeg.util.SingleExecuteCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.Config.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.test.MainActivity.TAG;
|
||||
|
||||
public class PipeTabFragment extends Fragment {
|
||||
|
||||
private MainActivity mainActivity;
|
||||
private VideoView videoView;
|
||||
private AlertDialog progressDialog;
|
||||
private Statistics statistics;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_pipe_tab, container, false);
|
||||
public PipeTabFragment() {
|
||||
super(R.layout.fragment_pipe_tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getView() != null) {
|
||||
View createButton = getView().findViewById(R.id.createButton);
|
||||
if (createButton != null) {
|
||||
createButton.setOnClickListener(new View.OnClickListener() {
|
||||
View createButton = view.findViewById(R.id.createButton);
|
||||
if (createButton != null) {
|
||||
createButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createVideo();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
videoView = getView().findViewById(R.id.videoPlayerFrame);
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createVideo();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
progressDialog = mainActivity.createProgressDialog("Creating video");
|
||||
videoView = view.findViewById(R.id.videoPlayerFrame);
|
||||
|
||||
progressDialog = DialogUtil.createProgressDialog(requireContext(), "Creating video");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
setActive();
|
||||
}
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setActive();
|
||||
}
|
||||
|
||||
public void setMainActivity(MainActivity mainActivity) {
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
public static PipeTabFragment newInstance(final MainActivity mainActivity) {
|
||||
final PipeTabFragment fragment = new PipeTabFragment();
|
||||
fragment.setMainActivity(mainActivity);
|
||||
return fragment;
|
||||
public static PipeTabFragment newInstance() {
|
||||
return new PipeTabFragment();
|
||||
}
|
||||
|
||||
public void enableLogCallback() {
|
||||
@@ -137,14 +126,14 @@ public class PipeTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void createVideo() {
|
||||
final File image1File = new File(mainActivity.getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(mainActivity.getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(mainActivity.getCacheDir(), "tajmahal.jpg");
|
||||
final File image1File = new File(requireContext().getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(requireContext().getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(requireContext().getCacheDir(), "tajmahal.jpg");
|
||||
final File videoFile = getVideoFile();
|
||||
|
||||
String pipe1 = Config.registerNewFFmpegPipe(mainActivity);
|
||||
String pipe2 = Config.registerNewFFmpegPipe(mainActivity);
|
||||
String pipe3 = Config.registerNewFFmpegPipe(mainActivity);
|
||||
String pipe1 = Config.registerNewFFmpegPipe(requireContext());
|
||||
String pipe2 = Config.registerNewFFmpegPipe(requireContext());
|
||||
String pipe3 = Config.registerNewFFmpegPipe(requireContext());
|
||||
|
||||
try {
|
||||
|
||||
@@ -159,15 +148,15 @@ public class PipeTabFragment extends Fragment {
|
||||
|
||||
showProgressDialog();
|
||||
|
||||
mainActivity.resourceToFile(R.drawable.colosseum, image1File);
|
||||
mainActivity.resourceToFile(R.drawable.pyramid, image2File);
|
||||
mainActivity.resourceToFile(R.drawable.tajmahal, image3File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.colosseum, image1File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.pyramid, image2File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.tajmahal, image3File);
|
||||
|
||||
final String ffmpegCommand = Video.generateCreateVideoWithPipesScript(pipe1, pipe2, pipe3, videoFile.getAbsolutePath());
|
||||
|
||||
Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'", ffmpegCommand));
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
@@ -183,7 +172,7 @@ public class PipeTabFragment extends Fragment {
|
||||
Log.d(TAG, "Create completed successfully; playing video.");
|
||||
playVideo();
|
||||
} else {
|
||||
Popup.show(mainActivity, "Create failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Create failed. Please check log for the details.");
|
||||
Log.d(TAG, String.format("Create failed with rc=%d", returnCode));
|
||||
}
|
||||
|
||||
@@ -200,12 +189,12 @@ public class PipeTabFragment extends Fragment {
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Create video failed", e);
|
||||
Popup.show(mainActivity, "Create video failed");
|
||||
Popup.show(requireContext(), "Create video failed");
|
||||
}
|
||||
}
|
||||
|
||||
protected void playVideo() {
|
||||
MediaController mediaController = new MediaController(mainActivity);
|
||||
MediaController mediaController = new MediaController(requireContext());
|
||||
mediaController.setAnchorView(videoView);
|
||||
videoView.setVideoURI(Uri.parse("file://" + getVideoFile().getAbsolutePath()));
|
||||
videoView.setMediaController(mediaController);
|
||||
@@ -229,14 +218,14 @@ public class PipeTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
protected File getVideoFile() {
|
||||
return new File(mainActivity.getFilesDir(), "video.mp4");
|
||||
return new File(requireContext().getFilesDir(), "video.mp4");
|
||||
}
|
||||
|
||||
public void setActive() {
|
||||
Log.i(MainActivity.TAG, "Pipe Tab Activated");
|
||||
enableLogCallback();
|
||||
enableStatisticsCallback();
|
||||
Popup.show(mainActivity, Tooltip.PIPE_TEST_TOOLTIP_TEXT);
|
||||
Popup.show(requireContext(), Tooltip.PIPE_TEST_TOOLTIP_TEXT);
|
||||
}
|
||||
|
||||
protected void showProgressDialog() {
|
||||
@@ -273,7 +262,7 @@ public class PipeTabFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public Object call() {
|
||||
PipeTabFragment.this.progressDialog = mainActivity.createProgressDialog("Creating video");
|
||||
PipeTabFragment.this.progressDialog = DialogUtil.createProgressDialog(requireContext(), "Creating video");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
+46
-72
@@ -23,33 +23,33 @@ import android.app.AlertDialog;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.MediaController;
|
||||
import android.widget.TextView;
|
||||
import android.widget.VideoView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
import com.arthenica.mobileffmpeg.LogCallback;
|
||||
import com.arthenica.mobileffmpeg.LogMessage;
|
||||
import com.arthenica.mobileffmpeg.Statistics;
|
||||
import com.arthenica.mobileffmpeg.StatisticsCallback;
|
||||
import com.arthenica.mobileffmpeg.util.ExecuteCallback;
|
||||
import com.arthenica.mobileffmpeg.util.DialogUtil;
|
||||
import com.arthenica.mobileffmpeg.util.ResourcesUtil;
|
||||
import com.arthenica.mobileffmpeg.util.SingleExecuteCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.RETURN_CODE_CANCEL;
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED;
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.Config.RETURN_CODE_CANCEL;
|
||||
import static com.arthenica.mobileffmpeg.Config.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.test.MainActivity.TAG;
|
||||
|
||||
public class SubtitleTabFragment extends Fragment {
|
||||
@@ -60,54 +60,42 @@ public class SubtitleTabFragment extends Fragment {
|
||||
BURNING
|
||||
}
|
||||
|
||||
private MainActivity mainActivity;
|
||||
private VideoView videoView;
|
||||
private AlertDialog createProgressDialog;
|
||||
private AlertDialog burnProgressDialog;
|
||||
private Statistics statistics;
|
||||
private State state;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_subtitle_tab, container, false);
|
||||
public SubtitleTabFragment() {
|
||||
super(R.layout.fragment_subtitle_tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getView() != null) {
|
||||
View burnSubtitlesButton = getView().findViewById(R.id.burnSubtitlesButton);
|
||||
burnSubtitlesButton.setOnClickListener(new View.OnClickListener() {
|
||||
View burnSubtitlesButton = view.findViewById(R.id.burnSubtitlesButton);
|
||||
burnSubtitlesButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
burnSubtitles();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
burnSubtitles();
|
||||
}
|
||||
});
|
||||
|
||||
videoView = getView().findViewById(R.id.videoPlayerFrame);
|
||||
}
|
||||
videoView = view.findViewById(R.id.videoPlayerFrame);
|
||||
|
||||
state = State.IDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
setActive();
|
||||
}
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setActive();
|
||||
}
|
||||
|
||||
public void setMainActivity(MainActivity mainActivity) {
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
public static SubtitleTabFragment newInstance(final MainActivity mainActivity) {
|
||||
final SubtitleTabFragment fragment = new SubtitleTabFragment();
|
||||
fragment.setMainActivity(mainActivity);
|
||||
return fragment;
|
||||
public static SubtitleTabFragment newInstance() {
|
||||
return new SubtitleTabFragment();
|
||||
}
|
||||
|
||||
public void enableLogCallback() {
|
||||
@@ -139,9 +127,9 @@ public class SubtitleTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void burnSubtitles() {
|
||||
final File image1File = new File(mainActivity.getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(mainActivity.getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(mainActivity.getCacheDir(), "tajmahal.jpg");
|
||||
final File image1File = new File(requireContext().getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(requireContext().getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(requireContext().getCacheDir(), "tajmahal.jpg");
|
||||
final File videoFile = getVideoFile();
|
||||
final File videoWithSubtitlesFile = getVideoWithSubtitlesFile();
|
||||
|
||||
@@ -162,10 +150,10 @@ public class SubtitleTabFragment extends Fragment {
|
||||
|
||||
showCreateProgressDialog();
|
||||
|
||||
mainActivity.resourceToFile(R.drawable.colosseum, image1File);
|
||||
mainActivity.resourceToFile(R.drawable.pyramid, image2File);
|
||||
mainActivity.resourceToFile(R.drawable.tajmahal, image3File);
|
||||
mainActivity.rawResourceToFile(R.raw.subtitle, getSubtitleFile());
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.colosseum, image1File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.pyramid, image2File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.tajmahal, image3File);
|
||||
ResourcesUtil.rawResourceToFile(getResources(), R.raw.subtitle, getSubtitleFile());
|
||||
|
||||
final String ffmpegCommand = Video.generateEncodeVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoFile.getAbsolutePath(), "mpeg4", "");
|
||||
|
||||
@@ -173,16 +161,12 @@ public class SubtitleTabFragment extends Fragment {
|
||||
|
||||
state = State.CREATING;
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
Log.d(TAG, String.format("FFmpeg process exited with rc %d", returnCode));
|
||||
|
||||
if (returnCode != RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED) {
|
||||
state = State.IDLE;
|
||||
}
|
||||
|
||||
hideCreateProgressDialog();
|
||||
|
||||
MainActivity.addUIAction(new Callable() {
|
||||
@@ -201,16 +185,12 @@ public class SubtitleTabFragment extends Fragment {
|
||||
|
||||
state = State.BURNING;
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
Log.d(TAG, String.format("FFmpeg process exited with rc %d", returnCode));
|
||||
|
||||
if (returnCode != RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED) {
|
||||
state = State.IDLE;
|
||||
}
|
||||
|
||||
hideBurnProgressDialog();
|
||||
|
||||
MainActivity.addUIAction(new Callable() {
|
||||
@@ -221,13 +201,10 @@ public class SubtitleTabFragment extends Fragment {
|
||||
Log.d(TAG, "Burn subtitles completed successfully; playing video.");
|
||||
playVideo();
|
||||
} else if (returnCode == RETURN_CODE_CANCEL) {
|
||||
Popup.show(mainActivity, "Burn subtitles operation cancelled.");
|
||||
Popup.show(requireContext(), "Burn subtitles operation cancelled.");
|
||||
Log.e(TAG, "Burn subtitles operation cancelled");
|
||||
} else if (returnCode == RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED) {
|
||||
Popup.show(mainActivity, "Multiple burn subtitles operations not allowed.");
|
||||
Log.e(TAG, "Multiple burn subtitles operations not allowed");
|
||||
} else {
|
||||
Popup.show(mainActivity, "Burn subtitles failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Burn subtitles failed. Please check log for the details.");
|
||||
Log.e(TAG, String.format("Burn subtitles failed with rc=%d", returnCode));
|
||||
}
|
||||
|
||||
@@ -238,13 +215,10 @@ public class SubtitleTabFragment extends Fragment {
|
||||
}, burnSubtitlesCommand);
|
||||
|
||||
} else if (returnCode == RETURN_CODE_CANCEL) {
|
||||
Popup.show(mainActivity, "Create operation cancelled.");
|
||||
Popup.show(requireContext(), "Create operation cancelled.");
|
||||
Log.e(TAG, "Create operation cancelled");
|
||||
} else if (returnCode == RETURN_CODE_MULTIPLE_EXECUTIONS_NOT_ALLOWED) {
|
||||
Popup.show(mainActivity, "Multiple create operations not allowed.");
|
||||
Log.e(TAG, "Multiple create operations not allowed");
|
||||
} else {
|
||||
Popup.show(mainActivity, "Create video failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Create video failed. Please check log for the details.");
|
||||
Log.e(TAG, String.format("Create failed with rc=%d", returnCode));
|
||||
}
|
||||
|
||||
@@ -256,12 +230,12 @@ public class SubtitleTabFragment extends Fragment {
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Burn subtitles failed", e);
|
||||
Popup.show(mainActivity, "Burn subtitles failed");
|
||||
Popup.show(requireContext(), "Burn subtitles failed");
|
||||
}
|
||||
}
|
||||
|
||||
protected void playVideo() {
|
||||
MediaController mediaController = new MediaController(mainActivity);
|
||||
MediaController mediaController = new MediaController(requireContext());
|
||||
mediaController.setAnchorView(videoView);
|
||||
videoView.setVideoURI(Uri.parse("file://" + getVideoWithSubtitlesFile().getAbsolutePath()));
|
||||
videoView.setMediaController(mediaController);
|
||||
@@ -285,22 +259,22 @@ public class SubtitleTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
public File getSubtitleFile() {
|
||||
return new File(mainActivity.getCacheDir(), "subtitle.srt");
|
||||
return new File(requireContext().getCacheDir(), "subtitle.srt");
|
||||
}
|
||||
|
||||
public File getVideoFile() {
|
||||
return new File(mainActivity.getFilesDir(), "video.mp4");
|
||||
return new File(requireContext().getFilesDir(), "video.mp4");
|
||||
}
|
||||
|
||||
public File getVideoWithSubtitlesFile() {
|
||||
return new File(mainActivity.getFilesDir(), "video-with-subtitles.mp4");
|
||||
return new File(requireContext().getFilesDir(), "video-with-subtitles.mp4");
|
||||
}
|
||||
|
||||
public void setActive() {
|
||||
android.util.Log.i(MainActivity.TAG, "Subtitle Tab Activated");
|
||||
Log.i(MainActivity.TAG, "Subtitle Tab Activated");
|
||||
enableLogCallback();
|
||||
enableStatisticsCallback();
|
||||
Popup.show(mainActivity, Tooltip.SUBTITLE_TEST_TOOLTIP_TEXT);
|
||||
Popup.show(requireContext(), Tooltip.SUBTITLE_TEST_TOOLTIP_TEXT);
|
||||
}
|
||||
|
||||
protected void showCreateProgressDialog() {
|
||||
@@ -309,7 +283,7 @@ public class SubtitleTabFragment extends Fragment {
|
||||
statistics = null;
|
||||
Config.resetStatistics();
|
||||
|
||||
createProgressDialog = mainActivity.createCancellableProgressDialog("Creating video", new View.OnClickListener() {
|
||||
createProgressDialog = DialogUtil.createCancellableProgressDialog(requireContext(), "Creating video", new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -353,7 +327,7 @@ public class SubtitleTabFragment extends Fragment {
|
||||
statistics = null;
|
||||
Config.resetStatistics();
|
||||
|
||||
burnProgressDialog = mainActivity.createCancellableProgressDialog("Burning subtitles", new View.OnClickListener() {
|
||||
burnProgressDialog = DialogUtil.createCancellableProgressDialog(requireContext(), "Burning subtitles", new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
FFmpeg.cancel();
|
||||
|
||||
+47
-57
@@ -23,78 +23,68 @@ import android.app.AlertDialog;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.MediaController;
|
||||
import android.widget.VideoView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.LogCallback;
|
||||
import com.arthenica.mobileffmpeg.LogMessage;
|
||||
import com.arthenica.mobileffmpeg.util.ExecuteCallback;
|
||||
import com.arthenica.mobileffmpeg.util.DialogUtil;
|
||||
import com.arthenica.mobileffmpeg.util.ResourcesUtil;
|
||||
import com.arthenica.mobileffmpeg.util.SingleExecuteCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.Config.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.test.MainActivity.TAG;
|
||||
|
||||
public class VidStabTabFragment extends Fragment {
|
||||
|
||||
private MainActivity mainActivity;
|
||||
private VideoView videoView;
|
||||
private VideoView stabilizedVideoView;
|
||||
private AlertDialog createProgressDialog;
|
||||
private AlertDialog stabilizeProgressDialog;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_vidstab_tab, container, false);
|
||||
public VidStabTabFragment() {
|
||||
super(R.layout.fragment_vidstab_tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getView() != null) {
|
||||
View stabilizeVideoButton = getView().findViewById(R.id.stabilizeVideoButton);
|
||||
stabilizeVideoButton.setOnClickListener(new View.OnClickListener() {
|
||||
View stabilizeVideoButton = view.findViewById(R.id.stabilizeVideoButton);
|
||||
stabilizeVideoButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
stabilizeVideo();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
stabilizeVideo();
|
||||
}
|
||||
});
|
||||
|
||||
videoView = getView().findViewById(R.id.videoPlayerFrame);
|
||||
stabilizedVideoView = getView().findViewById(R.id.stabilizedVideoPlayerFrame);
|
||||
}
|
||||
videoView = view.findViewById(R.id.videoPlayerFrame);
|
||||
stabilizedVideoView = view.findViewById(R.id.stabilizedVideoPlayerFrame);
|
||||
|
||||
createProgressDialog = mainActivity.createProgressDialog("Creating video");
|
||||
stabilizeProgressDialog = mainActivity.createProgressDialog("Stabilizing video");
|
||||
createProgressDialog = DialogUtil.createProgressDialog(requireContext(), "Creating video");
|
||||
stabilizeProgressDialog = DialogUtil.createProgressDialog(requireContext(), "Stabilizing video");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
setActive();
|
||||
}
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setActive();
|
||||
}
|
||||
|
||||
public void setMainActivity(MainActivity mainActivity) {
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
public static VidStabTabFragment newInstance(final MainActivity mainActivity) {
|
||||
final VidStabTabFragment fragment = new VidStabTabFragment();
|
||||
fragment.setMainActivity(mainActivity);
|
||||
return fragment;
|
||||
public static VidStabTabFragment newInstance() {
|
||||
return new VidStabTabFragment();
|
||||
}
|
||||
|
||||
public void enableLogCallback() {
|
||||
@@ -108,9 +98,9 @@ public class VidStabTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void stabilizeVideo() {
|
||||
final File image1File = new File(mainActivity.getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(mainActivity.getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(mainActivity.getCacheDir(), "tajmahal.jpg");
|
||||
final File image1File = new File(requireContext().getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(requireContext().getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(requireContext().getCacheDir(), "tajmahal.jpg");
|
||||
final File shakeResultsFile = getShakeResultsFile();
|
||||
final File videoFile = getVideoFile();
|
||||
final File stabilizedVideoFile = getStabilizedVideoFile();
|
||||
@@ -135,15 +125,15 @@ public class VidStabTabFragment extends Fragment {
|
||||
|
||||
showCreateProgressDialog();
|
||||
|
||||
mainActivity.resourceToFile(R.drawable.colosseum, image1File);
|
||||
mainActivity.resourceToFile(R.drawable.pyramid, image2File);
|
||||
mainActivity.resourceToFile(R.drawable.tajmahal, image3File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.colosseum, image1File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.pyramid, image2File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.tajmahal, image3File);
|
||||
|
||||
final String ffmpegCommand = Video.generateShakingVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoFile.getAbsolutePath());
|
||||
|
||||
android.util.Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'", ffmpegCommand));
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
@@ -165,7 +155,7 @@ public class VidStabTabFragment extends Fragment {
|
||||
|
||||
android.util.Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'", analyzeVideoCommand));
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
@@ -176,7 +166,7 @@ public class VidStabTabFragment extends Fragment {
|
||||
|
||||
android.util.Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'", stabilizeVideoCommand));
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
@@ -193,7 +183,7 @@ public class VidStabTabFragment extends Fragment {
|
||||
playVideo();
|
||||
playStabilizedVideo();
|
||||
} else {
|
||||
Popup.show(mainActivity, "Stabilize video failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Stabilize video failed. Please check log for the details.");
|
||||
android.util.Log.d(TAG, String.format("Stabilize video failed with rc=%d", returnCode));
|
||||
}
|
||||
|
||||
@@ -205,14 +195,14 @@ public class VidStabTabFragment extends Fragment {
|
||||
|
||||
} else {
|
||||
hideStabilizeProgressDialog();
|
||||
Popup.show(mainActivity, "Stabilize video failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Stabilize video failed. Please check log for the details.");
|
||||
android.util.Log.d(TAG, String.format("Stabilize video failed with rc=%d", returnCode));
|
||||
}
|
||||
}
|
||||
}, analyzeVideoCommand);
|
||||
|
||||
} else {
|
||||
Popup.show(mainActivity, "Create video failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Create video failed. Please check log for the details.");
|
||||
android.util.Log.d(TAG, String.format("Create failed with rc=%d", returnCode));
|
||||
}
|
||||
|
||||
@@ -224,12 +214,12 @@ public class VidStabTabFragment extends Fragment {
|
||||
|
||||
} catch (IOException e) {
|
||||
android.util.Log.e(TAG, "Stabilize video failed", e);
|
||||
Popup.show(mainActivity, "Stabilize video failed");
|
||||
Popup.show(requireContext(), "Stabilize video failed");
|
||||
}
|
||||
}
|
||||
|
||||
protected void playVideo() {
|
||||
MediaController mediaController = new MediaController(mainActivity);
|
||||
MediaController mediaController = new MediaController(requireContext());
|
||||
mediaController.setAnchorView(videoView);
|
||||
videoView.setVideoURI(Uri.parse("file://" + getVideoFile().getAbsolutePath()));
|
||||
videoView.setMediaController(mediaController);
|
||||
@@ -253,7 +243,7 @@ public class VidStabTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
protected void playStabilizedVideo() {
|
||||
MediaController mediaController = new MediaController(mainActivity);
|
||||
MediaController mediaController = new MediaController(requireContext());
|
||||
mediaController.setAnchorView(stabilizedVideoView);
|
||||
stabilizedVideoView.setVideoURI(Uri.parse("file://" + getStabilizedVideoFile().getAbsolutePath()));
|
||||
stabilizedVideoView.setMediaController(mediaController);
|
||||
@@ -277,21 +267,21 @@ public class VidStabTabFragment extends Fragment {
|
||||
}
|
||||
|
||||
public File getShakeResultsFile() {
|
||||
return new File(mainActivity.getCacheDir(), "transforms.trf");
|
||||
return new File(requireContext().getCacheDir(), "transforms.trf");
|
||||
}
|
||||
|
||||
public File getVideoFile() {
|
||||
return new File(mainActivity.getFilesDir(), "video.mp4");
|
||||
return new File(requireContext().getFilesDir(), "video.mp4");
|
||||
}
|
||||
|
||||
public File getStabilizedVideoFile() {
|
||||
return new File(mainActivity.getFilesDir(), "video-stabilized.mp4");
|
||||
return new File(requireContext().getFilesDir(), "video-stabilized.mp4");
|
||||
}
|
||||
|
||||
public void setActive() {
|
||||
android.util.Log.i(MainActivity.TAG, "VidStab Tab Activated");
|
||||
Log.i(MainActivity.TAG, "VidStab Tab Activated");
|
||||
enableLogCallback();
|
||||
Popup.show(mainActivity, Tooltip.VIDSTAB_TEST_TOOLTIP_TEXT);
|
||||
Popup.show(requireContext(), Tooltip.VIDSTAB_TEST_TOOLTIP_TEXT);
|
||||
}
|
||||
|
||||
protected void showCreateProgressDialog() {
|
||||
|
||||
+52
-63
@@ -23,14 +23,9 @@ import android.app.AlertDialog;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.util.AndroidRuntimeException;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.MediaController;
|
||||
@@ -38,83 +33,77 @@ import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.VideoView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.arthenica.mobileffmpeg.Config;
|
||||
import com.arthenica.mobileffmpeg.FFmpeg;
|
||||
import com.arthenica.mobileffmpeg.LogCallback;
|
||||
import com.arthenica.mobileffmpeg.LogMessage;
|
||||
import com.arthenica.mobileffmpeg.Statistics;
|
||||
import com.arthenica.mobileffmpeg.StatisticsCallback;
|
||||
import com.arthenica.mobileffmpeg.util.ExecuteCallback;
|
||||
import com.arthenica.mobileffmpeg.util.DialogUtil;
|
||||
import com.arthenica.mobileffmpeg.util.ResourcesUtil;
|
||||
import com.arthenica.mobileffmpeg.util.SingleExecuteCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static com.arthenica.mobileffmpeg.FFmpeg.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.Config.RETURN_CODE_SUCCESS;
|
||||
import static com.arthenica.mobileffmpeg.test.MainActivity.TAG;
|
||||
|
||||
public class VideoTabFragment extends Fragment implements AdapterView.OnItemSelectedListener {
|
||||
|
||||
private MainActivity mainActivity;
|
||||
private VideoView videoView;
|
||||
private AlertDialog progressDialog;
|
||||
private String selectedCodec;
|
||||
private Statistics statistics;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_video_tab, container, false);
|
||||
public VideoTabFragment() {
|
||||
super(R.layout.fragment_video_tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (getView() != null) {
|
||||
Spinner videoCodecSpinner = getView().findViewById(R.id.videoCodecSpinner);
|
||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mainActivity,
|
||||
R.array.video_codec, R.layout.spinner_item);
|
||||
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
|
||||
videoCodecSpinner.setAdapter(adapter);
|
||||
videoCodecSpinner.setOnItemSelectedListener(this);
|
||||
Spinner videoCodecSpinner = view.findViewById(R.id.videoCodecSpinner);
|
||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(requireContext(),
|
||||
R.array.video_codec, R.layout.spinner_item);
|
||||
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
|
||||
videoCodecSpinner.setAdapter(adapter);
|
||||
videoCodecSpinner.setOnItemSelectedListener(this);
|
||||
|
||||
View encodeButton = getView().findViewById(R.id.encodeButton);
|
||||
if (encodeButton != null) {
|
||||
encodeButton.setOnClickListener(new View.OnClickListener() {
|
||||
View encodeButton = view.findViewById(R.id.encodeButton);
|
||||
if (encodeButton != null) {
|
||||
encodeButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
encodeVideo();
|
||||
// encodeWebp();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
videoView = getView().findViewById(R.id.videoPlayerFrame);
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
encodeVideo();
|
||||
// encodeWebp();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
progressDialog = mainActivity.createProgressDialog("Encoding video");
|
||||
videoView = view.findViewById(R.id.videoPlayerFrame);
|
||||
|
||||
progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video");
|
||||
|
||||
selectedCodec = getResources().getStringArray(R.array.video_codec)[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser) {
|
||||
setActive();
|
||||
}
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setActive();
|
||||
}
|
||||
|
||||
public void setMainActivity(MainActivity mainActivity) {
|
||||
this.mainActivity = mainActivity;
|
||||
}
|
||||
|
||||
public static VideoTabFragment newInstance(final MainActivity mainActivity) {
|
||||
final VideoTabFragment fragment = new VideoTabFragment();
|
||||
fragment.setMainActivity(mainActivity);
|
||||
return fragment;
|
||||
public static VideoTabFragment newInstance() {
|
||||
return new VideoTabFragment();
|
||||
}
|
||||
|
||||
public void enableLogCallback() {
|
||||
@@ -158,9 +147,9 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
}
|
||||
|
||||
public void encodeVideo() {
|
||||
final File image1File = new File(mainActivity.getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(mainActivity.getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(mainActivity.getCacheDir(), "tajmahal.jpg");
|
||||
final File image1File = new File(requireContext().getCacheDir(), "colosseum.jpg");
|
||||
final File image2File = new File(requireContext().getCacheDir(), "pyramid.jpg");
|
||||
final File image3File = new File(requireContext().getCacheDir(), "tajmahal.jpg");
|
||||
final File videoFile = getVideoFile();
|
||||
|
||||
try {
|
||||
@@ -178,15 +167,15 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
|
||||
showProgressDialog();
|
||||
|
||||
mainActivity.resourceToFile(R.drawable.colosseum, image1File);
|
||||
mainActivity.resourceToFile(R.drawable.pyramid, image2File);
|
||||
mainActivity.resourceToFile(R.drawable.tajmahal, image3File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.colosseum, image1File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.pyramid, image2File);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.tajmahal, image3File);
|
||||
|
||||
final String ffmpegCommand = Video.generateEncodeVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoFile.getAbsolutePath(), getSelectedVideoCodec(), getCustomOptions());
|
||||
|
||||
Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'", ffmpegCommand));
|
||||
|
||||
MainActivity.executeAsync(new ExecuteCallback() {
|
||||
MainActivity.executeAsync(new SingleExecuteCallback() {
|
||||
|
||||
@Override
|
||||
public void apply(final int returnCode, final String commandOutput) {
|
||||
@@ -194,7 +183,7 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
|
||||
Log.d(TAG, "FFmpeg process output:");
|
||||
|
||||
FFmpeg.printLastCommandOutput(Log.INFO);
|
||||
Config.printLastCommandOutput(Log.INFO);
|
||||
|
||||
hideProgressDialog();
|
||||
|
||||
@@ -206,7 +195,7 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
Log.d(TAG, "Encode completed successfully; playing video.");
|
||||
playVideo();
|
||||
} else {
|
||||
Popup.show(mainActivity, "Encode failed. Please check log for the details.");
|
||||
Popup.show(requireContext(), "Encode failed. Please check log for the details.");
|
||||
Log.d(TAG, String.format("Encode failed with rc=%d", returnCode));
|
||||
}
|
||||
|
||||
@@ -218,16 +207,16 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Encode video failed", e);
|
||||
Popup.show(mainActivity, "Encode video failed");
|
||||
Popup.show(requireContext(), "Encode video failed");
|
||||
}
|
||||
}
|
||||
|
||||
protected void encodeWebp() {
|
||||
final File imageFile = new File(mainActivity.getCacheDir(), "colosseum.jpg");
|
||||
final File outputFile = new File(mainActivity.getFilesDir(), "video.webp");
|
||||
final File imageFile = new File(requireContext().getCacheDir(), "colosseum.jpg");
|
||||
final File outputFile = new File(requireContext().getFilesDir(), "video.webp");
|
||||
|
||||
try {
|
||||
mainActivity.resourceToFile(R.drawable.colosseum, imageFile);
|
||||
ResourcesUtil.resourceToFile(getResources(), R.drawable.colosseum, imageFile);
|
||||
|
||||
Log.d(TAG, "Testing VIDEO encoding with 'webp' codec");
|
||||
|
||||
@@ -240,12 +229,12 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
Log.d(TAG, String.format("FFmpeg process exited with rc %d", returnCode));
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Encode webp failed", e);
|
||||
Popup.show(mainActivity, "Encode webp failed");
|
||||
Popup.show(requireContext(), "Encode webp failed");
|
||||
}
|
||||
}
|
||||
|
||||
protected void playVideo() {
|
||||
MediaController mediaController = new MediaController(mainActivity);
|
||||
MediaController mediaController = new MediaController(requireContext());
|
||||
mediaController.setAnchorView(videoView);
|
||||
videoView.setVideoURI(Uri.parse("file://" + getVideoFile().getAbsolutePath()));
|
||||
videoView.setMediaController(mediaController);
|
||||
@@ -331,7 +320,7 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
}
|
||||
|
||||
final String video = "video." + extension;
|
||||
return new File(mainActivity.getFilesDir(), video);
|
||||
return new File(requireContext().getFilesDir(), video);
|
||||
}
|
||||
|
||||
public String getCustomOptions() {
|
||||
@@ -358,10 +347,10 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
}
|
||||
|
||||
public void setActive() {
|
||||
android.util.Log.i(MainActivity.TAG, "Video Tab Activated");
|
||||
Log.i(MainActivity.TAG, "Video Tab Activated");
|
||||
enableLogCallback();
|
||||
enableStatisticsCallback();
|
||||
Popup.show(mainActivity, Tooltip.VIDEO_TEST_TOOLTIP_TEXT);
|
||||
Popup.show(requireContext(), Tooltip.VIDEO_TEST_TOOLTIP_TEXT);
|
||||
}
|
||||
|
||||
protected void showProgressDialog() {
|
||||
@@ -398,7 +387,7 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
|
||||
|
||||
@Override
|
||||
public Object call() {
|
||||
VideoTabFragment.this.progressDialog = mainActivity.createProgressDialog("Encoding video");
|
||||
VideoTabFragment.this.progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alexander Berezhnoi
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.mobileffmpeg.util;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.arthenica.mobileffmpeg.test.R;
|
||||
|
||||
public class DialogUtil {
|
||||
|
||||
public static AlertDialog createProgressDialog(Context context, final String text) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
if (inflater != null) {
|
||||
View dialogView = inflater.inflate(R.layout.progress_dialog_layout, null);
|
||||
builder.setView(dialogView);
|
||||
|
||||
TextView textView = dialogView.findViewById(R.id.progressDialogText);
|
||||
if (textView != null) {
|
||||
textView.setText(text);
|
||||
}
|
||||
}
|
||||
builder.setCancelable(false);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
public static AlertDialog createCancellableProgressDialog(Context context, final String text, final View.OnClickListener onClickListener) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
if (inflater != null) {
|
||||
View dialogView = inflater.inflate(R.layout.cancellable_progress_dialog_layout, null);
|
||||
builder.setView(dialogView);
|
||||
|
||||
TextView textView = dialogView.findViewById(R.id.progressDialogText);
|
||||
if (textView != null) {
|
||||
textView.setText(text);
|
||||
}
|
||||
Button cancelButton = dialogView.findViewById(R.id.cancelButton);
|
||||
if (cancelButton != null) {
|
||||
cancelButton.setOnClickListener(onClickListener);
|
||||
}
|
||||
}
|
||||
builder.setCancelable(false);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Alexander Berezhnoi
|
||||
*
|
||||
* This file is part of MobileFFmpeg.
|
||||
*
|
||||
* MobileFFmpeg is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MobileFFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.arthenica.mobileffmpeg.util;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
|
||||
import com.arthenica.mobileffmpeg.test.MainActivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ResourcesUtil {
|
||||
public static void resourceToFile(Resources resources, final int resourceId, final File file) throws IOException {
|
||||
Bitmap bitmap = BitmapFactory.decodeResource(resources, resourceId);
|
||||
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
|
||||
FileOutputStream outputStream = new FileOutputStream(file);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
public static void rawResourceToFile(Resources resources, final int resourceId, final File file) throws IOException {
|
||||
final InputStream inputStream = resources.openRawResource(resourceId);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
final FileOutputStream outputStream = new FileOutputStream(file);
|
||||
|
||||
try {
|
||||
final byte[] buffer = new byte[1024];
|
||||
int readSize;
|
||||
|
||||
while ((readSize = inputStream.read(buffer)) > 0) {
|
||||
outputStream.write(buffer, 0, readSize);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
Log.e(MainActivity.TAG, "Saving raw resource failed.", e);
|
||||
} finally {
|
||||
inputStream.close();
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.AppCompatTextView
|
||||
android:id="@+id/header"
|
||||
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat"
|
||||
android:textColor="@android:color/white"
|
||||
android:textStyle="bold"
|
||||
app:fontFamily="sans-serif" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,33 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="207dp"
|
||||
tools:context="com.arthenica.mobileffmpeg.test.MainActivity"
|
||||
tools:layout_editor_absoluteY="81dp">
|
||||
tools:context="com.arthenica.mobileffmpeg.test.MainActivity">
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="0dp"
|
||||
<androidx.viewpager.widget.PagerTabStrip
|
||||
android:id="@+id/pagerTabStrip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
android:layout_gravity="top"/>
|
||||
|
||||
<android.support.v4.view.PagerTabStrip
|
||||
android:id="@+id/pagerTabStrip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="top"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:layout_marginTop="0dp"
|
||||
android:padding="0dp" />
|
||||
|
||||
</android.support.v4.view.ViewPager>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.viewpager.widget.ViewPager>
|
||||
@@ -22,15 +22,15 @@
|
||||
tools:targetApi="cupcake" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/runButton"
|
||||
android:layout_width="80dp"
|
||||
android:id="@+id/runFFmpegButton"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@drawable/rounded_button"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:text="@string/command_run_button_text"
|
||||
android:text="@string/command_run_ffmpeg_button_text"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
@@ -38,15 +38,15 @@
|
||||
tools:targetApi="jelly_bean" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/runAsyncButton"
|
||||
android:id="@+id/runFFprobeButton"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@drawable/rounded_button"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:text="@string/command_run_async_button_text"
|
||||
android:text="@string/command_run_ffprobe_button_text"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="headerColor">#e74c3c</color>
|
||||
<color name="headerColorDark">#DD4232</color>
|
||||
<color name="editColor">#3498db</color>
|
||||
<color name="navigationColor">#e67e22</color>
|
||||
</resources>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<string name="vidstab_tab">VID.STAB</string>
|
||||
<string name="pipe_tab">PIPE</string>
|
||||
<string name="command_text_input_placeholder">Enter command</string>
|
||||
<string name="command_run_async_button_text">RUN ASYNC</string>
|
||||
<string name="command_run_button_text">RUN</string>
|
||||
<string name="command_run_ffmpeg_button_text">RUN FFMPEG</string>
|
||||
<string name="command_run_ffprobe_button_text">RUN FFPROBE</string>
|
||||
<string name="video_encode_button_text">ENCODE</string>
|
||||
<string name="video_create_button_text">CREATE</string>
|
||||
<string name="https_get_info_button_text">GET INFO</string>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<item name="colorPrimary">@color/headerColor</item>
|
||||
<item name="colorPrimaryDark">@color/headerColor</item>
|
||||
<item name="colorPrimaryDark">@color/headerColorDark</item>
|
||||
<item name="colorAccent">@color/editColor</item>
|
||||
</style>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="chromaprint"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
+20
-20
@@ -75,7 +75,7 @@ get_arch_name() {
|
||||
esac
|
||||
}
|
||||
|
||||
get_target_host() {
|
||||
get_build_host() {
|
||||
case ${ARCH} in
|
||||
arm-v7a | arm-v7a-neon)
|
||||
echo "arm-linux-androideabi"
|
||||
@@ -359,7 +359,7 @@ get_cxxflags() {
|
||||
}
|
||||
|
||||
get_common_linked_libraries() {
|
||||
local COMMON_LIBRARY_PATHS="-L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/${TARGET_HOST}/lib -L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/sysroot/usr/lib/${TARGET_HOST}/${API} -L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/lib"
|
||||
local COMMON_LIBRARY_PATHS="-L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/${BUILD_HOST}/lib -L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/sysroot/usr/lib/${BUILD_HOST}/${API} -L${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/lib"
|
||||
|
||||
case $1 in
|
||||
ffmpeg)
|
||||
@@ -913,20 +913,20 @@ download_gpl_library_source() {
|
||||
GPL_LIB_DEST_DIR="libvidstab"
|
||||
;;
|
||||
x264)
|
||||
GPL_LIB_URL="ftp://ftp.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-20191024-2245-stable.tar.bz2"
|
||||
GPL_LIB_FILE="x264-snapshot-20191024-2245-stable.tar.bz2"
|
||||
GPL_LIB_ORIG_DIR="x264-snapshot-20191024-2245-stable"
|
||||
GPL_LIB_URL="https://code.videolan.org/videolan/x264/-/archive/1771b556ee45207f8711744ccbd5d42a3949b14c/x264-1771b556ee45207f8711744ccbd5d42a3949b14c.tar.bz2"
|
||||
GPL_LIB_FILE="x264-1771b556ee45207f8711744ccbd5d42a3949b14c.tar.bz2"
|
||||
GPL_LIB_ORIG_DIR="x264-1771b556ee45207f8711744ccbd5d42a3949b14c"
|
||||
GPL_LIB_DEST_DIR="x264"
|
||||
;;
|
||||
x265)
|
||||
GPL_LIB_URL="https://bitbucket.org/multicoreware/x265/downloads/x265_3.2.tar.gz"
|
||||
GPL_LIB_FILE="x265-3.2.tar.gz"
|
||||
GPL_LIB_ORIG_DIR="x265_3.2"
|
||||
GPL_LIB_URL="https://bitbucket.org/multicoreware/x265/downloads/x265_3.2.1.tar.gz"
|
||||
GPL_LIB_FILE="x265-3.2.1.tar.gz"
|
||||
GPL_LIB_ORIG_DIR="x265_3.2.1"
|
||||
GPL_LIB_DEST_DIR="x265"
|
||||
;;
|
||||
xvidcore)
|
||||
GPL_LIB_URL="https://downloads.xvid.com/downloads/xvidcore-1.3.5.tar.gz"
|
||||
GPL_LIB_FILE="xvidcore-1.3.5.tar.gz"
|
||||
GPL_LIB_URL="https://downloads.xvid.com/downloads/xvidcore-1.3.7.tar.gz"
|
||||
GPL_LIB_FILE="xvidcore-1.3.7.tar.gz"
|
||||
GPL_LIB_ORIG_DIR="xvidcore"
|
||||
GPL_LIB_DEST_DIR="xvidcore"
|
||||
;;
|
||||
@@ -1003,16 +1003,16 @@ download_gpl_library_source() {
|
||||
set_toolchain_clang_paths() {
|
||||
export PATH=$PATH:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin
|
||||
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
|
||||
export AR=${TARGET_HOST}-ar
|
||||
export AR=${BUILD_HOST}-ar
|
||||
export CC=$(get_clang_target_host)-clang
|
||||
export CXX=$(get_clang_target_host)-clang++
|
||||
|
||||
if [ "$1" == "x264" ]; then
|
||||
export AS=${CC}
|
||||
else
|
||||
export AS=${TARGET_HOST}-as
|
||||
export AS=${BUILD_HOST}-as
|
||||
fi
|
||||
|
||||
case ${ARCH} in
|
||||
@@ -1021,9 +1021,9 @@ set_toolchain_clang_paths() {
|
||||
;;
|
||||
esac
|
||||
|
||||
export LD=${TARGET_HOST}-ld
|
||||
export RANLIB=${TARGET_HOST}-ranlib
|
||||
export STRIP=${TARGET_HOST}-strip
|
||||
export LD=${BUILD_HOST}-ld
|
||||
export RANLIB=${BUILD_HOST}-ranlib
|
||||
export STRIP=${BUILD_HOST}-strip
|
||||
|
||||
export INSTALL_PKG_CONFIG_DIR="${BASEDIR}/prebuilt/android-$(get_target_build)/pkgconfig"
|
||||
export ZLIB_PACKAGE_CONFIG_PATH="${INSTALL_PKG_CONFIG_DIR}/zlib.pc"
|
||||
@@ -1050,14 +1050,14 @@ build_cpufeatures() {
|
||||
|
||||
set_toolchain_clang_paths "cpu-features"
|
||||
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags "cpu-features")
|
||||
export CXXFLAGS=$(get_cxxflags "cpu-features")
|
||||
export LDFLAGS=$(get_ldflags "cpu-features")
|
||||
|
||||
# THEN BUILD FOR THIS ABI
|
||||
$(get_clang_target_host)-clang -c ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/cpu-features.c -o ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/cpu-features.o 1>>${BASEDIR}/build.log 2>&1
|
||||
${TARGET_HOST}-ar rcs ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/libcpufeatures.a ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/cpu-features.o 1>>${BASEDIR}/build.log 2>&1
|
||||
${BUILD_HOST}-ar rcs ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/libcpufeatures.a ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/cpu-features.o 1>>${BASEDIR}/build.log 2>&1
|
||||
$(get_clang_target_host)-clang -shared ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/cpu-features.o -o ${ANDROID_NDK_ROOT}/sources/android/cpufeatures/libcpufeatures.so 1>>${BASEDIR}/build.log 2>&1
|
||||
|
||||
create_cpufeatures_package_config
|
||||
@@ -1076,13 +1076,13 @@ build_android_lts_support() {
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
# THEN BUILD FOR THIS ABI
|
||||
$(get_clang_target_host)-clang ${CFLAGS} -Wno-unused-command-line-argument -c ${BASEDIR}/android/app/src/main/cpp/android_lts_support.c -o ${BASEDIR}/android/app/src/main/cpp/android_lts_support.o ${LDFLAGS} 1>>${BASEDIR}/build.log 2>&1
|
||||
${TARGET_HOST}-ar rcs ${BASEDIR}/android/app/src/main/cpp/libandroidltssupport.a ${BASEDIR}/android/app/src/main/cpp/android_lts_support.o 1>>${BASEDIR}/build.log 2>&1
|
||||
${BUILD_HOST}-ar rcs ${BASEDIR}/android/app/src/main/cpp/libandroidltssupport.a ${BASEDIR}/android/app/src/main/cpp/android_lts_support.o 1>>${BASEDIR}/build.log 2>&1
|
||||
}
|
||||
|
||||
autoreconf_library() {
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="expat"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -51,7 +51,7 @@ fi
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ LIB_NAME="ffmpeg"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -336,8 +336,12 @@ export LDFLAGS="${LDFLAGS}"
|
||||
# USE HIGHER LIMITS FOR FFMPEG LINKING
|
||||
ulimit -n 2048 1>>${BASEDIR}/build.log 2>&1
|
||||
|
||||
# Workaround for issue #328
|
||||
rm -f ${BASEDIR}/src/${LIB_NAME}/libswscale/aarch64/hscale.S 1>>${BASEDIR}/build.log 2>&1
|
||||
cp ${BASEDIR}/tools/make/ffmpeg/libswscale/aarch64/hscale.S ${BASEDIR}/src/${LIB_NAME}/libswscale/aarch64/hscale.S 1>>${BASEDIR}/build.log 2>&1
|
||||
|
||||
./configure \
|
||||
--cross-prefix="${TARGET_HOST}-" \
|
||||
--cross-prefix="${BUILD_HOST}-" \
|
||||
--sysroot="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/sysroot" \
|
||||
--prefix="${BASEDIR}/prebuilt/android-$(get_target_build)/${LIB_NAME}" \
|
||||
--pkg-config="${HOST_PKG_CONFIG_PATH}" \
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="fontconfig"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
--disable-rpath \
|
||||
--disable-libxml2 \
|
||||
--disable-docs \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="freetype"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -58,7 +58,7 @@ export LIBPNG_LIBS="-L${BASEDIR}/prebuilt/android-$(get_target_build)/libpng/lib
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--disable-mmap \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="fribidi"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -52,7 +52,7 @@ fi
|
||||
--disable-fast-install \
|
||||
--disable-debug \
|
||||
--disable-deprecated \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="giflib"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})" -DS_IREAD=S_IRUSR -DS_IWRITE=S_IWUSR"
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -50,7 +50,7 @@ fi
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="gmp"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -51,7 +51,7 @@ fi
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--disable-maintainer-mode \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="gnutls"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
COMMON_CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
COMMON_CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
COMMON_LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -83,11 +83,11 @@ fi
|
||||
--disable-tests \
|
||||
--disable-tools \
|
||||
--disable-maintainer-mode \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
# CREATE PACKAGE CONFIG MANUALLY
|
||||
create_gnutls_package_config "3.6.10"
|
||||
create_gnutls_package_config "3.6.11.1"
|
||||
|
||||
make install || exit 1
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="jpeg"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="kvazaar"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -62,7 +62,7 @@ LIBS="${ARCH_SPECIFIC_LIBS}" ./configure \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="lame"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
--disable-frontend \
|
||||
--disable-efence \
|
||||
--disable-gtktest \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="leptonica"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export CPPFLAGS="-I${BASEDIR}/prebuilt/android-$(get_target_build)/giflib/include"
|
||||
@@ -72,7 +72,7 @@ fi
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--disable-programs \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libaom"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libass"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -69,7 +69,7 @@ esac
|
||||
--disable-profile \
|
||||
--disable-coretext \
|
||||
${ASM_FLAGS} \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libiconv"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -50,7 +50,7 @@ fi
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--disable-rpath \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libilbc"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -49,7 +49,7 @@ fi
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libogg"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -49,7 +49,7 @@ fi
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libpng"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -68,7 +68,7 @@ fi
|
||||
--disable-unversioned-libpng-pc \
|
||||
--disable-unversioned-libpng-config \
|
||||
${CPU_SPECIFIC_OPTIONS} \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libsndfile"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -53,7 +53,7 @@ fi
|
||||
--disable-alsa \
|
||||
--disable-full-suite \
|
||||
--disable-external-libs \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libtheora"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -60,7 +60,7 @@ fi
|
||||
--disable-sdltest \
|
||||
${ASM_FLAGS} \
|
||||
--disable-valgrind-testing \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libuuid"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -49,7 +49,7 @@ fi
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libvidstab"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libvorbis"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -43,7 +43,7 @@ ${SED_INLINE} 's/\-mno-ieee-fp//g' ${BASEDIR}/src/${LIB_NAME}/configure.ac
|
||||
# ALWAYS RECONFIGURE
|
||||
autoreconf_library ${LIB_NAME}
|
||||
|
||||
./configure \
|
||||
PKG_CONFIG= ./configure \
|
||||
--prefix=${BASEDIR}/prebuilt/android-$(get_target_build)/${LIB_NAME} \
|
||||
--with-pic \
|
||||
--with-sysroot=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/sysroot \
|
||||
@@ -55,7 +55,7 @@ autoreconf_library ${LIB_NAME}
|
||||
--disable-docs \
|
||||
--disable-examples \
|
||||
--disable-oggtest \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@ export CFLAGS="$(get_cflags ${LIB_NAME}) -I${ANDROID_NDK_ROOT}/sources/android/c
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS="$(get_ldflags ${LIB_NAME}) -L${ANDROID_NDK_ROOT}/sources/android/cpufeatures -lcpufeatures"
|
||||
|
||||
# RECOVER configure.sh
|
||||
rm -f ${BASEDIR}/src/${LIB_NAME}/build/make/configure.sh
|
||||
cp ${BASEDIR}/tools/make/configure.libvpx.android.sh ${BASEDIR}/src/${LIB_NAME}/build/make/configure.sh
|
||||
|
||||
TARGET_CPU=""
|
||||
DISABLE_NEON_FLAG=""
|
||||
case ${ARCH} in
|
||||
|
||||
@@ -28,18 +28,18 @@ LIB_NAME="libwebp"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
SIMD_OPTIONS=""
|
||||
ARCH_OPTIONS=""
|
||||
case ${ARCH} in
|
||||
arm-v7a)
|
||||
SIMD_OPTIONS="-DWEBP_ENABLE_SIMD=OFF"
|
||||
ARCH_OPTIONS="-DWEBP_ENABLE_SIMD=OFF"
|
||||
;;
|
||||
*)
|
||||
SIMD_OPTIONS="-DWEBP_ENABLE_SIMD=ON"
|
||||
ARCH_OPTIONS="-DWEBP_ENABLE_SIMD=ON"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -95,13 +95,13 @@ cmake -Wno-dev \
|
||||
-DWEBP_BUILD_IMG2WEBP=0 \
|
||||
-DWEBP_BUILD_WEBPMUX=0 \
|
||||
-DWEBP_BUILD_WEBPINFO=0 \
|
||||
${SIMD_OPTIONS} \
|
||||
${ARCH_OPTIONS} \
|
||||
-DCMAKE_SYSTEM_PROCESSOR=$(get_cmake_target_processor) \
|
||||
-DBUILD_SHARED_LIBS=0 .. || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
# CREATE PACKAGE CONFIG MANUALLY
|
||||
create_libwebp_package_config "1.0.3"
|
||||
create_libwebp_package_config "1.1.0"
|
||||
|
||||
make install || exit 1
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="libxml2"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -60,11 +60,11 @@ autoreconf_library ${LIB_NAME}
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
# CREATE PACKAGE CONFIG MANUALLY
|
||||
create_libxml2_package_config "2.9.9"
|
||||
create_libxml2_package_config "2.9.10"
|
||||
|
||||
make install || exit 1
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="nettle"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -65,7 +65,7 @@ fi
|
||||
--disable-gcov \
|
||||
--disable-documentation \
|
||||
${OPTIONAL_CPU_SUPPORT} \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="opencore-amr"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -50,7 +50,7 @@ fi
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--disable-maintainer-mode \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="openh264"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="opus"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -56,7 +56,7 @@ fi
|
||||
--disable-maintainer-mode \
|
||||
--disable-doc \
|
||||
--disable-extra-programs \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="sdl"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -51,7 +51,7 @@ fi
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="shine"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -49,7 +49,7 @@ fi
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="snappy"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="soxr"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="speex"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -56,7 +56,7 @@ fi
|
||||
--disable-shared \
|
||||
--disable-binaries \
|
||||
--disable-fast-install \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="tesseract"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -60,7 +60,7 @@ export ac_cv_c_bigendian=no
|
||||
--disable-cube \
|
||||
--disable-tessdata-prefix \
|
||||
--disable-largefile \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
${SED_INLINE} 's/\-lrt//g' ${BASEDIR}/src/${LIB_NAME}/api/Makefile
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ LIB_NAME="tiff"
|
||||
set_toolchain_clang_paths ${LIB_NAME}
|
||||
|
||||
# PREPARING FLAGS
|
||||
TARGET_HOST=$(get_target_host)
|
||||
BUILD_HOST=$(get_build_host)
|
||||
export CFLAGS=$(get_cflags ${LIB_NAME})
|
||||
export CXXFLAGS=$(get_cxxflags ${LIB_NAME})
|
||||
export LDFLAGS=$(get_ldflags ${LIB_NAME})
|
||||
@@ -55,7 +55,7 @@ fi
|
||||
--disable-cxx \
|
||||
--disable-win32-io \
|
||||
--disable-lzma \
|
||||
--host=${TARGET_HOST} || exit 1
|
||||
--host=${BUILD_HOST} || exit 1
|
||||
|
||||
make -j$(get_cpu_count) || exit 1
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user