My app is partly written in native app using C/C++. The problem is that whenever C/C++ part crashes for some reason the app dies and then restarts automatically. This causes all kinds of messy problems
Now of course, it should not crash in the native part and I'm trying to weed out all reasons why it would happen. However, if it does happen I'd like to:
Quit gracefully
If it does die, at least not try to restart automatically.
I'm curious as to why this behaviour happens. After some search I tried putting the following line in the main activity element of the AndroidManifest.xml:
android:finishOnTaskLaunch="true"
but the automatic restore still happens.
Anyone knows why this is happening and how to change it?
UPDATE:
I think a more fundamental question is,
Is there something similar to a callback if there is a native crash?
One of the answers suggested 'handling crash signals'. I'd be grateful for any links on how it can be done at an application or module level.
As it stands currently, if there is a crash the app just disappears, there's nothing in logcat, so no debugging is possible.
Try to handle crash signals (SIGSEGV etc.) and send kill to yourself in signal handler. This trick helps me.
Example:
#include <signal.h>
#include <unistd.h>
static void signal_handler(int signal, siginfo_t *info, void *reserved)
{
kill(getpid(),SIGKILL);
}
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
{
struct sigaction handler;
memset(&handler, 0, sizeof(handler));
handler.sa_sigaction = signal_handler;
handler.sa_flags = SA_SIGINFO;
sigaction(SIGILL, &handler, NULL);
sigaction(SIGABRT, &handler, NULL);
sigaction(SIGBUS, &handler, NULL);
sigaction(SIGFPE, &handler, NULL);
sigaction(SIGSEGV, &handler, NULL);
sigaction(SIGSTKFLT, &handler, NULL);
return(JNI_VERSION_1_6);
}
UPDATE2
if you want to see crashlog in android logcat you should use this signal handler
static void signal_handler(int signal, siginfo_t *info, void *reserved)
{
struct sockaddr_un addr;
size_t namelen;
socklen_t alen;
int s, err;
char name[] = "android:debuggerd";
namelen = strlen(name);
// Test with length +1 for the *initial* '\0'.
if ((namelen + 1) > sizeof(addr.sun_path)) {
errno = EINVAL;
return;
}
/* This is used for abstract socket namespace, we need
* an initial '\0' at the start of the Unix socket path.
*
* Note: The path in this case is *not* supposed to be
* '\0'-terminated. ("man 7 unix" for the gory details.)
*/
memset (&addr, 0, sizeof addr);
addr.sun_family = AF_LOCAL;
addr.sun_path[0] = 0;
memcpy(addr.sun_path + 1, name, namelen);
alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
s = socket(AF_LOCAL, SOCK_STREAM, 0);
if(s < 0) return;
RETRY_ON_EINTR(err,connect(s, (struct sockaddr *) &addr, alen));
if (err < 0) {
close(s);
s = -1;
}
pid_t tid = gettid();
if(s>=0)
{
/* debugger knows our pid from the credentials on the
* local socket but we need to tell it our tid. It
* is paranoid and will verify that we are giving a tid
* that's actually in our process
*/
int ret;
RETRY_ON_EINTR(ret, write(s, &tid, sizeof(unsigned)));
if (ret == sizeof(unsigned)) {
/* if the write failed, there is no point to read on
* the file descriptor. */
RETRY_ON_EINTR(ret, read(s, &tid, 1));
//notify_gdb_of_libraries();
}
close(s);
}
wait(NULL);
kill(getpid(),SIGKILL);
}
I took it from android source (can't insert link because android.git.kernel.org is down), but I am not sure that it will work in future Android releases
By default your application should not be automatically restarting. Generally one would have to register for this kind of thing, e.g. via the AlarmManager/keep alives.
Do you have a service as part of your application?
Related
I have problems with client/server application that is part of a bigger system for distributed computing. The clients are Android devices that run a native Android NDK application written in C. At some point the clients send registration messages to the server application, which is also written in C and runs on a windows machine.
The weird thing is, right after installing the Android application on the device everything works fine. However, after a while the Socket problem starts. All connect() function calls end with a time out on the client side. The error is not deterministic and occurs at different points in time. To make it work again, I have to uninstall the application in Android manually and reinstall it. After that I works for some time and then the error starts again. The same C code is used on clients that run on normal windows PCs and there the problem does not occur.
The network connection is fine and I checked, if the server ports are open and reachable with the Simple Socket Tester app from the client device. I also gave Android the permission for Internet use and the parameters of the connect() call are correct.
EDIT:
Sorry for the missing code. I thought the error is obvious and based on the different platforms, since it works on windows and I am not that experienced in Android NDK. Here is the code:
int pi_connect(SOCKET s, const SOCKADDR *name, int namelen)
{
int result = connect(s, name, namelen);
if (result < 0) {
ALOG("Socket connecting error!");
return -1;
}
return result;
}
SOCKET pi_socket(int af, int type, int protocol) {
SOCKET returnSocket = socket(af, type, protocol);
int yes = 1;
if (setsockopt(returnSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error!");
exit(1);
}
if (returnSocket < 0) {
ALOG("Socket creation error!");
return -1;
}
return returnSocket;
}
SOCKET setupSendSocket(u_long host, int hostPort) {
SOCKET sendingSocket;
SOCKADDR_IN addr;
sendingSocket = pi_socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(hostPort);
addr.sin_addr.s_addr = host;
long rc = pi_connect(sendingSocket, (SOCKADDR*) &addr, sizeof(SOCKADDR));
if (rc < 0) {
return 0;
}
return sendingSocket;
}
void requestOwnIP() {
SOCKET connectedIPSocket = setupSendSocket(inet_addr(brokerIP), 34123);
if(connectedIPSocket==0)
return;
sendBHeartbeatMessage(connectedIPSocket);
myIP = receiveBIPMessage(connectedIPSocket);
pi_closesocket(connectedIPSocket);
}
The requestOwnIP() function is called in the main function of the NDK application.
EDIT 2 (some new remarks): After rebooting the device, the connect() is successful again and the system works for some time. Is there something stored in the process table of the operating system, that can cause this problem? I first though that it could be a high amount of sockets that are in the time_wait state, but I added SO_REUSEADDR and the problem is still occurring.
I would really appreciate some help. Thank you in advance!
Regards
Dominik
I am using JNI with Android Studio 1.5.1 targeting Android API 18 and my question is:
Q) Without using a tool or changing/modifying the Dalvik VM source code, how can I find the memory address of a Java local variable on the Dalvik Stack from native code?
For example, I try to use the following code (adapted from the Internet) to find the memory address of a Java local variable magicNumber = 0x23420023 but I am getting segmentation fault errors.
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("MyLibrary");
}
public native boolean findMagicNumber(int pid, int tid);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int magicNumber = 0x23420023 ;
int pid = android.os.Process.myPid();
int tid = android.os.Process.myTid();
findMagicNumber(pid, tid);
}
}
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "com_example_magicnumber2_MainActivity.h"
#include <unistd.h>
#include <memory.h>
#define ENOENT 2 /* No such file or directory */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define EINVAL 22 /* Invalid argument */
jboolean validAddress(char* address)
{
if ((access(address, F_OK)==-1) && !(errno == ENOENT) && !(errno == ENAMETOOLONG))
return JNI_FALSE;
else if ((access(address, F_OK)==-1) && (errno == ENOMEM) ||
(access(address, F_OK)==-1) && (errno == EACCES) ||
(access(address, F_OK)==-1) && (errno == EFAULT) ||
(access(address, F_OK)==-1) && (errno == EINVAL))
return JNI_FALSE;
else if (address == NULL)
return JNI_FALSE;
else
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_example_magicnumber2_MainActivity_findMagicNumber(JNIEnv *env, jobject obj, jint pid, jint tid) {
long long startaddr, endaddr, size, offset, inode;
char permissions[8], device[8], filename[200], line[250];
char *start, *end, *candidate;
int result, i = 0;
char filepath[100];
sprintf(filepath,"/proc/%d/task/%d", pid, tid);
FILE* file = fopen(filepath, "r");
jboolean found = JNI_FALSE;
while (fgets(line, sizeof(line), file) && !found) {
sscanf(line,"%llx-%llx %s %llx %s %llx", &startaddr, &endaddr, permissions, &offset, device, &inode);
start = startaddr;
end = endaddr;
mprotect( (void*)start , (end-start), PROT_READ);
candidate = memchr( start, 0x14, (end-start));
while( validAddress(candidate) && !found){
if ((validAddress(candidate[2]) && (candidate[2]== 0x23)) &&
(validAddress(candidate[3]) && (candidate[3] == 0x00)) &&
(validAddress(candidate[4]) && (candidate[4] == 0x42)) &&
(validAddress(candidate[5]) && (candidate[5] == 0x23))){
__android_log_print(ANDROID_LOG_DEBUG,"***","Location=%p WE FOUND IT!", candidate);
found = JNI_TRUE;
break;
return JNI_TRUE;
}
else if ((validAddress(candidate)) &&
validAddress(candidate=memchr(candidate+1, 0x14, (end-candidate)))){;
}
}
}
}
This is an update:
The previous code that I posted was not the latest one, here is the latest one:
The Java Code:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("MyLibrary");
}
public native boolean findMagicNumber(int pid, int tid);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int magicNumber = 0x23420023 ;
int pid = android.os.Process.myPid();
int tid = android.os.Process.myTid();
findMagicNumber(pid, tid);
System.out.println("magicNumber = " + magicNumber );
}
}
The native Code:
JNIEXPORT jboolean JNICALL Java_com_example_magicnumber2_MainActivity_findMagicNumber(JNIEnv *env, jobject obj, jint pid, jint tid) {
long long startaddr, endaddr, size, offset, inode;
char permissions[8], device[8], filename[200], line[250];
char *start, *end, *candidate;
int result, i = 0;
char filepath[100];
sprintf(filepath,"/proc/%d/task/%d/maps", pid, tid);
FILE* file = fopen(filepath, "r");
jboolean found = JNI_FALSE;
while (fgets(line, sizeof(line), file) && !found) {
sscanf(line,"%llx-%llx %s %llx %s %llx %s", &startaddr, &endaddr, permissions, &offset, device, &inode, filename);
if (((strstr(filename, "apk#classes.dex")))==NULL) {
continue;
}
__android_log_print(ANDROID_LOG_DEBUG, "*****************", "%llx-%llx %s %llx %s %llx %s",
startaddr, endaddr, permissions, offset, device, inode, filename);
start = startaddr;
end = endaddr;
candidate = memchr( start, 0x14, (end-start));
while( candidate !=0 && !found){
if ((candidate[2]== 0x23) &&
(candidate[3] == 0x00) &&
(candidate[4] == 0x42) &&
(candidate[5] == 0x23)){
__android_log_print(ANDROID_LOG_DEBUG,"********************************************************************","WE FOUND IT at %p!!!", candidate);
found = JNI_TRUE;
break;
}
else
candidate=memchr(candidate+1, 0x14, (end-candidate));
}
}
}
This code is working and it can find the magic number but it finds it in the memory region mapped to /data/dalvik-cache/data#app#com.example.magicnumber2-1.apk#classes.dex which is not the Dalvik stack.
However, by running the above code and by looking at these two papers : paper1 (appendix B, only the egg-hunting code, I do not need to change any Dalvik code, so skip the code changing part) and paper2, we can notice the following (also to comments on fadden's remarks below):
(1) It seems that the int value magicNumber is stored in one Dalvik register. Also it seems that it is stored in the Dalvik stack and it is not on the native code stack because the int variable magicNumber is declared and assigned a value in the Java code section.
(2) According to the paper1, this answer and as evidence by running the attached latest code, we are not searching for 0x14 using the memchr function but we want to make sure we are at the beginning of a memory cell that store the int in ARM CPUs.
(3) I do not need to call the findMagicNumber function again. I just need to find the memory address of the magic number in the Dalvik stack
(4) I do not need to find nearby variables to the MagicNumber, so this is not a problem in my case.
(5) The project is targeting only Dalvik, so ART is not a problem
(6) I agree, using mprotect() is not a good idea and was not necessary in my case.
(7) If you refer to paper2, you can see that access() can be used for something that it is not designed for, checking if a virtual memory address is valid or not. I’m not using access() for any file related operations, although it was written for that purpose
(8) I do not need to change the variable. I just need the address of the variable magicNumber on the Dalvik stack programmatically without using any tool or changing the Dalvik source code
I want to know which of the memory regions of /proc/pid/task/tid/maps Dalvik uses to store its stack.
As you can see in paper1, the authors in section B.2, line #4, did not explain which memory region from procs/maps they used to assign the start and end variables their values.
It looks like you're trying to open /proc/[pid]/task/[tid]/maps, walk through the map, and manually scan through every address range for a magic number. Setting aside the fact that you're opening the task directory rather than the maps magic file in that directory, this approach has a few problems:
You're not guaranteed that the value is unique. If it appears somewhere else in memory -- perhaps because the value was stored in two different Dalvik registers -- you'll be in the wrong place. If the JIT compiler has compiled this stretch of code, you don't know if the "active" value will be on the managed stack or in a spilled register on the native stack.
You're searching for 0x14, which isn't part of your magic number.
You're scanning for the local variable on the thread that created it. Even if you find it and can change it, once the findMagicNumber method returns, the stack-allocated variable will disappear. It's not guaranteed to be in the same place if the method is called again.
If you were hoping to find related variables nearby, you will again have trouble if the JIT compiler rearranges things.
ART compiles almost everything ahead of time, so this is even less likely to be useful there.
I'm also not sure why you're calling mprotect(), rather than simply skipping the segments that aren't readable. You're forcing the permissions to read-only, disabling write and execute permission, which will cause you to crash when execute permission is disabled for the chunk of code that's executing, or when a thread tries to execute and touches its stack.
The access() system call takes a filename, not a memory address, and reports file permissions. I don't think there's an "is this address valid" call, but since you just sscanf'ed the map entry you shouldn't need one.
The only reliable way to find and change the value of a local variable is to use the JDWP debug interface. The compiler and debugger support work together to make reliable read-write access to local variables possible.
To sum up: the code is seriously broken, the approach is unsound. What problem are you trying to solve?
I'm trying to communicate between Arduino Mega Adk (ADK 2011) and android device.
Something goes ok, but something goes completely wrong.
Transfer data from Android to Arduino via acc.read from Arduino side works fine.
But when i try to send some bytes from Arduino to Android - something strange happens.
First of all here is Arduino sketch:
#include <Max3421e_constants.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
#define COMMAND_LED 0x2
#define TARGET_PIN_18 0x12
#define TARGET_PIN_19 0x13
#define V_ON 0x1
#define V_OFF 0x0
#define PIN_18 18
#define PIN_19 19
#define INPUT_PIN 30
AndroidAccessory acc("Google, Inc.",
"DemoKit",
"Ololo device board",
"1.0",
"http://www.android.com",
"0000000012345678");
byte rcvmsg[3];
byte sndmsg[3];
int buttonState = 0;
void setup();
void loop();
void led_setup(){
pinMode(PIN_18, OUTPUT);
pinMode(PIN_19, OUTPUT);
pinMode(INPUT_PIN, INPUT);
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\nStart");
led_setup();
acc.powerOn();
}
void loop()
{
if (acc.isConnected()) {
buttonState = digitalRead(INPUT_PIN);
if (buttonState == 1){
sndmsg[0] = 0x2;
sndmsg[1] = 0x1;
sndmsg[2] = 0x1;
int len = acc.write(sndmsg, 3);
digitalWrite(PIN_19, HIGH);
}
else {
//Nothing here for test
}
}
//usefull test for button
buttonState = digitalRead(INPUT_PIN);
if (buttonState == 1){
digitalWrite(PIN_19, HIGH);
}
else {
digitalWrite(PIN_19, LOW);
}
}
Ok. When acc.write() is executed it takes up to ~1 second to transfer data to android. And this time doesn't depend on number of bytes in sndmsg. Only if i execute acc.write(sndmsg,0) (sending 0 bytes) - everything goes fast.
That is a little bit disturbing. I've tried to change board to another one but have got the same result.
Any advices? may be that is a common bug, but there is no such much information in web.
UPD:
Wrote some very simple code, that only sends 3 bytes via acc.write.
here it is:
#include <Max3421e_constants.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
AndroidAccessory acc("Google, Inc.",
"DemoKit",
"Demokit board",
"1.0",
"http://www.android.com",
"0000000012345678");
byte msg[3];
unsigned long time;
void setup();
void loop();
void led_setup(){
}
void setup()
{
Serial.begin(115200);
Serial.print("\r\nStart");
acc.powerOn();
}
void loop()
{
if (acc.isConnected()) {
Serial.print("\r\nis Connected");
msg[0] = 0x1;
msg[1] = 0x1;
msg[2] = 0x1;
//Serial.print("\r\nSending");
time = millis();
Serial.print ("\r\nBefore write\r\n");
Serial.print (time);
acc.write(msg, 3);
time = millis();
Serial.print("\r\nAfter write: \r\n");
Serial.print (time);
//delay(500);
}
}
And it's debug output is:
is Connected
Before write
6983
After write:
10958
is Connected
Before write
10958
After write:
14491
is Connected
and so on. So on some reasons acc.write takes a lot of time and there is no data in the android app.
New UPD (19.01.2015):
Today i've performed some experiments. Here are results.
First, i've looked into AndroidAccessory.cpp and found write function:
int AndroidAccessory::write(void *buff, int len)
{
usb.outTransfer(1, out, len, (char *)buff);
return len;
}
Ok, then i looked into usb host shield library and found there usb.cpp with outTransfer fucntion, that returns error code if ouccured and 0x00 if everything is ok.
So i modified write function to return an error code instead of lenght, like this:
int AndroidAccessory::write(void *buff, int len)
{
byte rcode;
rcode = usb.outTransfer(1, out, len, (char *)buff);
return int(rcode);
}
and recived "4" as result.
According to MAX3421Econstants.h it is hrNAK (0x04) error code.
Any ideas? Looks like accessory does not recive NAKs from Android and write fails as a result.
Situation update:
Did some research. There is a hell of NAK's when accessory is connected. Here is dump from usb connector:
i found the solution. And it is very simple - i didn't setup communication with accessory correctly.
This is not an Arduino problem. Arduino works fine.
It is just how android interacts with android accessory.
So, results:
When AndroidAccessory is plugged to Android and Android haven't setup
communication with the accessory yet, Android OS will send a lot of
USB NAKs to the accessory and this is normal.
You must be careful
during setuping communication with the accessory. If you make some
mistakes, you can receive same situation: Probably possible to write
to the accessory, but accessory isn't possible to write to the
android.
If UsbManager opens accessory correctly, it stops sending
NAKs and starts recieve data from arduino.
It is a little bit strange for me, because it was really hard to found a problem: i have an application, written according to this manual: http://developer.android.com/guide/topics/connectivity/usb/accessory.html But, because i'm not very familiar with android, it seems that i've done some mistakes and receive strange behavior:
i was able to write to arduino
i was able to retrive information about arduino as android accessory
it was possible to ask for permissions
but when arduino tries to write to android, it recievs a lot of NAKs
So i decided to rewrite program in more simple way, just with one function and tried to do it in right way. And after some debugging it finally started to work as i want.
So thank everyone, who spend time for reading this.
Bonus: dump of normal packet, ended with EOP not NAK
UPD 26.01.2015:
I found problem and it was in my android code.
here is explanation:
Android developer's manual said that function, which set up communication with accessory must start it's own thread in which all communications with input and output streams are held. Smth like this:
private void openAccessory() {
Log.d(TAG, "openAccessory: " + accessory);
mFileDescriptor = mUsbManager.openAccessory(mAccessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "AccessoryThread");
thread.start();
}
}
I really messed this thing up. Forgot about creating new thread in openAccessory function and tried to do it in different place. And recieve a hell of NAK's. Then i've changed my code and add some debug-like run() function like this:
public void run() {
final byte[] buffer = new byte[16384];
int ret = 0;
int i = 0;
while (i<50) {
try {
ret = mInputStream.read(buffer);
i++;
Thread.sleep(500);
} catch (IOException e) {
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And until this run method exists (while i < 50) android reads arduino correctly. And when thread ends up (i > 50) - Arduino starts to readout Error Code 4 (NAK) from Android.
That's all folks.
I am trying to trim video using ffmpeg lib. Video Trimming is success first time but it crash second time.
For solving this crash, i search for it and use the dlopen() and dlclose() for dynamic loading for ffmpeg lib.
my code is-
const char* path;
void* handle;
void* handle1;
const char *in, *out;
int close;
__android_log_write(ANDROID_LOG_ERROR, "VideoTrimmer Invoke", "Video Trimmer Invoke");
in = (*env)->GetStringUTFChars(env, inputFile, 0);
out = (*env)->GetStringUTFChars(env, outFile, 0);
int *(*Java_com_videotrimmingwithnativesample_VideoTrimmer_trim)(JNIEnv*, jclass ,jstring inputFile, jstring outFile, jint startTime, jint length);
path = (*env)->GetStringUTFChars(env, libffmpegPath, 0);
handle = dlopen(path, RTLD_LAZY);
if(!handle)
{
__android_log_write(ANDROID_LOG_ERROR, "VideoTrimmer Invoke HAndle false", dlerror());
}
else
{
__android_log_write(ANDROID_LOG_ERROR, "VideoTrimmer Invoke HAndle True", dlerror());
}
Java_com_videotrimmingwithnativesample_VideoTrimmer_trim = dlsym(handle, "Java_com_example_videotrimmingwithnativesample_VideoTrimmer_trim");
if(!Java_com_videotrimmingwithnativesample_VideoTrimmer_trim)
{
__android_log_write(ANDROID_LOG_ERROR, "VideoTrimmer Invoke dlsym false",dlerror());
}
else
{
__android_log_write(ANDROID_LOG_ERROR, "VideoTrimmer Invoke dlsym true","Video TrimmerInvoke dlsym true");
}
int i=(*Java_com_videotrimmingwithnativesample_VideoTrimmer_trim)(env, obj, inputFile,outFile,startTime,length);
if(dlclose(handle)==0)
{
(*env)->ReleaseStringUTFChars(env, libffmpegPath, path);
__android_log_write(ANDROID_LOG_ERROR, "VideoTrimmer Invoke close true","Video TrimmerInvoke close true");
}
Error on second time use show on dlopen line --
Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), (IntentService[V)
Please help me for removing this crash.
Thanks in advance.
I am using FFmpeg 3.6.6 to build my application and with the same problem. According to my debugging experience ,it happen because the variable "nb_filtergraphs" is not the initial value any more but variable "filtergraphs" is, when this method is executed it will crash the system
static int init_complex_filters(void){
int i, ret = 0;
for (i = 0; i < nb_filtergraphs; i++) {
ret = init_complex_filtergraph(filtergraphs[i] //crash here);
if (ret < 0)
return ret;
}
return 0;}
the origin call chain is ffmpeg#main(you might change this function name) -> ffmpeg_opt#ffmpeg_parse_options -> ffmpeg_opt#init_complex_filters
My solution is to call the following code after the main method is executed
ffmpeg.c
int main(int argc, char **argv)//you might change the name {
//.....
ffmpeg_cleanup(received_nb_signals ? 255 : main_return_code);
nb_filtergraphs = 0;
progress_avio = NULL;
input_streams = NULL;
nb_input_streams = 0;
input_files = NULL;
nb_input_files = 0;
output_streams = NULL;
nb_output_streams = 0;
output_files = NULL;
nb_output_files = 0;
exit_program(received_nb_signals ? 255 : main_return_code);
return main_return_code;
}
Your problem may be related to discussion here
The linked thread is old but symptom there was that android/JNI call to ffmpeg worked first time but not the second time.
As noted in the thread, the solution is to explicitly unload/load the library in between successive calls to ffmpeg.
you could try it.
Just make a method in your ffmpeg.c which will seems like this
void exitmycode(){
ffmpeg_exit(0);
}
ffmpeg_exit(0) method is already there in the ffmpeg.c you just have to call exitmycode(); from your main C file after the completion of video trimming.
Now what was happening is that when you trim a video or anything else with the ffmpeg it doesn't get exit completely, so the next time you run the command it get exited, but it also don't run your trim command.Again if you run that third time, command get executed perfectly. So, what I had done is calling the ffmpeg_exit(0) manually at the end of processing done.
The issue is that ffmpeg uses static variables which are not reinitialized when the first run is complete. On the second run, they still have their values, so ffmpeg fails to initialize itself, and crashes.
You have two possibilites: either unload/reload your library between each run, or modify ffmpeg source code to reset these variables.
I write the Android application using libusb-1.0.9 and NDK (Android 4.0.4+) which has to read out audio-data from the USB-audiocard. The USB device from libusb opens successfully, and for it it is possible to receive all interfaces/EndPoint list. But when making ISOC transfer I faced with following unclear me error:
Debugging C code of making transfer:
static uint8_t buf[12];
static void cb_xfr(struct libusb_transfer *xfr)
{
LOGD("USB callback\n");
libusb_free_transfer(xfr);
}
JNIEXPORT jlong JNICALL
Java_com_usbtest_libusb_Libusb_makeISOCTransfer(JNIEnv *env, jobject this, jlong ms)
{
static struct libusb_transfer *xfr;
int num_iso_pack = 1;
unsigned char ep = 0x84;
xfr = libusb_alloc_transfer(num_iso_pack);
if (!xfr) {
LOGD("libusb_alloc_transfer: errno=%d\n", errno);
return -1000;
}
LOGD("libusb_fill_iso_transfer: ep=%x, buf=%d, num iso=%d\n", ep, sizeof(buf), num_iso_pack);
libusb_fill_iso_transfer(xfr, handle, ep, buf, sizeof(buf), num_iso_pack, cb_xfr, NULL, 0);
libusb_set_iso_packet_lengths(xfr, sizeof(buf)/num_iso_pack);
int res = libusb_submit_transfer(xfr);
LOGD("libusb_submit_transfer: %d, errno=%d\n", res, errno);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
libusb_handle_events_timeout(NULL, &tv);
return res;
}
After a call of libusb_submit_transfer I received a mistake: libusb_submit_transfer: -1, errno -2
And text messages:
need 1 32k URBs for transfer
first URB failed, easy peasy
EndPoint 0x84 is true for audio-in. The buf[] size = 12 - corresponds to the field wMaxPacketSize of this EndPoint. I request 1 transfer. Field of xfr->status = 0, but callback isn't caused.
I thought that it is necessary to increase the buf buffer to 32K - I increased, but it didn't help.
I tried to increase quantity of transfers. Same error.
Prompt me please in what there can be a error?
I found the solution of this problem.
In this topic http://en.it-usenet.org/thread/14995/14985/ there was a similar question, and the decision appeared to make detach for device HID USB interfaces.
I've used libusb_detach_kernel to detach the 2 hid drivers and submit
transfer returned 0!!
I made libusb_detach_kernel_driver(handle, interface) for all interfaces of the device (0..3) after device opening, and as a result of libusb_submit_transfer return SUCCESS of transfer.