forked from mia/Aegisub
Move more stuff to the common QT provider class and generalize initializing/de-initializing QuickTime.
Originally committed to SVN as r3243.
This commit is contained in:
parent
87e96be4b5
commit
7149e01888
4 changed files with 97 additions and 61 deletions
|
@ -34,11 +34,56 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#include <wx/wxprec.h>
|
#include "quicktime_common.h"
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef WITH_QUICKTIME
|
#ifdef WITH_QUICKTIME
|
||||||
#include "quicktime_common.h"
|
#include <wx/wxprec.h>
|
||||||
|
|
||||||
|
// static fun
|
||||||
|
int QuickTimeProvider::qt_initcount = 0;
|
||||||
|
GWorldPtr QuickTimeProvider::default_gworld = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void QuickTimeProvider::InitQuickTime() {
|
||||||
|
OSErr qt_err;
|
||||||
|
#ifdef WIN32
|
||||||
|
qt_err = InitializeQTML(0L);
|
||||||
|
QTCheckError(qt_err, wxString(_T("Failed to initialize QTML (do you have QuickTime installed?)")));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qt_err = EnterMovies();
|
||||||
|
QTCheckError(qt_err, wxString(_T("EnterMovies() failed")));
|
||||||
|
|
||||||
|
// have we been inited before?
|
||||||
|
if (qt_initcount <= 0) {
|
||||||
|
// we haven't, allocate an offscreen graphics world
|
||||||
|
// we need to do this before we actually open anything, or quicktime may crash (heh)
|
||||||
|
Rect def_box;
|
||||||
|
def_box.top = 0;
|
||||||
|
def_box.left = 0;
|
||||||
|
def_box.bottom = 320; // pick some random dimensions for now;
|
||||||
|
def_box.right = 240; // we won't actually use this buffer to render anything
|
||||||
|
QDErr qd_err = NewGWorld(&default_gworld, 32, &def_box, NULL, NULL, keepLocal);
|
||||||
|
if (qd_err != noErr)
|
||||||
|
throw wxString(_T("Failed to initialize temporary offscreen drawing buffer"));
|
||||||
|
SetGWorld(default_gworld, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
qt_initcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QuickTimeProvider::DeInitQuickTime() {
|
||||||
|
#ifdef WIN32
|
||||||
|
TerminateQTML();
|
||||||
|
#endif
|
||||||
|
qt_initcount--;
|
||||||
|
|
||||||
|
if (qt_initcount <= 0) {
|
||||||
|
ExitMovies();
|
||||||
|
DisposeGWorld(default_gworld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QuickTimeProvider::wxStringToDataRef(const wxString &string, Handle *dataref, OSType *dataref_type) {
|
void QuickTimeProvider::wxStringToDataRef(const wxString &string, Handle *dataref, OSType *dataref_type) {
|
||||||
|
@ -53,10 +98,26 @@ void QuickTimeProvider::wxStringToDataRef(const wxString &string, Handle *datare
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check if this error code signifies an error, and if it does, throw an exception
|
||||||
void QuickTimeProvider::QTCheckError(OSErr err, wxString errmsg) {
|
void QuickTimeProvider::QTCheckError(OSErr err, wxString errmsg) {
|
||||||
if (err != noErr)
|
if (err != noErr)
|
||||||
throw errmsg;
|
throw errmsg;
|
||||||
/* CheckError(err, errmsg.c_str()); // I wonder if this actually works on Mac, and if so, what it does */
|
/* CheckError(err, errmsg.c_str()); // I wonder if this actually works on Mac, and if so, what it does */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool QuickTimeProvider::CanOpen(const Handle& dataref, const OSType dataref_type) {
|
||||||
|
Boolean can_open;
|
||||||
|
Boolean prefer_img;
|
||||||
|
OSErr qt_err = CanQuickTimeOpenDataRef(dataref, dataref_type, NULL, &can_open, &prefer_img, 0);
|
||||||
|
QTCheckError(qt_err, wxString(_T("Checking if file is openable failed")));
|
||||||
|
|
||||||
|
// don't bother trying to open things quicktime considers images
|
||||||
|
if (can_open && !prefer_img)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* WITH_QUICKTIME */
|
#endif /* WITH_QUICKTIME */
|
||||||
|
|
|
@ -37,18 +37,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <wx/wxprec.h>
|
|
||||||
|
|
||||||
#ifdef WITH_QUICKTIME
|
#ifdef WITH_QUICKTIME
|
||||||
|
#include <wx/wxprec.h>
|
||||||
|
#include <wx/thread.h>
|
||||||
|
#include "include/aegisub/aegisub.h"
|
||||||
|
|
||||||
|
// qt stuff
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// avoid conflicts between MSVC's stdint.h and QT's stdint.h
|
// avoid conflicts between MSVC's stdint.h and QT's stdint.h
|
||||||
#define _STDINT_H
|
#define _STDINT_H
|
||||||
// get MSVC to shut up about a macro redefinition in QT's ConditionalMacros.h
|
// get MSVC to shut up about a macro redefinition in QT's ConditionalMacros.h
|
||||||
#pragma warning(disable: 4004)
|
#pragma warning(disable: 4004)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "include/aegisub/aegisub.h"
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <QTML.h>
|
#include <QTML.h>
|
||||||
|
@ -63,9 +64,15 @@ extern "C" {
|
||||||
|
|
||||||
class QuickTimeProvider {
|
class QuickTimeProvider {
|
||||||
public:
|
public:
|
||||||
|
void InitQuickTime();
|
||||||
|
void DeInitQuickTime();
|
||||||
void wxStringToDataRef(const wxString &string, Handle *dataref, OSType *dataref_type);
|
void wxStringToDataRef(const wxString &string, Handle *dataref, OSType *dataref_type);
|
||||||
|
bool CanOpen(const Handle& dataref, const OSType dataref_type);
|
||||||
void QTCheckError(OSErr err, wxString errmsg);
|
void QTCheckError(OSErr err, wxString errmsg);
|
||||||
|
|
||||||
|
static int qt_initcount;
|
||||||
|
static GWorldPtr default_gworld;
|
||||||
|
|
||||||
virtual ~QuickTimeProvider() {};
|
virtual ~QuickTimeProvider() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,13 @@
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
// Contact: mailto:zeratul@cellosoft.com
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "video_provider_quicktime.h"
|
||||||
|
|
||||||
#ifdef WITH_QUICKTIME
|
#ifdef WITH_QUICKTIME
|
||||||
|
|
||||||
#include "video_provider_quicktime.h"
|
|
||||||
#include "aegisub_endian.h"
|
#include "aegisub_endian.h"
|
||||||
|
|
||||||
|
// this function has a different name on win32 because the original name
|
||||||
|
// conflicts with a windows api function
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#define MacOffsetRect OffsetRect
|
#define MacOffsetRect OffsetRect
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,7 +49,6 @@ QuickTimeVideoProvider::QuickTimeVideoProvider(wxString filename) {
|
||||||
in_dataref = NULL;
|
in_dataref = NULL;
|
||||||
movie = NULL;
|
movie = NULL;
|
||||||
gw = NULL;
|
gw = NULL;
|
||||||
gw_tmp = NULL;
|
|
||||||
w = 0;
|
w = 0;
|
||||||
h = 0;
|
h = 0;
|
||||||
cur_fn = -1;
|
cur_fn = -1;
|
||||||
|
@ -58,14 +58,19 @@ QuickTimeVideoProvider::QuickTimeVideoProvider(wxString filename) {
|
||||||
qt_err = noErr;
|
qt_err = noErr;
|
||||||
errmsg = _T("QuickTime video provider: ");
|
errmsg = _T("QuickTime video provider: ");
|
||||||
|
|
||||||
#ifdef WIN32
|
// try to init quicktime
|
||||||
qt_err = InitializeQTML(0L);
|
try {
|
||||||
QTCheckError(qt_err, wxString(_T("QuickTime video provider: Failed to initialize QTML (do you have QuickTime installed?)")));
|
InitQuickTime();
|
||||||
#endif
|
}
|
||||||
|
catch (wxString temp) {
|
||||||
qt_err = EnterMovies();
|
errmsg.Append(temp);
|
||||||
QTCheckError(qt_err, wxString(_T("QuickTime video provider: EnterMovies() failed")));
|
throw errmsg;
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try loading the file
|
||||||
try {
|
try {
|
||||||
LoadVideo(filename);
|
LoadVideo(filename);
|
||||||
}
|
}
|
||||||
|
@ -83,10 +88,7 @@ QuickTimeVideoProvider::QuickTimeVideoProvider(wxString filename) {
|
||||||
|
|
||||||
QuickTimeVideoProvider::~QuickTimeVideoProvider() {
|
QuickTimeVideoProvider::~QuickTimeVideoProvider() {
|
||||||
Close();
|
Close();
|
||||||
ExitMovies();
|
DeInitQuickTime();
|
||||||
#ifdef WIN32
|
|
||||||
TerminateQTML();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,9 +99,6 @@ void QuickTimeVideoProvider::Close() {
|
||||||
if (gw)
|
if (gw)
|
||||||
DisposeGWorld(gw);
|
DisposeGWorld(gw);
|
||||||
gw = NULL;
|
gw = NULL;
|
||||||
if (gw_tmp)
|
|
||||||
DisposeGWorld(gw_tmp);
|
|
||||||
gw_tmp = NULL;
|
|
||||||
if (in_dataref)
|
if (in_dataref)
|
||||||
DisposeHandle(in_dataref);
|
DisposeHandle(in_dataref);
|
||||||
in_dataref = NULL;
|
in_dataref = NULL;
|
||||||
|
@ -109,18 +108,7 @@ void QuickTimeVideoProvider::Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool QuickTimeVideoProvider::CanOpen(const Handle& dataref, const OSType dataref_type) {
|
|
||||||
Boolean can_open;
|
|
||||||
Boolean prefer_img;
|
|
||||||
qt_err = CanQuickTimeOpenDataRef(dataref, dataref_type, NULL, &can_open, &prefer_img, 0);
|
|
||||||
QTCheckError(qt_err, wxString(_T("Checking if file is openable failed")));
|
|
||||||
|
|
||||||
// don't bother trying to open things quicktime considers images
|
|
||||||
if (can_open && !prefer_img)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QuickTimeVideoProvider::LoadVideo(const wxString _filename) {
|
void QuickTimeVideoProvider::LoadVideo(const wxString _filename) {
|
||||||
|
@ -133,18 +121,6 @@ void QuickTimeVideoProvider::LoadVideo(const wxString _filename) {
|
||||||
if (!CanOpen(in_dataref, in_dataref_type))
|
if (!CanOpen(in_dataref, in_dataref_type))
|
||||||
throw wxString(_T("QuickTime cannot open file as video"));
|
throw wxString(_T("QuickTime cannot open file as video"));
|
||||||
|
|
||||||
// allocate an offscreen graphics world
|
|
||||||
// we need to do this before we actually open the movie, or quicktime may crash (heh)
|
|
||||||
Rect m_box; // movie render rectangle
|
|
||||||
m_box.top = 0;
|
|
||||||
m_box.left = 0;
|
|
||||||
m_box.bottom = 320; // pick some random dimensions for now;
|
|
||||||
m_box.right = 240; // we won't actually use this buffer to render anything
|
|
||||||
QDErr qd_err = NewGWorld(&gw_tmp, 32, &m_box, NULL, NULL, keepLocal);
|
|
||||||
if (qd_err != noErr)
|
|
||||||
throw wxString(_T("Failed to initialize temporary offscreen drawing buffer"));
|
|
||||||
SetGWorld(gw_tmp, NULL);
|
|
||||||
|
|
||||||
// actually open file
|
// actually open file
|
||||||
short res_id = 0;
|
short res_id = 0;
|
||||||
qt_err = NewMovieFromDataRef(&movie, newMovieActive, &res_id, in_dataref, in_dataref_type);
|
qt_err = NewMovieFromDataRef(&movie, newMovieActive, &res_id, in_dataref, in_dataref_type);
|
||||||
|
@ -155,6 +131,7 @@ void QuickTimeVideoProvider::LoadVideo(const wxString _filename) {
|
||||||
QTCheckError(qt_err, wxString(_T("Failed to disable visual context")));
|
QTCheckError(qt_err, wxString(_T("Failed to disable visual context")));
|
||||||
|
|
||||||
// set offscreen buffer size to actual movie dimensions
|
// set offscreen buffer size to actual movie dimensions
|
||||||
|
Rect m_box;
|
||||||
GetMovieBox(movie, &m_box);
|
GetMovieBox(movie, &m_box);
|
||||||
// make sure its top left corner is at (0,0)
|
// make sure its top left corner is at (0,0)
|
||||||
MacOffsetRect(&m_box, -m_box.left, -m_box.top);
|
MacOffsetRect(&m_box, -m_box.left, -m_box.top);
|
||||||
|
@ -162,20 +139,12 @@ void QuickTimeVideoProvider::LoadVideo(const wxString _filename) {
|
||||||
w = m_box.right;
|
w = m_box.right;
|
||||||
h = m_box.bottom;
|
h = m_box.bottom;
|
||||||
// allocate a new offscreen rendering buffer with the correct dimensions
|
// allocate a new offscreen rendering buffer with the correct dimensions
|
||||||
qd_err = NewGWorld(&gw, 32, &m_box, NULL, NULL, keepLocal);
|
QDErr qd_err = NewGWorld(&gw, 32, &m_box, NULL, NULL, keepLocal);
|
||||||
if (qd_err != noErr)
|
if (qd_err != noErr)
|
||||||
throw wxString(_T("Failed to initialize offscreen drawing buffer"));
|
throw wxString(_T("Failed to initialize offscreen drawing buffer"));
|
||||||
|
|
||||||
// select our new offscreen render target
|
// select our new offscreen render target
|
||||||
SetGWorld(gw, NULL); // make sure the old one isn't used, since we're about to kill it
|
|
||||||
SetMovieGWorld(movie, gw, NULL);
|
SetMovieGWorld(movie, gw, NULL);
|
||||||
// Get rid of our old temporary rendering buffer.
|
|
||||||
// All this ridicolous hoop-jumping with two buffers is because no matter what I've tried,
|
|
||||||
// UpdateGWorld() either doesn't update the buffer, or if it does, trying to render to the
|
|
||||||
// updated buffer causes access violations.
|
|
||||||
// :argh: QuickDraw :argh:
|
|
||||||
DisposeGWorld(gw_tmp);
|
|
||||||
gw_tmp = NULL;
|
|
||||||
|
|
||||||
// get timestamps, keyframes and framecount
|
// get timestamps, keyframes and framecount
|
||||||
std::vector<int> timecodes = IndexFile();
|
std::vector<int> timecodes = IndexFile();
|
||||||
|
@ -216,7 +185,6 @@ std::vector<int> QuickTimeVideoProvider::IndexFile() {
|
||||||
|
|
||||||
// get the first frame
|
// get the first frame
|
||||||
GetMovieNextInterestingTime(movie, nextTimeMediaSample + nextTimeEdgeOK, 1, v_type, cur_timeval, 0, &cur_timeval, NULL);
|
GetMovieNextInterestingTime(movie, nextTimeMediaSample + nextTimeEdgeOK, 1, v_type, cur_timeval, 0, &cur_timeval, NULL);
|
||||||
keyframes.push_back(0); // interesting assumption?
|
|
||||||
|
|
||||||
// first, find timestamps and count frames
|
// first, find timestamps and count frames
|
||||||
while (cur_timeval >= 0) {
|
while (cur_timeval >= 0) {
|
||||||
|
@ -233,6 +201,7 @@ std::vector<int> QuickTimeVideoProvider::IndexFile() {
|
||||||
|
|
||||||
// next, find keyframes
|
// next, find keyframes
|
||||||
cur_timeval = 0;
|
cur_timeval = 0;
|
||||||
|
keyframes.push_back(0); // interesting assumption?
|
||||||
while (cur_timeval >= 0) {
|
while (cur_timeval >= 0) {
|
||||||
GetMovieNextInterestingTime(movie, nextTimeSyncSample, 1, v_type, cur_timeval, 0, &cur_timeval, NULL);
|
GetMovieNextInterestingTime(movie, nextTimeSyncSample, 1, v_type, cur_timeval, 0, &cur_timeval, NULL);
|
||||||
keyframes.push_back(timestamp_map[cur_timeval]);
|
keyframes.push_back(timestamp_map[cur_timeval]);
|
||||||
|
|
|
@ -36,22 +36,22 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <wx/wxprec.h>
|
#include "quicktime_common.h"
|
||||||
|
|
||||||
#ifdef WITH_QUICKTIME
|
#ifdef WITH_QUICKTIME
|
||||||
#include "include/aegisub/video_provider.h"
|
#include <wx/wxprec.h>
|
||||||
#include "quicktime_common.h"
|
|
||||||
#include <wx/dynarray.h>
|
#include <wx/dynarray.h>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "include/aegisub/video_provider.h"
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
|
|
||||||
|
|
||||||
class QuickTimeVideoProvider : public VideoProvider, QuickTimeProvider {
|
class QuickTimeVideoProvider : public VideoProvider, QuickTimeProvider {
|
||||||
private:
|
private:
|
||||||
Movie movie; // source object
|
Movie movie; // source object
|
||||||
GWorldPtr gw, gw_tmp; // render buffers
|
GWorldPtr gw; // render buffer
|
||||||
Handle in_dataref; // input data handle
|
Handle in_dataref; // input data handle
|
||||||
|
|
||||||
int w, h; // width/height
|
int w, h; // width/height
|
||||||
|
@ -65,7 +65,6 @@ private:
|
||||||
OSErr qt_err; // quicktime error code
|
OSErr qt_err; // quicktime error code
|
||||||
wxString errmsg; // aegisub error message
|
wxString errmsg; // aegisub error message
|
||||||
|
|
||||||
bool CanOpen(const Handle& dataref, const OSType dataref_type);
|
|
||||||
void LoadVideo(const wxString filename);
|
void LoadVideo(const wxString filename);
|
||||||
std::vector<int> IndexFile();
|
std::vector<int> IndexFile();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
Loading…
Reference in a new issue