0

I am designing an android app where i receive live mp3 data as stream from Red5 server and i need to play it.

I cant play it using media player class as i don't have any url for the stream, nor i cant use files. Another option is to use Audio track class, but requires PCM data only. So need to convert mp3 to pcm, so using ffmpeg.

My code for conversion is

AVCodec *codec;
AVCodecContext *c= NULL;
int out_size, len;
uint8_t *outbuf;

int iplen=(*env)->GetArrayLength(env, mp3buf);
int16_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
av_init_packet(&avpkt);
av_register_all();
avcodec_register_all();

codec = avcodec_find_decoder(CODEC_ID_MP3);
if(!codec){
    __android_log_print(ANDROID_LOG_DEBUG, "logfromjni", "Codec not found");
}
c = avcodec_alloc_context();
outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
avpkt.data = (*env)->GetByteArrayElements(env,mp3buf,NULL);

avpkt.size = (*env)->GetArrayLength(env, mp3buf);
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
int ao=avcodec_open(c, codec);
    if (ao < 0) {
        __android_log_print(ANDROID_LOG_DEBUG, "logfromjni", "avcodec not open");
    }
    len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);

The Problem is avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt); returns -1 always.

Cant figure out whats wrong.

Any help appreciated.

Ichigo Kurosaki
  • 3,765
  • 8
  • 41
  • 56
  • To find the cause of the error, try to see the ffmpeg output. If on the device is difficult to do, you can redirect the ffmpeg output and perform logging by own callback (see `av_log_set_callback` and `av_log_set_level`) – pogorskiy Jan 31 '14 at 13:06

1 Answers1

0

MP3 is a frame-based format, so you need to pass a complete frame to decode_audio3 for it to produce a meaningful result. It is not like zlib, which you can feed up with chunks of data of any size (even 1 byte) and eventually get some output. Make sure that:

  • Your server sending the data in proper frames;
  • You handle those frames properly on the client side (remember that two 2kb send() from the server will NOT result in two 2kb blocks in recv(), but rather in a single 4kb block);
  • You pass the complete block to decode_audio3.
George Y.
  • 11,307
  • 3
  • 24
  • 25
  • I think i might be facing problems of complete frame, any idea how can i ensure frame is valid, or complete block is received.. – Ichigo Kurosaki Feb 01 '14 at 11:10
  • When you send the blocks from the server size, first send the frame length (as DWORD) followed by the frame content. This way you will always know on the client whether the whole frame was received. – George Y. Feb 01 '14 at 22:50