Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3

Из *.avi файла извлечь кадр по индексу

10.04.2011, 19:51. Показов 3806. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех! Есть такая задача: из *.avi файла извлечь кадр по индексу. Реализовал следующим образом:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include"AviControl.h"
//...
int Error;
PAVIFILE AviFile;
PAVISTREAM AviStream;
PGETFRAME gapgf;
PBITMAPINFOHEADER lpbi;
char *bits;
AVIFILEINFOA AviInfo;
HDC DC_Handle;
//...
/* функция извлечения кадра по индексу */
HBITMAP GetFrame(unsigned int FrameIndex)
{
    HBITMAP hBmp;
    gapgf=AVIStreamGetFrameOpen(AviStream,NULL);    //готовим поток к декомпрессии кадров
    if(gapgf==NULL)
    {
        UnloadAvi();
        return NULL;
    }
    lpbi=(PBITMAPINFOHEADER)AVIStreamGetFrame(gapgf,FrameIndex);    //получаем адрес кадра по индексу
    if(lpbi==NULL)
    {
        AVIStreamGetFrameClose(gapgf);  //освобождаем ресурсы выделенные для декомпрессии кадров
        return NULL;
    }
    bits=(char*)(int)lpbi+sizeof(BITMAPINFOHEADER);
    DC_Handle=CreateDC("Display",NULL,NULL,NULL);
    try
    {
        hBmp=CreateDIBitmap(DC_Handle,lpbi,4,bits,(PBITMAPINFO)lpbi,0);
    }
    finally
    {
        DeleteDC(DC_Handle);
    }
    AVIStreamGetFrameClose(gapgf);
    return hBmp;
}
Все бы хорошо, только во время работы вылетает с ошибкой "A generic error occured in GDI+". Что не так я сделал? Буду признателен за любую помощь!

P.S. практика показала, что возвращаемый хендл равен нулю. Откуда ноги растут?

Добавлено через 34 минуты
Оказалось, что после строки 16 gapgf равен нулю.

Добавлено через 2 минуты
Вообще код является модификацией этого:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function GetFrame(Index:LongWord):boolean;
begin
  // Prepares to decompress video frames
  gapgf := AVIStreamGetFrameOpen(AVIStream, nil);
  if gapgf = nil then
  begin
    UnloadAvi;
    Result:=false;
    Exit;
  end;
  // Read current Frame
  // AVIStreamGetFrame Returns the address of a decompressed video frame
  lpbi := AVIStreamGetFrame(gapgf, FrameIndex);
  if lpbi = nil then
  begin
    AVIStreamGetFrameClose(gapgf);
    Result:=false;
    Exit;
  end;
  Frame.Height := lpbi.biHeight;
  Frame.Width := lpbi.biWidth;
  bits := Pointer(Integer(lpbi) + SizeOf(TBITMAPINFOHEADER));
  DC_Handle := CreateDC('Display', nil, nil, nil);
  try
      hBmp := CreateDIBitmap(DC_Handle, // handle of device context
      lpbi^, // address of bitmap size and format data
      CBM_INIT, // initialization flag
      bits, // address of initialization data
      PBITMAPINFO(lpbi)^, // address of bitmap color-format data
      DIB_RGB_COLORS); // color-data usage
  finally
      DeleteDC(DC_Handle);
  end;
  Frame.Handle := hBmp;
  AVIStreamGetFrameClose(gapgf);
  Frame.PixelFormat:=pf24bit;
  Result:=true;
end;
Добавлено через 5 минут
Интерфейс Avistream получается нормальный, но по какой-то причине gapgf все равно равен нулю.

Добавлено через 7 минут
Вопрос такой: дело может быть в кодеках? Почему спрашиваю: есть у меня проект (собственно код из него представлен) на делфях. Так вот он работал, давно и на 100% другой версии кодеков. Теперь ради теста его решил прогнать и он вылетел с AV на той же строчке. Может такое быть и как бороться?

Добавлено через 5 часов 25 минут
Детальная инспекция видеофайлов показала, что данный код работает только на тех, кодеки которых стоят в системе. Указанный баг был выявлен из-за отсутствия DivX-кодека.
P.S. тему пока можно считать закрытой, но если будет что-то важное по теме, я допишу.
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.04.2011, 19:51
Ответы с готовыми решениями:

Выдирать кадр из avi файла
Помагите написать программу чтоб выдирала кадр из avi файла используя следующее: AVI INIT FILE AVIF AVIFILE OPEN I O COMPRESS AVI...

Как извлечь кадр из видео файла *avi?
Как извлеч кадр из видео файла *avi Есть у меня видео файлы в формате avi, мне их нужно перевести в формат *bmp, как?

Извлечь кадр из .h264, или преобразовать .h264 в avi
Извлеч кадр из .h264 или его преобразование в avi подскажите если кто то обладает как извлеч из h264 кадр и преобразовать его в bmp или...

11
 Аватар для FreeMan108
121 / 121 / 32
Регистрация: 04.03.2013
Сообщений: 370
01.11.2013, 20:44
Цитата Сообщение от HighPredator Посмотреть сообщение
bits=(char*)(int)lpbi+sizeof(BITMAPINFOH EADER);
Но это не всегда будет работать корректно.
Правильно вот так:
C++
1
bits=(char*)(int)lpbi+sizeof(LPBITMAPINFOHEADER);
Проверял на Windows 7. Если прибавлять sizeof (BITMAPINFOHEADER), то программа вылетает (правда не во всех случаях), а если дальний указатель, то работает прекрасно всегда.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
01.11.2013, 20:48
С каких пор CreateDIBitmap бросает исключение?
0
Автор FAQ
 Аватар для -=ЮрА=-
6614 / 4256 / 401
Регистрация: 08.08.2009
Сообщений: 10,325
Записей в блоге: 24
01.11.2013, 23:18
HighPredator, нагородил ты конечно...
Ладно чтобы дать конкретный пример направляю сюда
http://www.codeproject.com/Art... AVI-Frames

Добавлено через 3 минуты

Не по теме:

ЗЫ: контекст "не делают руками" а получают от окна с помощью GetDC, затем делают совместимый контекст (дабы не мигало), после рисуют в нём, а потом с помощью BitBlt отправляют в исходный контекст

0
 Аватар для raxper
10237 / 6615 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
01.11.2013, 23:42
...работает только на тех, кодеки которых стоят в системе. Указанный баг был выявлен из-за отсутствия DivX-кодека.
именно так. Впрочем граббинг методами DirectShow с аналогичной проблемой.

Могу рекомендовать использовать со встроенными кодеками, FFMPEG позволяет выдрать n-й кадр или с n-го времени столько сколько нужно.
0
06.11.2013, 14:09  [ТС]

Не по теме:

Обалдеть какая древность всплыла:D Если найду то, как решил это - выложу.

0
0 / 0 / 0
Регистрация: 24.11.2014
Сообщений: 47
06.12.2014, 14:07
подскажите пожалуйста смогли вы найти решение своей проблемы?
я столкнулась с очень похожей проблемой
0
120 / 142 / 46
Регистрация: 31.10.2014
Сообщений: 721
Записей в блоге: 1
06.12.2014, 14:24
Цитата Сообщение от FreeMan108 Посмотреть сообщение
sizeof(LPBITMAPINFOHEADER);
это будет = 4 байтам.

В то время как sizeof(BITMAPINFOHEADER) равно 40 байтам.

Потому что LPBITMAPINFOHEADER это указатель на структуру
0
0 / 0 / 0
Регистрация: 24.11.2014
Сообщений: 47
06.12.2014, 14:41
не могли бы взглянуть код и сказать в чем у меня беда, он выдает либо pFrame=0 либо вылетает на строчке:
C++
1
2
BYTE* pDIB = (BYTE*) AVIStreamGetFrame(pFrame, index);
        CreateFromPackedDIBPointer(pDIB,index);
вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// izvlechenie_cadra.cpp: определяет точку входа для консольного приложения.
//
 
#include "stdafx.h"
#include <Windows.h>
#include <WindowsX.h>
#include <iostream>
#include <Vfw.h>
#include <atlstr.h>//CString
#include <string.h> 
#include <string>
#include <ShellAPI.h>
//#include <afxwin.h>// AfxMessageBox
 
#pragma comment(lib, "vfw32.lib")
 
using namespace std;
BOOL CreateFromPackedDIBPointer(LPBYTE pDIB, int iFrame);
 
BOOL ExtractAVIFrames(string szFileName)
{
    AVIFileInit();
 
    PAVIFILE avi;
    int res=AVIFileOpen(&avi, "ZOL.avi", OF_READ, NULL);
 
    if (res!=AVIERR_OK)
    {
        //ошибка возникает
        if (avi!=NULL)
            AVIFileRelease(avi);
        
        return FALSE;
    }
 
    AVIFILEINFO avi_info;
    AVIFileInfo(avi, &avi_info, sizeof(AVIFILEINFO));
 
    CString szFileInfo;
    szFileInfo.Format("Dimention: %dx%d\n"
                      "Length: %d frames\n"
                      "Max bytes per second: %d\n"
                      "Samples per second: %d\n"
                      "Streams: %d\n"
                      "File Type: %d", 
                            avi_info.dwWidth,
                            avi_info.dwHeight,
                            avi_info.dwLength,
                            avi_info.dwMaxBytesPerSec,
                            (DWORD) (avi_info.dwRate / avi_info.dwScale),
                            avi_info.dwStreams,
                            avi_info.szFileType);
 
    MessageBox(NULL,szFileInfo,"", MB_ICONINFORMATION | MB_OK);
 
    PAVISTREAM pStream;
    res=AVIFileGetStream(avi, &pStream, streamtypeVIDEO /*video stream*/, 
                                               0 /*first stream*/);
 
    if (res!=AVIERR_OK)
    {
        if (pStream!=NULL)
            AVIStreamRelease(pStream);
 
        AVIFileExit();
        return FALSE;
    }
 
    //сделать некоторые задачи с поток
    int iNumFrames;
    int iFirstFrame;
 
    iFirstFrame=AVIStreamStart(pStream);
    if (iFirstFrame==-1)
    {
        //Ошибка getteing кадр внутри потока
 
        if (pStream!=NULL)
            AVIStreamRelease(pStream);
 
        AVIFileExit();
        return FALSE;
    }
 
    iNumFrames=AVIStreamLength(pStream);
    if (iNumFrames==-1)
    {
        //Ошибка getteing количество из кадры внутри потока
        
        if (pStream!=NULL)
            AVIStreamRelease(pStream);
        
        AVIFileExit();
        return FALSE;
    }
 
    //получение растрового изображения от кадра
    BITMAPINFOHEADER bih;
    ZeroMemory(&bih, sizeof(BITMAPINFOHEADER));
 
    bih.biBitCount=24;    //24 бита на пиксел
    bih.biClrImportant=0;
    bih.biClrUsed = 0;
    bih.biCompression = BI_RGB;
    bih.biPlanes = 1;
    bih.biSize = 40;
    bih.biXPelsPerMeter = 0;
    bih.biYPelsPerMeter = 0;
    bih.biWidth=1280;
    bih.biHeight=720;
    //вычислить Общий размер из RGBQUAD строк (выравнивание DWORD)
    bih.biSizeImage = (((bih.biWidth * 3) + 3) & 0xFFFC) * bih.biHeight ;
 
    PGETFRAME pFrame;
    pFrame=AVIStreamGetFrameOpen(pStream, 
          // NULL//
          //(BITMAPINFOHEADER*) AVIGETFRAMEF_BESTDISPLAYFMT
          &bih );
    
    //Получить первый кадр
    int index=0;
    for (int i=iFirstFrame; i<iNumFrames; i++)
    {
        index= i-iFirstFrame;
 
        BYTE* pDIB = (BYTE*) AVIStreamGetFrame(pFrame, index);
        CreateFromPackedDIBPointer(pDIB,index);
        
        //CreateFromPackedDIBPointer((LPBYTE)pDIB, index);
    }
 
    AVIStreamGetFrameClose(pFrame);
 
    //закрыть поток после завершения задачи
    if (pStream!=NULL)
        AVIStreamRelease(pStream);
 
    AVIFileExit();
 
    return TRUE;
}
 
 
 
BOOL CreateFromPackedDIBPointer(LPBYTE pDIB, int iFrame)
{
   //ASSERT(pDIB!=NULL);
 
    //Создает полный цвет (без палитры) DIB из указателя к     //полноцветная памяти DIB 
    //получить BITMAPINFOHEADER
    BITMAPINFOHEADER bih;
    RtlMoveMemory(&bih.biSize, pDIB, sizeof(BITMAPINFOHEADER));
 
    //теперь получить bitmap бит    
    if (bih.biSizeImage < 1)
    {
        return FALSE;
    }
 
    BYTE* Bits=new BYTE[bih.biSizeImage];
 
    RtlMoveMemory(Bits, pDIB + sizeof(BITMAPINFOHEADER), bih.biSizeImage);
 
    //and BitmapInfo переменной длины UDT     
    BYTE memBitmapInfo[40];
    RtlMoveMemory(memBitmapInfo, &bih, sizeof(bih));
 
    BITMAPFILEHEADER bfh;
    bfh.bfType=19778;    //BM заголовка 
    bfh.bfSize=55 + bih.biSizeImage;
    bfh.bfReserved1=0;
    bfh.bfReserved2=0;
    bfh.bfOffBits=sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER); //54
    
    string FileName;
    FileName.insert(6,5,iFrame);
        //Format("Frame-%05d.bmp", iFrame);
    
    FILE* fp=fopen(FileName.c_str(), "wb");
    if (fp!=NULL)
    {
        fwrite(&bfh, sizeof(bfh), 1, fp);
        fwrite(&memBitmapInfo, sizeof(memBitmapInfo), 1, fp);
        fwrite(Bits, bih.biSizeImage, 1, fp);
        fclose(fp);
    }
    else
    {
        MessageBox(NULL,_T("Error writing the bitmap file"),"",MB_OK);
        return FALSE;
    }
 
    delete [] Bits;
    return TRUE;
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    ExtractAVIFrames("ZOL.avi");
    return 0;
}
это пока консольный вариант, буду очень благодарна и признательна
0
 Аватар для raxper
10237 / 6615 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
06.12.2014, 15:11
http://digilinux.ru/2010/10/21... th-ffmpeg/
0
0 / 0 / 0
Регистрация: 24.11.2014
Сообщений: 47
06.12.2014, 17:34
спасибо за подсказку но не особо все понятно
0
 Аватар для raxper
10237 / 6615 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
06.12.2014, 18:33
Просто дочитайте до конца, вдумчиво. Если не доходит до глубин сознания - добро пожаловать читать справку на офсайте FFMPEG.

p.s.: это все к посту #5.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.12.2014, 18:33
Помогаю со студенческими работами здесь

Получить кадр из AVI файла в TBitmap
Получить кадр из AVI файла в TBitmap Если есть у кого а есть исходник выложите, перерыр кучу инфы и нет продвижения по извлечению из...

Как получить кадр bmp из avi?
Как получить кадр bmp из avi?

Извлечь кадр из видеофайла
Здравствуйте! Есть ли библиотеки или утилиты, либо средства в Qt, для извлечения кадра из видеофайла с произвольного момента?...

Нужно из кусков разных фильмов (avi, mpg) создать один avi
Такая задача. Нужно из кусков разных фильмов (avi, mpg) создать один avi. Помогите кто чем может.

Раскодирование AVI-файла
Доброго времени суток! Ситуация следующая: ф-и библиотеки vfw, а именно, AviStreamRead не раскодируют более 2-х ГБ. Читал форумы,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru