Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3

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

10.04.2011, 19:51. Показов 3802. Ответов 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 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru