Android — ошибка в addTrack () при попытке мультиплексировать аудио и видео

Я занимаюсь разработкой собственного приложения для Android, в котором записываю видеопоток с экрана (кодируя его с помощью собственного AMediaCodec библиотека для video/avc) и я смешиваю его с AAC / audio/mp4a-latm звуковая дорожка. Мой код отлично работает на нескольких устройствах, но у меня возникли проблемы с некоторыми устройствами (Huawei P8 и P10 lite, работающие под управлением Android 6.0.0 и 7.0 соответственно, и Nexus 5 под управлением Android 6.0.1). Проблема в том, что всякий раз, когда я пытаюсь добавить второй трек в мультиплексор (независимо от порядка их добавления), это терпит неудачу возвращая -10000 код ошибки.

Я упрощенный проблема в том, чтобы просто объединить аудио и видео файл; результаты одинаковы. В этой упрощенной версии я использую два AMediaExtractorчтобы получить аудио и видео форматы для настройки AMediaMuxer, но когда я добавляю второй трек, я все равно получаю ошибку. Вот код:

const auto videoSample = "videosample.mp4";
const auto audioSample = "audiosample.aac";
const auto filePath = "muxed_file.mp4"
auto* extractorV = AMediaExtractor_new();
AMediaExtractor_setDataSource(extractorV, videoSample);
AMediaExtractor_selectTrack(extractorV, 0U); // here I take care to select the right "video/avc" track
auto* videoFormat = AMediaExtractor_getTrackFormat(extractorV, 0U);

auto* extractorA = AMediaExtractor_new();
AMediaExtractor_setDataSource(extractorA, audioSample);
AMediaExtractor_selectTrack(extractorA, 0U); // here I take care to select the right "mp4a-latm" track
auto* audioFormat = AMediaExtractor_getTrackFormat(extractorA, 0U);

auto fd = open(filePath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
auto* muxer = AMediaMuxer_new(fd, AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4);
auto videoTrack = AMediaMuxer_addTrack(muxer, videoFormat); // the operation succeeds: videoTrack is 0
auto audioTrack = AMediaMuxer_addTrack(muxer, audioFormat); // error: audioTrack is -10000

AMediaExtractor_seekTo(extractorV, 0, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
AMediaExtractor_seekTo(extractorA, 0, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);

AMediaMuxer_start(muxer);

Что-то не так с моим кодом? Это что-то, что не должно работать на Android до 8 или это чистое совпадение? Я прочитал много постов (особенно @fadden) здесь на SO, но я не в состоянии понять это.

Позвольте мне дать вам некоторый контекст:

  • ошибка не зависит от порядка добавления двух дорожек: он всегда будет второй AMediaMuxer_addTrack() терпеть неудачу
  • аудио и видео треки должны быть в порядке: когда я смешиваю только один из треков, все работает хорошо даже на Huaweis и Nexus 5 я получаю правильные выходные файлы, как с аудио, так и с видео дорожкой
  • Я пытался переместить AMediaExtractor_seekTo() звонки на другие должности, безуспешно
  • тот же код отлично работает на других устройствах (OnePlus 5 и Nokia 7 plus, оба работают под управлением Android> = 8.0)

Просто для полноты, этот код я позже использую для получения выходного файла mp4:

AMediaMuxer_start(muxer);

// mux the VIDEO track
std::array<uint8_t, 256U * 1024U> videoBuf;
AMediaCodecBufferInfo videoBufInfo{};
videoBufInfo.flags = AMediaExtractor_getSampleFlags(extractorV);
bool videoEos{};
while (!videoEos) {
auto ts = AMediaExtractor_getSampleTime(extractorV);
videoBufInfo.presentationTimeUs = std::max(videoBufInfo.presentationTimeUs, ts);
videoBufInfo.size = AMediaExtractor_readSampleData(extractorV, videoBuf.data(), videoBuf.size());
if(videoBufInfo.presentationTimeUs == -1 || videoBufInfo.size < 0) {
videoEos = true;
} else {
AMediaMuxer_writeSampleData(muxer, videoTrack, videoBuf.data(), &videoBufInfo);
AMediaExtractor_advance(extractorV);
}
}

// mux the audio track
std::array<uint8_t, 256U * 1024U> audioBuf;
AMediaCodecBufferInfo audioBufInfo{};
audioBufInfo.flags = AMediaExtractor_getSampleFlags(extractorA);
bool audioEos{};
while (!audioEos) {
audioBufInfo.size = AMediaExtractor_readSampleData(extractorA, audioBuf.data(), audioBuf.size());
if(audioBufInfo.size < 0) {
audioEos = true;
} else {
audioBufInfo.presentationTimeUs = AMediaExtractor_getSampleTime(extractorA);
AMediaMuxer_writeSampleData(muxer, audioTrack, audioBuf.data(), &audioBufInfo);
AMediaExtractor_advance(extractorA);
}
}

AMediaMuxer_stop(muxer);
AMediaMuxer_delete(muxer);
close(fd);
AMediaFormat_delete(audioFormat);
AMediaExtractor_delete(extractorA);
AMediaFormat_delete(videoFormat);
AMediaExtractor_delete(extractorV);

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]