В настоящее время я пытаюсь изучить FFmpeg API, следуя этот учебник. Однако у меня уже есть проблемы с первым уроком по декодированию видео. Мой код в основном такой же, как и в учебнике, за исключением того, что я использую C++. Моя проблема в том, что видеопоток не соответствует потоку из пакета, возвращаемого av_read_frame.
Видеопоток получается циклически по доступным потокам, пока видеопоток не будет найден.
for(int i = 0; i < pFormatCtx->nb_streams; i++) { // nb_streams == 2
if (pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break; // videoStream == 0
}
}
Затем при получении данных кадра он захватывает аудиоканал.
while(av_read_frame(pFormatCtx, &packet) >= 0) { // read returns 0
// Is this a packet from the video stream?
if (packet.stream_index == videoStream) {
//packet.stream_index == 1, which correspond to the audio stream
}
}
Я не нашел в Интернете примеров, когда этот тест действительно не удался. Я пропустил какой-нибудь способ указать stream_index, которого нет в учебнике? Может быть, руководство устарело и что-то делает не так? Если да, то как правильно извлечь данные кадра? В случае, если это имеет значение, я использую последнюю сборку FFmpeg 4.0.2 на 64-битная Windows, компилируя с Visual Studio 2017.
На видео без звука два потока совпадают, и я могу правильно декодировать и отображать кадры.
Пакеты хранятся в контейнере с чередованием, поэтому вы решаете сохранить их или нет после демультиплексирования. Отмените ссылку на пакет, если он принадлежит другому потоку.
@ G.M. Вы полностью в курсе. На самом деле я уже пытался перейти к следующим кадрам, но недостаточно далеко! Думаю, я ожидал более регулярной картины между потоками. Для моего видео это было: 0-46 -> аудио, 47 -> видео, 48-49 -> аудио, 50-81 -> видео, и я остановился раньше, чем переход 46-47. Спасибо за помощь. Должен ли я удалить сообщение?
Перейдите по этой ссылке, чтобы получить образец программы, которая написана простым способом, чтобы новички могли понять основы. stackoverflow.com/a/37484145/6180077. Также эта ссылка на github: github.com/abdullahfarwees/screen-recorder-ffmpeg-cpp





Попробуйте вот так:
while(av_read_frame(pFormatCtx, &packet) == 0) {
AVStream *st = pFormatCtx->streams[packet.stream_index];
switch (st->codecpar->codec_type)
{
case AVMEDIA_TYPE_AUDIO:
/* handle audio */
break;
case AVMEDIA_TYPE_VIDEO:
/* handle video */
break;
...
}
}
Я не уверен, что понимаю. Если считывание кадра предназначено для потока, который вас не интересует, просто проигнорируйте его и переходите к следующему кадру. Прошу прощения, если я упустил суть.