Экспортируйте каждый кадр как изображение из Movie-File (QuickTime-API) - PullRequest
1 голос
/ 07 декабря 2009

Я хочу открыть существующий Movie-файл и экспортировать каждый кадр этого файла в изображение, такое как JPEG или TIFF. Я дошел до сих пор:

int main(int argc, char* argv[]) {
    char filename[255]; // Filename to ping.
    OSErr e;            // Error return.
    FSSpec filespec;    // QT file specification
    short filemovie;    // QT movie handle.
    Movie movie;        // QT movie "object".

    InitializeQTML(0);
    EnterMovies();
    // Because of QT's Mac origin, must convert C-string filename 
    // to Pascal counted string, then use that to make a filespec.
    c2pstr(filename); 
    FSMakeFSSpec(0, 0L, (ConstStr255Param)filename, &filespec);

    OpenMovieFile(&filespec, &filemovie, fsRdPerm);
    NewMovieFromFile(&movie, filemovie, nil, nil, newMovieActive, nil);
    ...

До сих пор он работал нормально (я тестировал TimeValue movietime = GetMovieDuration(movie); и распечатывал его), но теперь я хочу получить каждый кадр фильма и экспортировать его в файл (сначала, позже я просто хочу сохранить данные памяти, чтобы работать с ним, но я должен знать, если это действительно работает, поэтому экспорт в файл изображения пока лучше).
Как я могу это сделать? Нужен ли мне GWorld или PixMap? Как я могу получить GWorld / PixMap из Movie-файла, особенно каждый его кадр?

edit: Моя платформа - WinXP

Ответы [ 4 ]

1 голос
/ 30 сентября 2011

Эти утилиты командной строки OSX действительно хороши для извлечения содержимого фильма Quicktime без необходимости покупать QTPro:

qt_tools

1 голос
/ 07 декабря 2009

Если вы работаете только в OS X, я бы придерживался API QTKit, потому что они намного более высокого уровня и, как правило, с ними легче работать.

Общая суть того, что вы хотите сделать:

  1. Шаг через каждый кадр в фильме
  2. Получить представление изображения для текущего кадра
  3. Сохранить изображение текущего кадра в файл на диске

Для просмотра кадров в фильме QuickTime вы можете использовать класс QTMovie в QTKit, чтобы сделать это следующим образом:

- (void)dumpFramesWithMovie:(QTMovie*)movie toFolder:(NSString*)folderPath
{
    [movie setIdling:NO]; // Don't idle the movie

    [movie gotoEnd];
    QTTime endTime = [movie currentTime];

    [movie gotoBeginning];

    // Number of frames counted so far
    unsigned long numFrames = 0;

    // Turn off the Movie's looping so we are quaranteed to stop
    [movie setAttribute:[NSNumber numberWithBool:NO] forKey:QTMovieLoopsAttribute];

    // Construct a Dictionary of to use when reading frames from a movie
    NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
    [attributes setObject:QTMovieFrameImageTypeNSImage forKey:QTMovieFrameImageType];    
    while (true)
    {
        QTTime curTime = [movie currentTime];
        if (QTTimeCompare(curTime, endTime) == NSOrderedSame)
        {
            // Reached end of file
            break;
        }

        // Get the Current Frame as an NSImage
        NSImage* image = [movie frameImageAtTime:curTime 
                                  withAttributes:attributes error:nil];

        // Get the bitmap representation of this image
        // NOTE: This code assumes the first image representation is a NSBitmapImageRep, which is true
        // by default in OS X 10.5 and later.  
        // Production code should do error checking here.
        NSBitmapImageRep *bitmap = [[image representations] objectAtIndex: 0];

        // Construct a filename based upon the folder path and number of frames read so far
        NSString* fileName = [NSString stringWithFormat:@"%@/frame%d.png", folderPath, numFrames];

        // Get an PNG representation of this file
        NSData *data = [bitmap representationUsingType: NSPNGFileType
                                            properties: nil];

        // Write to disk
        [data writeToFile: fileName
               atomically: NO];

        // Step to the next Frame
        [movie stepForward];
        numFrames++;
    }

    [movie gotoBeginning];
}
@end

Этот код компилируется, но не был полностью протестирован.

Одно предостережение при таком подходе заключается в том, что файлы MPEG-1 не будут правильно декодироваться в OS X 10.5 и более ранних версиях. Насколько я знаю, это было исправлено на 10.6. Кроме того, если вы пишете приложение для Windows, вам нужно использовать API Quicktime-C нижнего рычага.

Обязательно проверьте следующие справочные страницы, работая над этим:

1 голос
/ 21 декабря 2009

Для начала, эта статья об экспортерах фильмов должна помочь вам начать:

http://www.mactech.com/articles/mactech/Vol.16/16.05/May00QTToolkit/index.html

Несмотря на то, что MacTech - это ресурс Mac, все описанные функции API должны быть доступны вQuickTime для Windows SDK.

Я сам соберу пример кода вместе, как только я найду время.

Редактировать

См. Эту выдержку из книги для получения дополнительной информации:

QuickTime Toolkit - Основные функции воспроизведения фильмов и мультимедиа @ Google Книги

Редактировать 2 - The High-Подход на уровне: экспортеры фильмов

Если все, что вам нужно сделать, - это извлечь все видеокадры из фильма QuickTime и преобразовать их в другой формат, поддерживаемый QuickTime API, вам не нужно будет ничего делатьдействия любого уровня при использовании Movie Exporter .

Приведенный ниже пример кода позволяет извлечь и преобразовать все видеокадры из фильма QuickTime в, например, набор файлов JPEG.используя программно вызванный диалог экспорта фильма.

Просто выберите Фильм к последовательности изображений в комбинированном окне Экспорт диалогового окна и выберите нужный формат изображения, нажав Опции .

Примечание 1: Если вам нужно сделать это не в интерактивном режиме, просто дайте мне знать.

Примечание 2: обработка ошибок для ясности опущена

#include "Movies.h"
#include "QTML.h"
#pragma comment (lib, "QTMLClient.lib")

...

int  flags                  = createMovieFileDeleteCurFile 
    | showUserSettingsDialog 
    | movieToFileOnlyExport;
ItemCount  movie_prop_count = 0;
CFStringRef  cfpath         = 0;
Boolean  bool_true          = true; 
QTNewMoviePropertyElement  movie_props[ 2 ];
Movie  movie;

// initialize QuickTime API
InitializeQTML( 0 );
EnterMovies();

// set up Core Foundation string for source path (argv[ 1 ]) contains the full path to the MOV file to convert
cfpath = CFStringCreateWithCString( 0, argv[ 1 ], kCFStringEncodingASCII );
movie_props[movie_prop_count].propClass        = kQTPropertyClass_DataLocation;
movie_props[movie_prop_count].propID           = kQTDataLocationPropertyID_CFStringNativePath;
movie_props[movie_prop_count].propValueSize    = sizeof(cfpath);
movie_props[movie_prop_count].propValueAddress = (void*)&cfpath;            
movie_props[movie_prop_count].propStatus       = 0;
++movie_prop_count;

// make Movie active
movie_props[movie_prop_count].propClass        = kQTPropertyClass_NewMovieProperty;
movie_props[movie_prop_count].propID           = kQTNewMoviePropertyID_Active;
movie_props[movie_prop_count].propValueSize    = sizeof(bool_true);
movie_props[movie_prop_count].propValueAddress = &bool_true;
movie_props[movie_prop_count].propStatus       = 0;
++movie_prop_count;

// aquire Movie for our Movie file
NewMovieFromProperties( movie_prop_count, movie_props, 0, 0, &movie );

// invoke conversion dialog
ConvertMovieToFile( movie, 0, 0, 0, 'TVOD', 0, 0, flags, 0 );

// clean up
DisposeMovie( movie );
CFRelease( cfpath );

ExitMovies();
TerminateQTML();

...

0 голосов
/ 07 декабря 2009

Обычно я просто выгружаю декодированные кадры в двоичный файл один за другим, а затем использую какой-нибудь YUV-Viewer, чтобы посмотреть, хорошо ли они выглядят. Для этого вы должны знать точный формат цвета и разрешение декодированных кадров. Если у вас есть RGB, для этого наверняка есть зрители.

UPDATE:

Ссылка не работает. Вам придется искать в Google для просмотра YUV. Кроме того, вы можете купить один из Elecard .

...