Приветствую,
Я на этом ресурсе новый человек, посему если что не так, поправьте пожалуйста.
Проблема в том, что папу Джобса как всегда сутра клюнул жаренный петух и теперь по какойто причине Apple убрали поддержку AudioQueue output поддержку для AMR кодека в iOS 4.3. В старых системах мое приложение замечательно так читало пакеты из RTSP и играло видео и аудио, теперь играет только видео. Я решил сделать методы перекодирования из AMR в MP3 используя ffmpeg библиотеку, которую я кокраз и использую для работы с RTSP. Т.е. идея такова: получаем AVPacket для аудио, декодируем его в raw buffer, а потом энкодируем в MP3, запихиваем в новый AVPacket и гадим его в AudioQueue. Я сделал два метода (для decode и encode), но, толи у меня не хватает понимания как это работает, толи Джобс гдета капнул, но звук полон всяких артифактов и звучит аки поезд что по рельсам едет. Два дня читал всякие доки и форумы, пока не нашел ничего. Может тут мне подскажут что не так. Вот собственно методы (смесь Objective C и С. код переделовался много раз, потому не слишком чист):
- (void) decodeAudioPacketToRaw:(AVPacket) inPacket
{
AVCodec *codec;
AVCodecContext *c= NULL;
int out_size, size, len, total;
uint8_t *outbuf;
uint8_t *readybuf;
uint8_t *buf;
total = 0;
codec = avcodec_find_decoder(CODEC_ID_AMR_NB);
if (!codec) {
fprintf(stderr, "input codec not found\n");
return;
}
c= avcodec_alloc_context();
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open input codec\n");
return;
}
readybuf = (uint8_t*) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
memset(readybuf, 0, AVCODEC_MAX_AUDIO_FRAME_SIZE);
size = inPacket.size;
NSLog(@"Input packet size is %i", size);
while (size > 0) {
outbuf = (uint8_t*) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &inPacket);
if (len < 0) {
fprintf(stderr, "Error while decoding\n");
return;
}
NSLog(@"Decoded len is %i", len);
NSLog(@"Decoded out size is %i", out_size);
if (out_size > 0) {
size -= len;
inPacket.size -= len;
inPacket.data += len;
memcpy(readybuf + total, outbuf, out_size);
total += out_size;
//[self encodeAudioBuffer:(const short *)outbuf withSize:out_size andSourcePacket:inPacket]; Пробовал даже так, еще хуже
}
free(outbuf);
}
if(total > 0)
{
buf = (uint8_t*) malloc(total);
memcpy(buf, readybuf, total);
free(readybuf);
[self encodeAudioBuffer:(const short *)buf withSize:total andSourcePacket:inPacket];
free(buf);
}
}
- (void) encodeAudioBuffer:(const short *) in_buffer withSize:(unsigned int) in_buf_byte_size andSourcePacket:(AVPacket)sourcePacket
{
AVCodec * codec;
AVCodecContext * c= NULL;
int count, out_size, outbuf_size, frame_byte_size;
uint8_t * outbuf;
uint8_t * totaloutbuf;
printf("Audio encoding\n");
codec = avcodec_find_encoder(CODEC_ID_MP3);
if (!codec) {
fprintf(stderr, "output codec not found\n");
return;
}
c= avcodec_alloc_context();
c->bit_rate = 16000;
c->sample_rate = 8000;
c->channels = 1;
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open output codec\n");
return;
}
NSLog(@"START");
int total = 0;
int test = in_buf_byte_size;
out_size = 0;
while(out_size <= 0)
{
outbuf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
outbuf = (uint8_t*) malloc(outbuf_size);
memset(outbuf, 0, AVCODEC_MAX_AUDIO_FRAME_SIZE);
out_size = avcodec_encode_audio(c, outbuf, outbuf_size, (short*)in_buffer);
if(out_size > 0)
{
AVPacket resPacket;
av_init_packet(&resPacket);
resPacket.data = malloc(out_size);
resPacket.size = 0;
memset(resPacket.data, 0, out_size);
memcpy(resPacket.data, outbuf, out_size);
resPacket.size = out_size;
// тут гадим пакет в очередь.
test -= out_size;
total += out_size;
}
free(outbuf);
}
avcodec_close(c);
av_free(c);
NSLog(@"FINISH");
}
На самом деле не совсем ясно, что возвращает avcodec_encode_audio. В одной инструкции говорится, что возвращает скока использовалось байт из входного буфера, в другой, скока получилось байт в output буфере. В общем загадка. Странно, но первый раз оно возвращает 0, потому я там цикл сделал. Забавно то, что MP2 при первой попытке возвращает значчение более 0, но AudioQueue на iPhone не поддержывает и его.
Помогите кто может, а то уже моск кипит!!!
Спасибо!