Я занимаюсь разработкой собственного приложения для 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()
терпеть неудачуAMediaExtractor_seekTo()
звонки на другие должности, безуспешноПросто для полноты, этот код я позже использую для получения выходного файла 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);
Задача ещё не решена.
Других решений пока нет …