I have integrated ffmpeg lib in my project and I can also get the information of media files. But now i have to play mp3 files using AudioTrack class in android using ffmpeg lib.
For this I have to pass byte buffer to AudioTrack but I dont know how to get byte buffer from ffmpeg and use it with AudioTrack. I also want to play file instantly without delay.
Here is my audio track code in java :
AudioTrack track;
bufferSize = AudioTrack.getMinBufferSize(44100,AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT)
track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize, mode);
//Play audio clip
track.play();
while(stream_is_over){
//Copy the decoded raw buffer from native code to "buffer" .....
............
track.write(buffer, 0, readBytes);
}
Can anyone please give me the working code to play mp3 files with audio track. I have searched a lot but haven't find any correct answer.
I managed this by creating buffer of audio files and then playing it with AudioTrack class on the fly.
Now i'm trying to pause/stop the audio file cause stopping or pausing AudioTrack is not working.
Here is my code to pass byte buffer to my java class :
#include <assert.h>
#include <jni.h>
#include <string.h>
#include <android/log.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#define LOG_TAG "mylib"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
void Java_ru_dzakhov_ffmpeg_test_MainActivity_createEngine(JNIEnv* env,
jclass clazz) {
avcodec_init();
av_register_all();
}
jstring Java_ru_dzakhov_ffmpeg_test_MainActivity_loadFile(JNIEnv* env,
jobject obj, jstring file, jbyteArray array) {
{
jboolean isfilenameCopy;
const char * filename = (*env)->GetStringUTFChars(env, file,
&isfilenameCopy);
int audioStreamIndex;
AVCodec *codec;
AVCodecContext *c = NULL;
AVFormatContext * pFormatCtx;
AVCodecContext * aCodecCtx;
int out_size, len, audioStream = -1, i, err;
FILE *f, *outfile;
uint8_t *outbuf;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID play = (*env)->GetMethodID(env, cls, "playSound", "([BI)V"); //At the begining of your main function
LOGE("source file name is %s", filename);
avcodec_init();
av_register_all();
LOGE("Stage 1");
/* get format somthing of source file to AVFormatContext */
int lError;
if ((lError = av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL))
!= 0) {
LOGE("Error open source file: %d", lError);
exit(1);
}
if ((lError = av_find_stream_info(pFormatCtx)) < 0) {
LOGE("Error find stream information: %d", lError);
exit(1);
}
LOGE("Stage 1.5");
LOGE("audio format: %s", pFormatCtx->iformat->name);
LOGE("audio bitrate: %d", pFormatCtx->bit_rate);
audioStreamIndex = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO,
-1, -1, &codec, 0);
LOGE("audio codec: %s", codec->name);
/* get codec somthing of audio stream to AVCodecContext */
aCodecCtx = pFormatCtx->streams[audioStreamIndex]->codec;
if (avcodec_open(aCodecCtx, codec) < 0) {
LOGE("cannot open the audio codec!");
exit(1);
}
printf("Audio decoding\n");
LOGE("Stage 1.7");
LOGE("S");
codec = avcodec_find_decoder(aCodecCtx->codec_id);
LOGE("Stage 1.8");
if (!codec) {
LOGE("codec not found\n");
exit(1);
}
LOGE("Stage 2");
// c= avcodec_alloc_context();
LOGE("Stage 3");
/* open it */
if (avcodec_open(aCodecCtx, codec) < 0) {
LOGE("could upper");
fprintf(stderr, "could not open codec\n");
LOGE("could not open codec");
}
LOGE("Stage 4");
outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "could not open %s\n", filename);
LOGE("could not open");
exit(1);
}
/* decode until eof */
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
LOGE("Stage 5");
while (avpkt.size > 0) {
// LOGE("Stage 6");
out_size = (AVCODEC_MAX_AUDIO_FRAME_SIZE / 3) * 2;
len = avcodec_decode_audio3(aCodecCtx, (int16_t *) outbuf,
&out_size, &avpkt);
LOGE("data_size %d len %d", out_size, len);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
LOGE("DECODING ERROR");
LOGE("DECODING ERROR %d", len);
exit(1);
}
// LOGE("Stage 7");
if (out_size > 0) {
/* if a frame has been decoded, output it */
// LOGE("Stage 8");
jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
memcpy(bytes, outbuf, out_size); //
(*env)->ReleaseByteArrayElements(env, array, bytes, 0);
(*env)->CallVoidMethod(env, obj, play, array, out_size);
// LOGE("DECODING ERROR5");
}
LOGE("Stage 9");
avpkt.size -= len;
avpkt.data += len;
if (avpkt.size < AUDIO_REFILL_THRESH) {
/* Refill the input buffer, to avoid trying to decode
* incomplete frames. Instead of this, one could also use
* a parser, or use a proper container format through
* libavformat. */
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
AUDIO_INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}
}
LOGE("Stage 12");
fclose(f);
free(outbuf);
avcodec_close(c);
av_free(c);
}
}
I have no clue about programming in android, but google just introduced a new low-level media api at I/O 2012
Here's the link to the yt video: http://www.youtube.com/watch?v=YmCqJlzIUXs
Related
I am trying to set the baud-rate of "/dev/ttyS4" and return the Text(EditText) using C code with the help of JNI in android studio
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#define DEBUG 1
#if DEBUG
#include <android/log.h>
# define D(x...) __android_log_print(ANDROID_LOG_INFO,"hello-jni",x)
#else
# define D(...) do {} while (0)
#endif
char* str;
char buffer[512];
extern "C" JNIEXPORT jstring JNICALL
Java_com_android_uart_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */, jstring text)
{
{
asprintf(&str, "Hi\n");
strlcpy(buffer, str, sizeof buffer);
free(str);
int ttyFD = 0;
struct termios tty;
const char *stringInC = env->GetStringUTFChars(text, NULL);
auto SampleCmd = stringInC;
int i_WriteBytes = 0;
memset (&tty, 0, sizeof tty);
ttyFD = open("/dev/ttyS4", O_RDWR| O_NONBLOCK | O_NDELAY );
if(ttyFD < 0)
{
asprintf(&str, "Error in opening /dev/ttyS4\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
else
{
asprintf(&str, "ttyS4 port opened successfully\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
if (tcgetattr ( ttyFD, &tty ) != 0 )
{
asprintf(&str, "Error from tcgetattr\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
cfsetspeed(&tty, B0);
tty.c_cflag &= ~PARENB; /* parity */
tty.c_cflag &= ~CSTOPB; /* stop bits */
//tty.c_cflag &= ~CSIZE; /* */
tty.c_cflag |= CS8; /* data bits */
tty.c_cflag &= ~CRTSCTS; /* no hardware flow control */
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* no s/w flow ctrl */
tty.c_lflag = 0; /* non canonical */
tty.c_oflag = 0; /* no remapping, no delays */
tty.c_cc[VMIN] = 0; /* read doesn't block */
tty.c_cc[VTIME] = 0; /* read timeout */
tty.c_cflag |=
CREAD | CLOCAL; /* turn on READ & ignore ctrl lines */
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* */
//tty.c_oflag &= ~OPOST; /* */
tcflush(ttyFD, TCIFLUSH);
if (tcsetattr(ttyFD, TCSANOW, &tty) != 0) {
asprintf(&str, "Error from tcsetattr\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
i_WriteBytes = write(ttyFD, SampleCmd, sizeof(SampleCmd) - 1);
asprintf(&str, "written bytes = %d\n", i_WriteBytes);
strlcat(buffer, str, sizeof buffer);
free(str);
if (i_WriteBytes < 0) {
asprintf(&str, "failed to write value on port\n");
strlcat(buffer, str, sizeof buffer);
free(str);
}
sleep(1);
char read_buf[1024];
memset(&read_buf, '\0', sizeof(read_buf));
int num_bytes = read(ttyFD, &read_buf, sizeof(read_buf));
if (num_bytes < 0) {
asprintf(&str, "Error reading: %s", strerror(errno));
strlcat(buffer, str, sizeof buffer);
free(str);
}
asprintf(&str, "Read bytes = %i \n Received message: %s", num_bytes, read_buf);
strlcat(buffer, str, sizeof buffer);
free(str);
close(ttyFD);
return env->NewStringUTF(buffer);
}
My problem is that WriteBytes and Read bytes only take 7 bytes of the edittext"Text" and it only display 7 characters of it.
What i want is to display the entire "Text" from the EditText.
This is the result iam getting:
**Input:**
EditText(baud Rate)=0
EditText(message) =this is a test app
**Output:**
TextView(Details)
hi
ttyS4 port opened successfully
written bytes = 7
Read bytes =7
Received message:this is
The line
i_WriteBytes = write(ttyFD, SampleCmd, sizeof(SampleCmd) - 1);
is wrong.
Variable SampleCmd, defined as
const char *stringInC = env->GetStringUTFChars(text, NULL);
auto SampleCmd = stringInC;
is of type int in C or type const char * in C++. (Note that auto is an old keyword in C which defines a storage class is the default for variables inside functions and forbidden at file scope. As you don't specify a type, it defaults to int.)
The value sizeof(SampleCmd) is not related to the length of the string pointed to by stringInC. It is the size of a variable of type int (in C, or type char* in C++). Apparently this size is 8 on your platform, so you will always write 7 bytes.
You could use
i_WriteBytes = write(ttyFD, SampleCmd, strlen(SampleCmd));
or use fdopen on ttyFD and use output functions from stdio.h.
I'm following this article to implement android linux kernel communicate with user space.
I use insmod kernel to insert my kernel to Android avd goldfish kernel, then I use cat /proc/kmsg to observe the kernel message, but I find the program doesn't execute as intended. Here is my code:
void hello_nl_recv_msg(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
char *msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %sn", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr *)skb->data;
printk(KERN_INFO "Netlink received msg payload:%sn", (char *)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out)
{
printk(KERN_ERR "Failed to allocate new skbn");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0)
printk(KERN_INFO "Error while sending bak to usern");
}
int init_module()
{
printk("Entering: %sn", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
printk("%s",nl_sk);
// nl_sk = netlink_kernel_create(NETLINK_USER, input);
//if (!nl_sk)
//{
// printk(KERN_ALERT "Error creating socket.n");
// return -10;
//}
return 0;
}
I find when the program exec
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
The kernel returns -1 or other integer, and it can't execute the function "hello_ne_recv_msg". I use android avd, the kernel is goldfish 2.6. Please help me, thanks.
Here is my code (tested on sony z2 kernel).
Note: your code may still fail if seandroid (selinux) is enforced.
Beware of code copy pasting. Check it!
Don't ignore compilation warnings.
Kernel module:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <net/sock.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
static struct sock* nl_sk;
#define NETLINK_USER 31
void hello_nl_recv_msg(struct sk_buff* skb)
{
struct nlmsghdr* nlh;
int pid;
struct sk_buff* skb_out;
int msg_size;
char* msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr*)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s\n", (char*)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out) {
printk(KERN_ERR "Failed to allocate new skbn\n");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0) {
printk(KERN_INFO "Error while sending back to user\n");
}
}
int __init init_netlink_test(void)
{
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
if (!nl_sk) {
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
void __exit exit_netlink_test(void)
{
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
module_init(init_netlink_test);
module_exit(exit_netlink_test);
userspace test app:
#include <sys/socket.h>
#include <linux/netlink.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#define NETLINK_USER 31
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr* nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
int main()
{
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
if (sock_fd < 0) {
return -1;
}
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
/* interested in group 1<<0 */
bind(sock_fd, (struct sockaddr*)&src_addr,
sizeof(src_addr));
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0; /* For Linux Kernel */
dest_addr.nl_groups = 0; /* unicast */
nlh = (struct nlmsghdr*)malloc(
NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
strcpy(NLMSG_DATA(nlh), "Hello");
iov.iov_base = (void*)nlh;
iov.iov_len = nlh->nlmsg_len;
msg.msg_name = (void*)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
printf("Sending message to kernel\n");
sendmsg(sock_fd, &msg, 0);
printf("Waiting for message from kernel\n");
/* Read message from kernel */
recvmsg(sock_fd, &msg, 0);
printf(" Received message payload: %s\n",
NLMSG_DATA(nlh));
close(sock_fd);
}
I'm trying to share data between kernel and user space. The ultimate goal is to port it to Android, so I'm using unix domain sockets. (I don't know if this is the best option).
I have a kernel module acting as socket client and a c program acting as socket server. And vice-versa, a kernel module acting as socket server and a c program acting as socket client.
Programs are very simple. Servers just send a string to clients and they print it.
I run server_user.c and then I try to insert client_module.ko using insmod. I get the following error:
Kernel panic - not syncing: stack - protector: Kernel stack is corrupted in: ffffffffa0005157
drm-kms-helper: panic occurred, switching back to text console
What's wrong?
Module Server
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/un.h>
#include <net/sock.h>
#define SOCK_PATH "/tmp/usocket"
#define LISTEN 10
struct socket *sock = NULL;
struct socket *newsock = NULL;
static int __init server_module_init( void ) {
int retval;
char* string = "hello_world";
struct sockaddr_un addr;
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
// create
retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &sock);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
// bind
retval = sock->ops->bind(sock,(struct sockaddr *)&addr, sizeof(addr));
// listen
retval = sock->ops->listen(sock, LISTEN);
//accept
retval = sock->ops->accept(sock, newsock, 0);
//sendmsg
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iov->iov_base = string;
msg.msg_iov->iov_len = strlen(string)+1;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
retval = sock_sendmsg(newsock, &msg, strlen(string)+1);
set_fs(oldfs);
return 0;
}
static void __exit server_module_exit( void ) {
printk(KERN_INFO "Exit usocket.");
}
module_init( server_module_init );
module_exit( server_module_exit );
MODULE_LICENSE("GPL");
Module Client
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/un.h>
#include <linux/net.h>
#include <net/sock.h>
#include <linux/socket.h>
#define SOCK_PATH "/tmp/usocket"
#define MAX 100
struct socket *sock = NULL;
static int __init client_module_init( void ) {
int retval;
char str[MAX];
struct sockaddr_un addr;
struct msghdr msg;
struct iovec iov;
mm_segment_t oldfs;
printk(KERN_INFO "Start client module.\n");
// create
retval = sock_create(AF_UNIX, SOCK_STREAM, 0, &sock);
// connect
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, SOCK_PATH);
retval = sock->ops->connect(sock, (struct sockaddr *)&addr, sizeof(addr), 0);
// recvmsg
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_iov->iov_base= str;
msg.msg_iov->iov_len= strlen(str)+1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
retval = sock_recvmsg(sock, &msg, strlen(str)+1, 0);
set_fs(oldfs);
// print str
printk(KERN_INFO "client module: %s.\n",str);
// release socket
sock_release(sock);
return 0;
}
static void __exit client_module_exit( void )
{
printk(KERN_INFO "Exit client module.\n");
}
module_init( client_module_init );
module_exit( client_module_exit );
MODULE_LICENSE("GPL");
User Server
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "/tmp/usocket"
int send_msg_to_client(int socketfd, char* data) {
struct msghdr msg;
struct iovec iov;
int s;
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov.iov_base = data;
iov.iov_len = strlen(data)+1;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
s = sendmsg(socketfd, &msg, 0);
printf("after send - iov_base: %s, length: %d\n", (char *) msg.msg_iov->iov_base, (int) strlen(msg.msg_iov->iov_base));
if(s < 0){
perror("sendmsg");
return 0;
}
return s;
}
int main(int argc, char* argv[])
{
if (argc != 2) {
printf("Usage: $ %s <string>\n",argv[0]);
return 0;
}
int s, s2, len, slen;
socklen_t t;
struct sockaddr_un local, remote;
char* data = argv[1];
printf("print data: %s\n",data);
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
memset(&local, 0, sizeof(local));
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
slen = send_msg_to_client(s2, data);
if(slen < 0)
perror("send");
close(s2);
return 0;
}
User Client
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "/tmp/usocket"
#define MAX 100
int recv_msg_from_server(int socketfd, char data[MAX]) {
struct msghdr msg;
struct iovec iov;
int s;
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov.iov_base = data;
iov.iov_len = MAX;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
s = recvmsg(socketfd, &msg, 0);
printf("after recv - iov_base: %s, length: %d\n", (char *) msg.msg_iov->iov_base, (int) strlen(msg.msg_iov->iov_base));
if(s < 0){
perror("recvmsg");
}
return s;
}
int main(void)
{
int s, len, slen;
struct sockaddr_un remote;
char data[MAX];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("Trying to connect...\n");
memset(&remote, 0, sizeof(remote));
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
slen = recv_msg_from_server(s, data);
if (slen < 0) {
perror("recvmsg");
}
//printf("print data received > %s\n", data);
close(s);
return 0;
}
I have just faced a similar issue (with UNIX datagrams though), and I believe there is a bug in the unix_mkname() function which is part of the kernel: this function makes sure the sun_path field of the given sockaddr_un structure is always null terminated by adding a NUL character after the end of that field. Since this is the last field, it will corrupt the area (stack or heap) where that structure has been allocated.
The best solution is to patch that function in the kernel source code, so that it only sets to NUL the last character of the sun_path field. Meanwhile, you can make your code work by decreasing by 1 byte the size you give for the sockaddr_un structure:
Module Server
// bind
retval = sock->ops->bind(sock,(struct sockaddr *)&addr, sizeof(addr) - 1);
Module Client
retval = sock->ops->connect(sock, (struct sockaddr *)&addr, sizeof(addr) - 1, 0);
As I am using UNIX datagrams, I cannot really tell if it fixes the issue for bind() and connect(), but a least, it fixes it for sock_sendmsg().
#shu-suzuki: thanks for the leads.
After 5 years I came back here...
I again stucked with this problem and found that I did the same thing 5 years ago.
The cause is as in Tey's answer and the solution is OK (sutbract 1 from the length) but here's another solution.
What you can do is to use struct sockaddr_storage as struct sockaddr_un. As far as I read the kernel code this is what they use to handle bind system call from user space.
sockeaddr_storage is larger than sockaddr_un so kernel code can write beyond the sizeof(sockaddr_un).
The code should be like
struct sockaddr_storage addrStorage;
struct sockaddr_un* addr;
memset(&addrStorage, 0, sizeof(addrStorage));
addr = (struct sockaddr_un*)&addrStorage;
addr->sun_family = AF_UNIX;
strcpy(addr->sun_path, "/my/sock/name");
kernel_bind(listenSock, (struct sockaddr*)addr, sizeof(*addr));
This looks working for me.
hi I am trying to change the sample rate of the audio streams of a video file using ffmpeg. but i am not able to change audio of the original file. Till now i am able to read audio and video streams separately and can show its sample rate. Don't know how can i apply this effect permanently. Following is my Java code.
public class MainActivity extends Activity {
public static native float logFileInfo(String inputfilename);
static
{
System.loadLibrary("mylib");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv= new TextView(this);
String path= Environment.getExternalStorageDirectory().getPath();
path+="/test2_modified.mp4";
float x=logFileInfo(path);
String y=Float.toString(x);
tv.setText(y);
setContentView(tv);
}
and my native file
JNIEXPORT jfloat JNICALL Java_ru_dzakhov_ffmpeg_test_MainActivity_logFileInfo
(JNIEnv * env,
jobject this,
jstring filename
)
{
AVFormatContext *pFormatCtx;
int i, videoStream, audioStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVPacket packet;
int frameFinished;
float aspect_ratio;
AVCodecContext *aCodecCtx;
AVCodec *aCodec;
av_register_all();
char *str = (*env)->GetStringUTFChars(env, filename, 0);
LOGI(str);
// Open video file
if(av_open_input_file(&pFormatCtx, str, NULL, 0, NULL)!=0)
;
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
;
LOGI("Separating");
// Find the first video stream
videoStream=-1;
audioStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++) {
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
videoStream < 0) {
videoStream=i;
}
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
audioStream < 0) {
audioStream=i;
}
}
if(videoStream==-1)
LOGI("Video stream is -1");
;
if(audioStream==-1)
LOGI("Audio stream is -1");
;
//pFormatCtx->streams[audioStream]->codec->sample_rate=16000;
aCodecCtx=pFormatCtx->streams[audioStream]->codec;
//aCodecCtx->sample_rate=16000;
jfloat sr=aCodecCtx->sample_rate;
return sr;}
I am using the following standard code pasted below (ref: http://dranger.com/ffmpeg/) to use ffmpeg in android using ndk. My code is working fine in ubuntu 10.04 using gcc compiler. But I am facing an issue in android.The issue is av_read_frame(pFormatCtx, &packet) is always returning packet.stream_index=0. I have tested my code with various rtsp urls and I have the same behaviour in all cases. I do not have any linking or compiling issues as everything seems to be working fine except this issue. I am trying to solve this from last 2 days but I am stuck badly.Please point me in right direction.
#include <jni.h>
#include <android/log.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#define DEBUG_TAG "mydebug_ndk"
jint Java_com_example_tut2_MainActivity_myfunc(JNIEnv * env, jobject this,jstring myjurl) {
AVFormatContext *pFormatCtx = NULL;
int i, videoStream;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
int frameFinished;
AVDictionary *optionsDict = NULL;
struct SwsContext *sws_ctx = NULL;
jboolean isCopy;
const char * mycurl = (*env)->GetStringUTFChars(env, myjurl, &isCopy);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:p2: [%s]", mycurl);
// Register all formats and codecs
av_register_all();
avformat_network_init();
// Open video file
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:before_open");
if(avformat_open_input(&pFormatCtx, mycurl, NULL, NULL)!=0)
return -1;
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "start: %d\t%d\n",pFormatCtx->raw_packet_buffer_remaining_size,pFormatCtx->max_index_size);
(*env)->ReleaseStringUTFChars(env, myjurl, mycurl);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:before_stream");
// Retrieve stream information
if(avformat_find_stream_info(pFormatCtx, NULL)<0)
return -1;
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_stream");
// Find the first video stream
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream=i;
break;
}
if(videoStream==-1)
return -1; // Didn't find a video stream
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_videostream");
// Get a pointer to the codec context for the video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_codec_context");
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_decoder");
if(pCodec==NULL)
return -1;
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:found_decoder");
// Open codec
if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0)
return -1;
// Allocate video frame
pFrame=avcodec_alloc_frame();
sws_ctx = sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width,
pCodecCtx->height,PIX_FMT_YUV420P,SWS_BILINEAR,NULL,NULL,NULL);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:before_while");
int count=0;
while(av_read_frame(pFormatCtx, &packet)>=0) {
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "entered while: %d %d %d\n", packet.duration,packet.stream_index,packet.size);
if(packet.stream_index==videoStream) {
// Decode video frame
//break;
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,&packet);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:in_while");
if(frameFinished) {
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:gng_out_of_while");
break;
}
}
// Free the packet that was allocated by av_read_frame
av_free_packet(&packet);
if(++count>1000)
return -2; //infinite while loop
}
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK:after_while");
// Free the YUV frame
av_free(pFrame);
// Close the codec
avcodec_close(pCodecCtx);
// Close the video file
avformat_close_input(&pFormatCtx);
return 0;
}
I have same problam too.
after my test, I'v found my mistake, Hopes can help you.
my av_read_frame() also always return av_pkg of stream index 0;
The problem is: I mixed two version of ffmpeg libs.
At before, I'v install the ffmpeg of 0.9.x
Now, I install ffmpeg of 1.2
the libs are in different version.I used some lib from 0.9.x and others from 1.2.
So... error occur.
I solution:
uninstall all version of ffmpeg , and then reinstall one version of ffmpeg(me->1.2).
The av_read_frame() goes right. :)