2015-08-19 9 views
0

У меня есть приложение для Android, которое получает необработанные байты AAC с внешнего устройства, и я хочу декодировать эти данные, но я не могу заставить декодер работать, однако ffmpeg отлично работает для декодирования файла mp4, который содержит те же аудиоданные (проверенные с помощью isoviewer). Недавно мне удалось получить эту библиотеку ffmpeg на android для декодирования видеокадров с одного и того же внешнего устройства, но звук, похоже, не сработает.нужна помощь в настройке ffmpeg для декодирования необработанного AAC с android ndk

Вот выход FFmpeg для файла с теми же данными:

$ ffmpeg -i Video_2000-01-01_0411.mp4 
ffmpeg version 2.6.1 Copyright (c) 2000-2015 the FFmpeg developers 
    built with Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) 
    configuration: --prefix=/usr/local/Cellar/ffmpeg/2.6.1 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libmp3lame --enable-libvo-aacenc --enable-libxvid --enable-vda 
    libavutil  54. 20.100/54. 20.100 
    libavcodec  56. 26.100/56. 26.100 
    libavformat 56. 25.101/56. 25.101 
    libavdevice 56. 4.100/56. 4.100 
    libavfilter  5. 11.102/5. 11.102 
    libavresample 2. 1. 0/2. 1. 0 
    libswscale  3. 1.101/3. 1.101 
    libswresample 1. 1.100/1. 1.100 
    libpostproc 53. 3.100/53. 3.100 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'AXON_Flex_Video_2000-01-01_0411.mp4': 
    Metadata: 
    major_brand  : mp42 
    minor_version : 1 
    compatible_brands: isom3gp43gp5 
    Duration: 00:00:15.73, start: 0.000000, bitrate: 1134 kb/s 
    Stream #0:0(eng): Audio: aac (LC) (mp4a/0x6134706D), 8000 Hz, mono, fltp, 40 kb/s (default) 
    Metadata: 
     handler_name : soun 
    Stream #0:1(eng): Video: mpeg4 (Simple Profile) (mp4v/0x7634706D), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 1087 kb/s, 29.32 fps, 26.58 tbr, 90k tbn, 1k tbc (default) 
    Metadata: 
     handler_name : vide 

Вот мой NDK код для создания и декодирования аудио:

jint ffmpeg_init(JNIEnv * env, jobject this) { 
    audioCodec = avcodec_find_decoder(AV_CODEC_ID_AAC); 
    if (!audioCodec) { 
     LOGE("audio codec %d not found", AV_CODEC_ID_AAC); 
     return -1; 
    } 

    audioContext = avcodec_alloc_context3(audioCodec); 
    if (!audioContext) { 
     LOGE("Could not allocate codec context"); 
     return -1; 
    } 

    int openRet = avcodec_open2(audioContext, audioCodec, NULL); 
     if (openRet < 0) { 
      LOGE("Could not open codec, error:%d", openRet); 
      return -1; 
     } 

    audioContext->sample_rate = 8000; 
    audioContext->channel_layout = AV_CH_LAYOUT_MONO; 
    audioContext->profile = FF_PROFILE_AAC_LOW; 
    audioContext->bit_rate = 48 * 1024; 
    audioContext->sample_fmt = AV_SAMPLE_FMT_FLTP; 

    // unsigned char extradata[] = {0x15, 0x88}; 
    // audioContext->extradata = extradata; 
    // audioContext->extradata_size = sizeof(extradata); 
    audioFrame = av_frame_alloc(); 
    if (!audioFrame) { 
     LOGE("Could not create audio frame"); 
     return -1; 
    } 
} 


jint ffmpeg_decodeAudio(JNIEnv *env, jobject this, jbyteArray aacData, jbyteArray output, int offset, int len) { 

    LOGI("ffmpeg_decodeAudio()"); 
    char errbuf[128]; 
    AVPacket avpkt = {0}; 
    av_init_packet(&avpkt); 
    LOGI("av_init_packet()"); 
    int error, got_frame;  
    uint8_t* buffer = (uint8_t *) (*env)->GetByteArrayElements(env, aacData,0); 
    uint8_t* copy = av_malloc(len); 
    memcpy(copy, &buffer[offset], len); 
    av_packet_from_data(&avpkt, copy, len); 


    if ((error = avcodec_decode_audio4(audioContext, audioFrame, &got_frame, &avpkt)) < 0) { 
     ffmpeg_log_error(error); 
     av_free_packet(&avpkt); 
     return error; 
    } 
    if (got_frame) { 
     LOGE("Copying audioFrame->extended_data to output jbytearray, linesize[0]:%d", audioFrame->linesize[0]); 
     (*env)->SetByteArrayRegion(env, output, 0, audioFrame->linesize[0], *audioFrame->extended_data); 
    } 

    return 0; 

} 

Как вы можете видеть, что я» У вас есть функция init, которая открывает декодер и создает контекст, все это прекрасно работает, без ошибок. Однако, когда я называю avcodec_decode_audio4 я получаю сообщение об ошибке: Ошибка

FFMPEG: -1094995529, недопустимые данные, найденные при обработке ввода

Я пробовал все виды комбинаций свойств AVCodecContext. Я не уверен, что мне нужно установить для декодера, чтобы сделать это, но из чтения онлайн мне просто нужно установить макет канала и sample_rate (который я пробовал самостоятельно). Я также попытался установить параметры extradata/extradata_size для того, что должно соответствовать настройкам видео: http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio Но не повезло.

С устройства, с которого мы получаем пакеты от отправки данных aac, которые не имеют звука в начале (но являются действительными пакетами), я попытался просто отправить их, поскольку они определенно должны правильно декодировать.

Ниже приведен пример исходных пакетов аудио, которые молчание:

010c9eb43f21f90fc87e46fff10a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5dffe214b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4b4bbd1c429696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696978 

Обратите внимание, что данные, приведенные выше, является лишь шестнадцатеричным кодированием данных, которые я помещаю в AVPacket, и это было отправляется с внешнего устройства на приложение Android. Мое приложение не имеет прямого доступа к файлу, хотя мне нужно декодировать необработанные кадры/образцы по мере их получения. Когда я смотрю на данные аудиодорожки в isoviewer, я вижу, что первый образец аудиодорожки - это те же данные, что и у устройства, содержащего этот файл (таким образом, внешнее устройство просто отправляет мне исходные данные образца). Я считаю, что эти данные могут быть получены из поля ввода stsz (размер выборки), начиная с полей stco (chunk offset) из поля mdat файла.

Кроме того, isoviewer показывает окно ESDS как имеющее следующее:

ESDescriptor{esId=0, streamDependenceFlag=0, URLFlag=0, oCRstreamFlag=0, streamPriority=0, URLLength=0, URLString='null', remoteODFlag=0, dependsOnEsId=0, oCREsId=0, decoderConfigDescriptor=DecoderConfigDescriptor{objectTypeIndication=64, streamType=5, upStream=0, bufferSizeDB=513, maxBitRate=32000, avgBitRate=32000, decoderSpecificInfo=null, audioSpecificInfo=AudioSpecificConfig{configBytes=1588, audioObjectType=2 (AAC LC), samplingFrequencyIndex=11 (8000), samplingFrequency=0, channelConfiguration=1, syncExtensionType=0, frameLengthFlag=0, dependsOnCoreCoder=0, coreCoderDelay=0, extensionFlag=0, layerNr=0, numOfSubFrame=0, layer_length=0, aacSectionDataResilienceFlag=false, aacScalefactorDataResilienceFlag=false, aacSpectralDataResilienceFlag=false, extensionFlag3=0}, configDescriptorDeadBytes=, profileLevelIndicationDescriptors=[[]]}, slConfigDescriptor=SLConfigDescriptor{predefined=2}} 

И двоичное это:

00 00 00 30 65 73 64 73 00 00 00 00 03 80 80 80 
1f 00 00 00 04 80 80 80 14 40 15 00 02 01 00 00 
7d 00 00 00 7d 00 05 80 80 80 02 15 88 06 01 02 
+0

Какие типы данных вы вносите в эти функции? 010c ... на самом деле не помогает, это пакетированные данные AAC из проанализированного файла m4a? Или необработанные фрагменты файла AAC? Или m4a куски файлов? Или что-то другое? –

+0

Я обновил (последний абзац), чтобы объяснить, что представляют данные. –

+0

@ RonaldS.Bultje Я только что видел ваш комментарий отсюда http://stackoverflow.com/questions/31726738/ffmpeg-native-aac-decoder/31729894#31729894, и это заставляет меня задаться вопросом, могу ли я просто взять данные окна esds и установите это в поле extradata. Я устанавливаю все данные коробки или только определенные части? Я должен иметь возможность просто жестко кодировать эти данные. –

ответ

0

я нашел главную проблему с приведенным выше кодом. Декодер инициализируется при вызове avcodec_open2. Таким образом, следует установить контекст поля первой перед открытием, как это:

jint ffmpeg_init(JNIEnv * env, jobject this) { 
//.... 

audioContext = avcodec_alloc_context3(audioCodec); 

audioContext->sample_rate = 8000; 
audioContext->channel_layout = AV_CH_LAYOUT_MONO; 
audioContext->channels = 1; 
int openRet = avcodec_open2(audioContext, audioCodec, NULL); 
if (openRet < 0) { 
    LOGE("Could not open codec, error:%d", openRet); 
    return -1; 
} 

Декодер теперь декодирования аудио без ошибок.