Я пытаюсь кодировать необработанный звук PCM в G711A и G711U, а затем декодировать его, с этими кодеками все работает нормально, потому что я могу выбрать любое значение для AVCodecContext frame_size для кодирования, но в случае кода Opus c AVCodecContext frame_size является равно 120, поэтому, если я правильно понял, если размер моего массива входных данных больше 120, тогда мне нужно сделать какую-то буферизацию и разделить мои входные данные на несколько частей, а затем последовательно поместить их в AVFrame-> data и передать AVFrame в кодировку.
В результате я получаю очень плохой звук, и я получаю этот результат не только при использовании кода Opus c, но и в G711, если я установил для AVCodecContext frame_size какое-то значение, которое будет меньше размер моих входных данных.
Итак, мой вопрос: каков правильный способ кодирования входных данных, если их размер больше, чем AVCodecContext frame_size? Нужно ли разбивать входные данные на несколько частей, которые <= AVCodecContext frame_size, если да, то как мне это сделать? </p>
На данный момент мой код выглядит следующим образом:
void encode(uint8_t *data, unsigned int length)
{
int rawOffset = 0;
int rawDelta = 0;
int rawSamplesCount = frameEncode->nb_samples <= length ? frameEncode->nb_samples : length;
while (rawSamplesCount > 0)
{
memcpy(frameEncode->data[0], &data[rawOffset], sizeof(uint8_t) * rawSamplesCount);
encodeFrame();
rawOffset += rawSamplesCount;
rawDelta = length - rawOffset;
rawSamplesCount = rawDelta > frameEncode->nb_samples ? frameEncode->nb_samples : rawDelta;
}
av_frame_unref(frameEncode);
}
void encodeFrame()
{
/* send the frame for encoding */
int ret = avcodec_send_frame(contextEncoder, frameEncode);
if (ret < 0)
{
LOGE(TAG, "[encodeFrame] avcodec_send_frame error: %s", av_err2str(ret));
return;
}
/* read all the available output packets (in general there may be any number of them) */
while (ret >= 0)
{
ret = avcodec_receive_packet(contextEncoder, packetEncode);
if (ret < 0 && ret != AVERROR(EAGAIN)) LOGE(TAG, "[encodeFrame] error in avcodec_receive_packet: %s", av_err2str(ret));
if (ret < 0) break;
std::pair<uint8_t*, unsigned int> p = std::pair<uint8_t*, unsigned int>();
p.first = (uint8_t *)(malloc(sizeof(uint8_t) * packetEncode->size));
memcpy(p.first, packetEncode->data, (size_t)packetEncode->size);
p.second = (unsigned int)(packetEncode->size);
listEncode.push_back(p); // place encoded data into list to finally create one array of encoded data from it
}
av_packet_unref(packetEncode);
}
Вы можете вижу, что я делю свои входные данные на несколько частей, затем помещаю их в frame-> data и затем передаю кадр в кодировку, но я не уверен, что это правильный путь.
UPD: я заметил, что когда я использую G711, если я установил AVCodecContext frame_size на 160, а размер моих входных данных равен 160 или 320, все работает нормально, но если размер входных данных равен 640, тогда я получаю плохой жужжащий звук.