Если вам не нужна функция перекрестной платформы Видео для Windows (VFW) API является хорошей альтернативой (http://msdn.microsoft.com/en-us/library/windows/desktop/dd756808(v=vs.85).aspx), я не буду размещать весь блок кода, так как вам нужно много сделать, но вы должны иметь возможность рисовать это из ссылки. В основном, вы делаете AVIFileOpen
, затем получаете видеопоток через AVIFileGetStream
с streamtypeVIDEO
или, наоборот, делаете это сразу с AVIStreamOpenFromFile
, а затем читаете образцы из потока с AVIStreamRead
. Если вы доберетесь до точки, где вы потерпите неудачу, я могу попытаться помочь, но это должно быть довольно просто.
Кроме того, не знаю, почему ffmpeg терпит неудачу, я делаю необработанное чтение AVI с помощью ffmpeg без участия каких-либо кодеков, можете ли вы опубликовать, какой вызов ffpeg на самом деле не удается?
EDIT:
Для вопроса, который вы видите, когда размер данных для чтения 0. Файл AVI имеет N слоты для кадров в каждом втором, где N является кадром видео. В реальной жизни образцы не будут поступать именно на такой скорости (например, камеры IP-наблюдения), поэтому фактические индексы образцов данных могут быть не непрерывными, как 1,5,11, ... и VFW будут вставлять пустые образцы между ними (то есть откуда вы читаете образец с нулевым размером). Вам нужно позвонить AVIStreamRead
с NULL в качестве буфера и 0 в размере до bRead
не 0 или вы пропустите последний образец. Когда вы получите фактический размер, вы можете снова позвонить AVIStreamRead
по этому образцу с указателем и размером буфера. Я обычно делаю сжатое видео, так что я не использовать предложенный размер, но, по крайней мере, в соответствии с вашим кодом snipplet я хотел бы сделать что-то вроде этого:
...
bRead = 0;
do
{
aviOpRes = AVIStreamRead(ppavi,smpS,1,NULL,0,&bRead,&smpN);
} while (bRead == 0 && ++smpS < si.dwLength + si.dwStart);
if(smpS >= si.dwLength + si.dwStart)
break;
PUCHAR tempBuffer = new UCHAR[bRead];
aviOpRes = AVIStreamRead(ppavi,smpS,1,tempBuffer,bRead,&bRead,&smpN);
/* do whatever you need */
delete tempBuffer;
...
EDIT 2:
Так как это может пригодиться кому-то или самому себе сделать выбор между VFW и FFMPEG. Я также обновил ваш пример FFMPEG, чтобы он разбирал один и тот же файл (извините за качество кода, поскольку он не имеет проверки ошибок, но я думаю, вы можете видеть логический поток):
/* register all formats and codecs */
av_register_all();
AVFormatContext* fmt_ctx = NULL;
/* open input file, and allocate format context */
const char *src_filename = "E:\\Output.avi";
if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) {
fprintf(stderr, "Could not open source file %s\n", src_filename);
abort();
}
/* retrieve stream information */
int res = avformat_find_stream_info(fmt_ctx, NULL);
if (res < 0) {
fprintf(stderr, "Could not find stream information\n");
abort();
}
int video_stream_index = 0; /* video stream is usualy 0 but still better to lookup in case it's not present */
for(; video_stream_index < fmt_ctx->nb_streams; ++video_stream_index)
{
if(fmt_ctx->streams[video_stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
break;
}
if(video_stream_index == fmt_ctx->nb_streams)
abort();
AVPacket *packet = new AVPacket;
while(av_read_frame(fmt_ctx, packet) == 0)
{
if (packet->stream_index == video_stream_index)
printf("Sample nr %d\n", packet->pts);
av_free_packet(packet);
}
В основном вы открываете контекст и читать пакеты из него.Вы получите как аудио-, так и видеопакеты, чтобы вы могли проверить, принадлежит ли пакет потоку интереса. FFMPEG избавит вас от проблем с пустыми кадрами и даст только те образцы, в которых есть данные.
См. Редактирование моего ответа на решение. –