forked from mia/Aegisub
Remove the deprecated ffmpeg audio/video providers. They have not yet been removed from any of the build systems; verm will remove them from the Unix one and I will remove them from the MSVC project file shortly.
Originally committed to SVN as r3148.
This commit is contained in:
parent
e589bceaa6
commit
dfea9f9713
12 changed files with 6 additions and 1352 deletions
|
@ -47,9 +47,6 @@
|
||||||
#ifdef WITH_AVISYNTH
|
#ifdef WITH_AVISYNTH
|
||||||
#include "audio_provider_avs.h"
|
#include "audio_provider_avs.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
#include "audio_provider_lavc.h"
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
#include "audio_provider_ffmpegsource.h"
|
#include "audio_provider_ffmpegsource.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -283,9 +280,6 @@ void AudioProviderFactoryManager::RegisterProviders() {
|
||||||
#ifdef WITH_AVISYNTH
|
#ifdef WITH_AVISYNTH
|
||||||
RegisterFactory(new AvisynthAudioProviderFactory(),_T("Avisynth"));
|
RegisterFactory(new AvisynthAudioProviderFactory(),_T("Avisynth"));
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
RegisterFactory(new LAVCAudioProviderFactory(),_T("FFMPEG"));
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
RegisterFactory(new FFmpegSourceAudioProviderFactory(),_T("FFmpegSource"));
|
RegisterFactory(new FFmpegSourceAudioProviderFactory(),_T("FFmpegSource"));
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,297 +0,0 @@
|
||||||
// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define EMULATE_INTTYPES
|
|
||||||
#endif
|
|
||||||
#include <wx/wxprec.h>
|
|
||||||
|
|
||||||
/* avcodec.h uses INT64_C in a *single* place. This prolly breaks on Win32,
|
|
||||||
* but, well. Let's at least fix it for Linux.
|
|
||||||
*/
|
|
||||||
/* Update: this used to be commented out but is now needed on Windows.
|
|
||||||
* Not sure about Linux, so it's wrapped in an ifdef.
|
|
||||||
*/
|
|
||||||
#ifdef WIN32
|
|
||||||
#define __STDC_CONSTANT_MACROS 1
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif /* WIN32 */
|
|
||||||
/* - done in posix/defines.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "audio_provider_lavc.h"
|
|
||||||
#include "mkv_wrap.h"
|
|
||||||
#include "lavc_file.h"
|
|
||||||
#include "lavc_file.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// Constructor
|
|
||||||
LAVCAudioProvider::LAVCAudioProvider(Aegisub::String _filename)
|
|
||||||
: lavcfile(NULL), codecContext(NULL), rsct(NULL), buffer(NULL)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
#if 0
|
|
||||||
/* since seeking currently is likely to be horribly broken with two
|
|
||||||
* providers accessing the same stream, this is disabled for now.
|
|
||||||
*/
|
|
||||||
LAVCVideoProvider *vpro_lavc = dynamic_cast<LAVCVideoProvider *>(vpro);
|
|
||||||
if (vpro_lavc) {
|
|
||||||
lavcfile = vpro->lavcfile->AddRef();
|
|
||||||
filename = vpro_lavc->GetFilename();
|
|
||||||
} else {
|
|
||||||
#endif
|
|
||||||
lavcfile = LAVCFile::Create(_filename);
|
|
||||||
filename = _filename.c_str();
|
|
||||||
#if 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
audStream = -1;
|
|
||||||
for (int i = 0; i < (int)lavcfile->fctx->nb_streams; i++) {
|
|
||||||
codecContext = lavcfile->fctx->streams[i]->codec;
|
|
||||||
if (codecContext->codec_type == CODEC_TYPE_AUDIO) {
|
|
||||||
stream = lavcfile->fctx->streams[i];
|
|
||||||
audStream = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (audStream == -1) {
|
|
||||||
codecContext = NULL;
|
|
||||||
throw _T("ffmpeg audio provider: Could not find an audio stream");
|
|
||||||
}
|
|
||||||
AVCodec *codec = avcodec_find_decoder(codecContext->codec_id);
|
|
||||||
if (!codec) {
|
|
||||||
codecContext = NULL;
|
|
||||||
throw _T("ffmpeg audio provider: Could not find a suitable audio decoder");
|
|
||||||
}
|
|
||||||
if (avcodec_open(codecContext, codec) < 0)
|
|
||||||
throw _T("ffmpeg audio provider: Failed to open audio decoder");
|
|
||||||
|
|
||||||
sample_rate = Options.AsInt(_T("Audio Sample Rate"));
|
|
||||||
if (!sample_rate) {
|
|
||||||
/* aegisub wants audio with sample rate higher than 32khz */
|
|
||||||
if (codecContext->sample_rate < 32000)
|
|
||||||
sample_rate = 48000;
|
|
||||||
else
|
|
||||||
sample_rate = codecContext->sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we rely on the intermediate audio provider to do downmixing for us later if necessary */
|
|
||||||
channels = codecContext->channels;
|
|
||||||
|
|
||||||
/* TODO: test if anything but S16 actually works! */
|
|
||||||
switch (codecContext->sample_fmt) {
|
|
||||||
case SAMPLE_FMT_U8: bytes_per_sample = 1; break;
|
|
||||||
case SAMPLE_FMT_S16: bytes_per_sample = 2; break;
|
|
||||||
case SAMPLE_FMT_S32: bytes_per_sample = 4; break; /* downmixing provider doesn't support this, will definitely not work */
|
|
||||||
default:
|
|
||||||
throw _T("ffmpeg audio provider: Unknown or unsupported sample format");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initiate resampling if necessary */
|
|
||||||
if (sample_rate != codecContext->sample_rate) {
|
|
||||||
rsct = audio_resample_init(channels, channels, sample_rate, codecContext->sample_rate);
|
|
||||||
if (!rsct)
|
|
||||||
throw _T("ffmpeg audio provider: Failed to initialize resampling");
|
|
||||||
resample_ratio = (float)sample_rate / (float)codecContext->sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* libavcodec seems to give back invalid stream length values for Matroska files.
|
|
||||||
* As a workaround, we can use the overall file length.
|
|
||||||
*/
|
|
||||||
double length;
|
|
||||||
if(stream->duration == AV_NOPTS_VALUE)
|
|
||||||
length = (double)lavcfile->fctx->duration / AV_TIME_BASE;
|
|
||||||
else
|
|
||||||
length = (double)stream->duration * av_q2d(stream->time_base);
|
|
||||||
num_samples = (int64_t)(length * sample_rate); /* number of samples per channel */
|
|
||||||
|
|
||||||
buffer = (int16_t *)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
|
||||||
if (!buffer)
|
|
||||||
throw _T("ffmpeg audio provider: Failed to allocate audio decoding buffer, out of memory?");
|
|
||||||
|
|
||||||
leftover_samples = 0;
|
|
||||||
last_output_sample = -1;
|
|
||||||
|
|
||||||
} catch (...) {
|
|
||||||
Destroy();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LAVCAudioProvider::~LAVCAudioProvider()
|
|
||||||
{
|
|
||||||
Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LAVCAudioProvider::Destroy()
|
|
||||||
{
|
|
||||||
if (buffer)
|
|
||||||
free(buffer);
|
|
||||||
if (rsct)
|
|
||||||
audio_resample_close(rsct);
|
|
||||||
if (codecContext)
|
|
||||||
avcodec_close(codecContext);
|
|
||||||
if (lavcfile)
|
|
||||||
lavcfile->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LAVCAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
|
||||||
{
|
|
||||||
int16_t *_buf = (int16_t *)buf;
|
|
||||||
|
|
||||||
/* this exception disabled for now */
|
|
||||||
/* if (last_output_sample != start-1)
|
|
||||||
throw _T("ffmpeg audio provider: nonlinear access attempted, try loading audio to RAM or HD cache"); */
|
|
||||||
|
|
||||||
last_output_sample += count;
|
|
||||||
|
|
||||||
int64_t samples_to_decode = (num_samples - start) * channels; /* samples left to the end of the stream */
|
|
||||||
if (count < samples_to_decode) /* haven't reached the end yet, so just decode the requested number of samples */
|
|
||||||
samples_to_decode = count * channels; /* times the number of channels */
|
|
||||||
if (samples_to_decode < 0) /* requested beyond the end of the stream */
|
|
||||||
samples_to_decode = 0;
|
|
||||||
|
|
||||||
/* if we got asked for more samples than there are left in the stream, add zeros to the decoding buffer until
|
|
||||||
we have enough to fill the request */
|
|
||||||
memset(_buf + samples_to_decode, 0, ((count * channels) - samples_to_decode) * bytes_per_sample);
|
|
||||||
|
|
||||||
/* do we have leftover samples from last time we were called? */
|
|
||||||
/* FIXME: this assumes that requests are always linear! attempts at random access give bogus results! */
|
|
||||||
if (leftover_samples > 0) {
|
|
||||||
int length = (samples_to_decode > leftover_samples) ? leftover_samples : samples_to_decode;
|
|
||||||
samples_to_decode -= length;
|
|
||||||
leftover_samples -= length;
|
|
||||||
|
|
||||||
/* put them in the output buffer */
|
|
||||||
samples_to_decode -= leftover_samples;
|
|
||||||
while (length > 0) {
|
|
||||||
*(_buf++) = *(overshoot_buffer++);
|
|
||||||
length--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AVPacket packet;
|
|
||||||
while (samples_to_decode > 0 && av_read_frame(lavcfile->fctx, &packet) >= 0) {
|
|
||||||
/* we're not dealing with video packets in this here provider */
|
|
||||||
if (packet.stream_index == audStream) {
|
|
||||||
int size = packet.size;
|
|
||||||
uint8_t *data = packet.data;
|
|
||||||
|
|
||||||
while (size > 0) {
|
|
||||||
int temp_output_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; /* see constructor, it malloc()'s buffer to this */
|
|
||||||
int retval, decoded_bytes, decoded_samples;
|
|
||||||
|
|
||||||
retval = avcodec_decode_audio2(codecContext, buffer, &temp_output_buffer_size, data, size);
|
|
||||||
/* decoding failed, skip this packet and hope next one doesn't fail too */
|
|
||||||
if (retval < 0)
|
|
||||||
break;
|
|
||||||
/* throw _T("ffmpeg audio provider: failed to decode audio"); */
|
|
||||||
|
|
||||||
size -= retval;
|
|
||||||
data += retval;
|
|
||||||
/* decoding succeeded but this audio frame is empty, continue to next frame */
|
|
||||||
if (temp_output_buffer_size <= 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
decoded_bytes = temp_output_buffer_size;
|
|
||||||
decoded_samples = decoded_bytes / bytes_per_sample; /* FIXME: stop assuming everything is 16-bit! */
|
|
||||||
|
|
||||||
/* do we need to resample? */
|
|
||||||
if (rsct) {
|
|
||||||
/* allocate some memory to save the resampled data in */
|
|
||||||
int16_t *temp_output_buffer = (int16_t *)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
|
|
||||||
if (!temp_output_buffer)
|
|
||||||
throw _T("ffmpeg audio provider: Failed to allocate audio resampling buffer, out of memory?");
|
|
||||||
|
|
||||||
/* do the actual resampling */
|
|
||||||
decoded_samples = audio_resample(rsct, temp_output_buffer, buffer, decoded_samples / codecContext->channels);
|
|
||||||
|
|
||||||
/* did we end up with more samples than we were asked for? */
|
|
||||||
if (decoded_samples > samples_to_decode) {
|
|
||||||
/* in that case, count them */
|
|
||||||
leftover_samples = decoded_samples - samples_to_decode;
|
|
||||||
/* and put them aside for later */
|
|
||||||
memcpy(buffer, &temp_output_buffer[samples_to_decode+1], leftover_samples * bytes_per_sample);
|
|
||||||
overshoot_buffer = buffer;
|
|
||||||
/* output the other samples that didn't overflow */
|
|
||||||
memcpy(_buf, temp_output_buffer, samples_to_decode * bytes_per_sample);
|
|
||||||
_buf += samples_to_decode;
|
|
||||||
} else {
|
|
||||||
memcpy(_buf, temp_output_buffer, decoded_samples * bytes_per_sample);
|
|
||||||
|
|
||||||
_buf += decoded_samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(temp_output_buffer);
|
|
||||||
} else { /* no resampling needed */
|
|
||||||
/* overflow? (as above) */
|
|
||||||
if (decoded_samples > samples_to_decode) {
|
|
||||||
/* count sheep^H^H^H^H^Hsamples */
|
|
||||||
leftover_samples = decoded_samples - samples_to_decode;
|
|
||||||
/* and put them aside for later (mm, lamb chops) */
|
|
||||||
overshoot_buffer = &buffer[samples_to_decode+1];
|
|
||||||
/* output the other samples that didn't overflow */
|
|
||||||
memcpy(_buf, buffer, samples_to_decode * bytes_per_sample);
|
|
||||||
|
|
||||||
_buf += samples_to_decode;
|
|
||||||
} else {
|
|
||||||
/* just do a straight copy to buffer */
|
|
||||||
memcpy(_buf, buffer, decoded_bytes);
|
|
||||||
|
|
||||||
_buf += decoded_samples;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
samples_to_decode -= decoded_samples;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
av_free_packet(&packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,102 +0,0 @@
|
||||||
// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define EMULATE_INTTYPES
|
|
||||||
#endif
|
|
||||||
#include <wx/wxprec.h>
|
|
||||||
|
|
||||||
/* avcodec.h uses INT64_C in a *single* place. This prolly breaks on Win32,
|
|
||||||
* but, well. Let's at least fix it for Linux.
|
|
||||||
*
|
|
||||||
#define __STDC_CONSTANT_MACROS 1
|
|
||||||
#include <stdint.h>
|
|
||||||
* - done in posix/defines.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
}
|
|
||||||
#include "mkv_wrap.h"
|
|
||||||
#include "lavc_file.h"
|
|
||||||
#include "include/aegisub/audio_provider.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// LAVC Audio Provider
|
|
||||||
class LAVCAudioProvider : public AudioProvider {
|
|
||||||
private:
|
|
||||||
LAVCFile *lavcfile;
|
|
||||||
|
|
||||||
AVCodecContext *codecContext;
|
|
||||||
ReSampleContext *rsct;
|
|
||||||
float resample_ratio;
|
|
||||||
AVStream *stream;
|
|
||||||
int audStream;
|
|
||||||
|
|
||||||
int16_t *buffer;
|
|
||||||
int16_t *overshoot_buffer;
|
|
||||||
|
|
||||||
int64_t last_output_sample;
|
|
||||||
|
|
||||||
int leftover_samples;
|
|
||||||
|
|
||||||
void Destroy();
|
|
||||||
|
|
||||||
public:
|
|
||||||
LAVCAudioProvider(Aegisub::String _filename);
|
|
||||||
virtual ~LAVCAudioProvider();
|
|
||||||
|
|
||||||
// Supposedly lavc always returns machine endian samples
|
|
||||||
bool AreSamplesNativeEndian() { return true; }
|
|
||||||
|
|
||||||
virtual void GetAudio(void *buf, int64_t start, int64_t count);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Factory
|
|
||||||
class LAVCAudioProviderFactory : public AudioProviderFactory {
|
|
||||||
public:
|
|
||||||
AudioProvider *CreateProvider(Aegisub::String file) { return new LAVCAudioProvider(file); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -75,6 +75,12 @@
|
||||||
#define WITH_AVISYNTH
|
#define WITH_AVISYNTH
|
||||||
|
|
||||||
|
|
||||||
|
// Enable ffmpegsource video and audio providers
|
||||||
|
// Requires: FFmpegSource2 headers (in repository), loader library and DLL
|
||||||
|
//#define WITH_FFMPEGSOURCE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////// MEDIUM PRIORITY ////////////
|
///////////// MEDIUM PRIORITY ////////////
|
||||||
|
|
||||||
|
@ -140,19 +146,6 @@
|
||||||
//#define WITH_LIBASS
|
//#define WITH_LIBASS
|
||||||
|
|
||||||
|
|
||||||
// Enable FFmpeg video and audio decoders
|
|
||||||
// Requires: libavcodec, libavformat, libswscale, libavutil
|
|
||||||
// If you compiled static libraries (yes, by default), uncomment the second line as well,
|
|
||||||
// and remember to add the correct .a files to the linker's additional dependencies.
|
|
||||||
// #define WITH_FFMPEG
|
|
||||||
// #define WITH_STATIC_FFMPEG
|
|
||||||
|
|
||||||
|
|
||||||
// Enable ffmpegsource video and audio providers
|
|
||||||
// Requires: ffmpegsource version 2
|
|
||||||
//#define WITH_FFMPEGSOURCE
|
|
||||||
|
|
||||||
|
|
||||||
// Enable Ruby support for Automation
|
// Enable Ruby support for Automation
|
||||||
// Requires: Ruby 1.9
|
// Requires: Ruby 1.9
|
||||||
//#define WITH_RUBY
|
//#define WITH_RUBY
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
#include <wx/wxprec.h>
|
|
||||||
#include <wx/filename.h>
|
|
||||||
#include "lavc_file.h"
|
|
||||||
|
|
||||||
LAVCFile::Initializer LAVCFile::init;
|
|
||||||
|
|
||||||
LAVCFile::Initializer::Initializer()
|
|
||||||
{
|
|
||||||
av_register_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
LAVCFile::LAVCFile(Aegisub::String _filename)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
fctx = NULL;
|
|
||||||
wxString filename = _filename.c_str();
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
wxFileName fn(filename);
|
|
||||||
filename = fn.GetShortPath();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
result = av_open_input_file(&fctx,filename.mb_str(csConvLocal),NULL,0,NULL);
|
|
||||||
if (result != 0) throw _T("Failed opening file.");
|
|
||||||
|
|
||||||
// Get stream info
|
|
||||||
result = av_find_stream_info(fctx);
|
|
||||||
if (result < 0) {
|
|
||||||
av_close_input_file(fctx);
|
|
||||||
fctx = NULL;
|
|
||||||
throw _T("Unable to read stream info");
|
|
||||||
}
|
|
||||||
refs = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LAVCFile::~LAVCFile()
|
|
||||||
{
|
|
||||||
if (fctx)
|
|
||||||
av_close_input_file(fctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // WITH_FFMPEG
|
|
|
@ -1,69 +0,0 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define EMULATE_INTTYPES
|
|
||||||
#endif
|
|
||||||
#include <wx/filename.h>
|
|
||||||
extern "C" {
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
}
|
|
||||||
#include "include/aegisub/aegisub.h"
|
|
||||||
|
|
||||||
|
|
||||||
class LAVCFile {
|
|
||||||
private:
|
|
||||||
unsigned refs;
|
|
||||||
|
|
||||||
LAVCFile(Aegisub::String filename);
|
|
||||||
~LAVCFile();
|
|
||||||
|
|
||||||
class Initializer {
|
|
||||||
public:
|
|
||||||
Initializer();
|
|
||||||
};
|
|
||||||
static Initializer init;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AVFormatContext *fctx;
|
|
||||||
|
|
||||||
static LAVCFile *Create(Aegisub::String filename) { return new LAVCFile(filename); }
|
|
||||||
LAVCFile *AddRef() { refs++; return this; };
|
|
||||||
void Release() { if (!--refs) delete this; };
|
|
||||||
};
|
|
|
@ -1,142 +0,0 @@
|
||||||
// Copyright (c) 2007, 2points
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define __STDC_CONSTANT_MACROS 1
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif /* WIN32 */
|
|
||||||
|
|
||||||
#include "dialog_progress.h"
|
|
||||||
#include "lavc_keyframes.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// Constructor
|
|
||||||
LAVCKeyFrames::LAVCKeyFrames(const Aegisub::String filename)
|
|
||||||
: file(0), stream(0), streamN(-1), numFrames(0) {
|
|
||||||
// Open LAVCFile
|
|
||||||
file = LAVCFile::Create(filename);
|
|
||||||
|
|
||||||
// Find video stream
|
|
||||||
for (unsigned int i = 0; i < file->fctx->nb_streams; ++i) {
|
|
||||||
if (file->fctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
|
|
||||||
stream = file->fctx->streams[i];
|
|
||||||
streamN = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (streamN == -1) throw _T("ffmpeg keyframes reader: Could not find a video stream");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////
|
|
||||||
// Destructor
|
|
||||||
LAVCKeyFrames::~LAVCKeyFrames() {
|
|
||||||
if (file) file->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////
|
|
||||||
// Parse file for keyframes
|
|
||||||
wxArrayInt LAVCKeyFrames::GetKeyFrames() {
|
|
||||||
wxArrayInt keyframes;
|
|
||||||
|
|
||||||
AVPacket packet;
|
|
||||||
int total_frames;
|
|
||||||
// check if the stream duration is bogus (will happen for MKV files)
|
|
||||||
if (stream->duration == AV_NOPTS_VALUE) {
|
|
||||||
// throw _T("ffmpeg keyframes reader: demuxer returned invalid stream length");
|
|
||||||
// FIXME: find some less dumb way to do this
|
|
||||||
total_frames = 123456; // random suitably big number
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
total_frames = stream->duration;
|
|
||||||
}
|
|
||||||
register unsigned int frameN = 0; // Number of parsed frames
|
|
||||||
numFrames = 0;
|
|
||||||
|
|
||||||
volatile bool canceled = false;
|
|
||||||
DialogProgress *progress = new DialogProgress(NULL,_("Load keyframes"),&canceled,_("Reading keyframes from video"),0,total_frames);
|
|
||||||
progress->Show();
|
|
||||||
progress->SetProgress(0,1);
|
|
||||||
|
|
||||||
while (av_read_frame(file->fctx, &packet) == 0 && !canceled) {
|
|
||||||
// Check if packet is part of video stream
|
|
||||||
if (packet.stream_index == streamN) {
|
|
||||||
framesData.push_back(LAVCFrameInfo(packet.dts, (packet.flags & PKT_FLAG_KEY) ? 1 : 0));
|
|
||||||
|
|
||||||
// Check if the packet contains a keyframe
|
|
||||||
if (packet.flags & PKT_FLAG_KEY)
|
|
||||||
// note: frame numbers start from 0, watch out for the fencepost error
|
|
||||||
keyframes.Add(frameN);
|
|
||||||
|
|
||||||
// Increment number of passed frames
|
|
||||||
frameN++;
|
|
||||||
|
|
||||||
/* Might need some adjustments here, to make it
|
|
||||||
appear as fluid as wanted. Just copied 2points thingy,
|
|
||||||
and reduced it a bit */
|
|
||||||
if ((frameN & (1024 - 1)) == 0)
|
|
||||||
progress->SetProgress(frameN,total_frames);
|
|
||||||
}
|
|
||||||
av_free_packet(&packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
numFrames = frameN;
|
|
||||||
|
|
||||||
// Clean up progress
|
|
||||||
if (!canceled) progress->Destroy();
|
|
||||||
else throw wxString(_T("Keyframe loading cancelled by user"));
|
|
||||||
|
|
||||||
return keyframes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the video duration in frames
|
|
||||||
int LAVCKeyFrames::GetNumFrames() {
|
|
||||||
return numFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the frame metadata vector
|
|
||||||
LAVCFrameInfoVector LAVCKeyFrames::GetFrameData() {
|
|
||||||
return framesData;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // WITH_FFMPEG
|
|
|
@ -1,64 +0,0 @@
|
||||||
// Copyright (c) 2007, 2points
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <wx/wxprec.h>
|
|
||||||
#include "lavc_file.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct LAVCFrameInfo {
|
|
||||||
int64_t DTS;
|
|
||||||
bool isKeyFrame;
|
|
||||||
LAVCFrameInfo(int64_t ADTS, bool isAKeyFrame) : DTS(ADTS), isKeyFrame(isAKeyFrame) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<LAVCFrameInfo> LAVCFrameInfoVector;
|
|
||||||
|
|
||||||
class LAVCKeyFrames {
|
|
||||||
private:
|
|
||||||
LAVCFile* file; // Video file
|
|
||||||
AVStream* stream; // Used stream
|
|
||||||
int streamN; // Stream index
|
|
||||||
int numFrames; // number of frames in the video
|
|
||||||
protected:
|
|
||||||
LAVCFrameInfoVector framesData;
|
|
||||||
public:
|
|
||||||
LAVCKeyFrames(const Aegisub::String filename);
|
|
||||||
~LAVCKeyFrames();
|
|
||||||
wxArrayInt GetKeyFrames();
|
|
||||||
int GetNumFrames();
|
|
||||||
LAVCFrameInfoVector GetFrameData();
|
|
||||||
};
|
|
|
@ -165,17 +165,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//////////
|
|
||||||
// FFMPEG
|
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
#ifndef WITH_STATIC_FFMPEG
|
|
||||||
#pragma comment(lib, "avcodec-51.lib")
|
|
||||||
#pragma comment(lib, "avformat-51.lib")
|
|
||||||
#pragma comment(lib, "avutil-49.lib")
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
// FreeType2
|
// FreeType2
|
||||||
#ifdef WITH_FREETYPE2
|
#ifdef WITH_FREETYPE2
|
||||||
|
|
|
@ -1,419 +0,0 @@
|
||||||
// Copyright (c) 2006-2007, Rodrigo Braz Monteiro
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define EMULATE_INTTYPES
|
|
||||||
#define __STDC_CONSTANT_MACROS 1
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif /* WIN32 */
|
|
||||||
|
|
||||||
#include <wx/wxprec.h>
|
|
||||||
#include <wx/image.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include "video_provider_lavc.h"
|
|
||||||
#include "mkv_wrap.h"
|
|
||||||
#include "lavc_file.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "vfr.h"
|
|
||||||
#include "ass_file.h"
|
|
||||||
#include "lavc_keyframes.h"
|
|
||||||
#include "video_context.h"
|
|
||||||
#include "options.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// Constructor
|
|
||||||
LAVCVideoProvider::LAVCVideoProvider(Aegisub::String filename,double fps) {
|
|
||||||
// Init variables
|
|
||||||
codecContext = NULL;
|
|
||||||
lavcfile = NULL;
|
|
||||||
codec = NULL;
|
|
||||||
stream = NULL;
|
|
||||||
frame = NULL;
|
|
||||||
frameRGB = NULL;
|
|
||||||
bufferRGB = NULL;
|
|
||||||
sws_context = NULL;
|
|
||||||
buffer1 = NULL;
|
|
||||||
buffer2 = NULL;
|
|
||||||
buffer1Size = 0;
|
|
||||||
buffer2Size = 0;
|
|
||||||
vidStream = -1;
|
|
||||||
validFrame = false;
|
|
||||||
framesData.clear();
|
|
||||||
|
|
||||||
// Load
|
|
||||||
LoadVideo(filename,fps);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
|
||||||
// Destructor
|
|
||||||
LAVCVideoProvider::~LAVCVideoProvider() {
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////
|
|
||||||
// Load video
|
|
||||||
void LAVCVideoProvider::LoadVideo(Aegisub::String filename, double fps) {
|
|
||||||
// Close first
|
|
||||||
Close();
|
|
||||||
|
|
||||||
lavcfile = LAVCFile::Create(filename);
|
|
||||||
// Load
|
|
||||||
try {
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
// Find video stream
|
|
||||||
vidStream = -1;
|
|
||||||
codecContext = NULL;
|
|
||||||
for (int i=0; i < (int)lavcfile->fctx->nb_streams; i++) {
|
|
||||||
codecContext = lavcfile->fctx->streams[i]->codec;
|
|
||||||
if (codecContext->codec_type == CODEC_TYPE_VIDEO) {
|
|
||||||
stream = lavcfile->fctx->streams[i];
|
|
||||||
vidStream = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vidStream == -1) throw _T("ffmpeg video provider: Could not find a video stream");
|
|
||||||
|
|
||||||
// Find codec
|
|
||||||
codec = avcodec_find_decoder(codecContext->codec_id);
|
|
||||||
if (!codec) throw _T("ffmpeg video provider: Could not find suitable video decoder");
|
|
||||||
|
|
||||||
// Enable truncation
|
|
||||||
//if (codec->capabilities & CODEC_CAP_TRUNCATED) codecContext->flags |= CODEC_FLAG_TRUNCATED;
|
|
||||||
|
|
||||||
// Open codec
|
|
||||||
result = avcodec_open(codecContext,codec);
|
|
||||||
if (result < 0) throw _T("ffmpeg video provider: Failed to open video decoder");
|
|
||||||
|
|
||||||
// Parse file for keyframes and other useful stuff
|
|
||||||
LAVCKeyFrames LAVCFrameData(filename);
|
|
||||||
KeyFramesList = LAVCFrameData.GetKeyFrames();
|
|
||||||
keyFramesLoaded = true;
|
|
||||||
// set length etc.
|
|
||||||
length = LAVCFrameData.GetNumFrames();
|
|
||||||
framesData = LAVCFrameData.GetFrameData();
|
|
||||||
|
|
||||||
std::vector<int> timecodesVector;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
int timestamp = (int)((framesData[i].DTS * (int64_t)lavcfile->fctx->streams[vidStream]->time_base.num * 1000)
|
|
||||||
/ (int64_t)lavcfile->fctx->streams[vidStream]->time_base.den);
|
|
||||||
timecodesVector.push_back(timestamp);
|
|
||||||
}
|
|
||||||
timecodes.SetVFR(timecodesVector);
|
|
||||||
int OverrideTC = wxYES;
|
|
||||||
if (VFR_Output.IsLoaded()) {
|
|
||||||
OverrideTC = wxMessageBox(_("You already have timecodes loaded. Would you like to replace them with timecodes from the video file?"), _("Replace timecodes?"), wxYES_NO | wxICON_QUESTION);
|
|
||||||
if (OverrideTC == wxYES) {
|
|
||||||
VFR_Input.SetVFR(timecodesVector);
|
|
||||||
VFR_Output.SetVFR(timecodesVector);
|
|
||||||
}
|
|
||||||
} else { // no timecodes loaded, go ahead and apply
|
|
||||||
VFR_Input.SetVFR(timecodesVector);
|
|
||||||
VFR_Output.SetVFR(timecodesVector);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate frame
|
|
||||||
frame = avcodec_alloc_frame();
|
|
||||||
|
|
||||||
// Set frame
|
|
||||||
frameNumber = -1;
|
|
||||||
lastFrameNumber = -1;
|
|
||||||
|
|
||||||
allowUnsafeSeeking = Options.AsBool(_T("FFmpeg allow unsafe seeking"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch errors
|
|
||||||
catch (...) {
|
|
||||||
Close();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
|
||||||
// Close video
|
|
||||||
void LAVCVideoProvider::Close() {
|
|
||||||
// Clean buffers
|
|
||||||
if (buffer1) delete buffer1;
|
|
||||||
if (buffer2) delete buffer2;
|
|
||||||
buffer1 = NULL;
|
|
||||||
buffer2 = NULL;
|
|
||||||
buffer1Size = 0;
|
|
||||||
buffer2Size = 0;
|
|
||||||
|
|
||||||
// Clean frame
|
|
||||||
if (frame) av_free((void*)frame);
|
|
||||||
frame = NULL;
|
|
||||||
|
|
||||||
// Free SWS context and other stuff from RGB conversion
|
|
||||||
if (sws_context)
|
|
||||||
sws_freeContext(sws_context);
|
|
||||||
sws_context = NULL;
|
|
||||||
if(frameRGB)
|
|
||||||
av_free(frameRGB);
|
|
||||||
frameRGB = NULL;
|
|
||||||
if(bufferRGB)
|
|
||||||
delete(bufferRGB);
|
|
||||||
bufferRGB = NULL;
|
|
||||||
|
|
||||||
// Close codec context
|
|
||||||
if (codec && codecContext) avcodec_close(codecContext);
|
|
||||||
codecContext = NULL;
|
|
||||||
codec = NULL;
|
|
||||||
|
|
||||||
// Close format context
|
|
||||||
if (lavcfile)
|
|
||||||
lavcfile->Release();
|
|
||||||
lavcfile = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
|
||||||
// Get next frame
|
|
||||||
bool LAVCVideoProvider::GetNextFrame(int64_t *startDTS) {
|
|
||||||
AVPacket packet;
|
|
||||||
*startDTS = -1; // magic
|
|
||||||
|
|
||||||
// Read packet
|
|
||||||
while (av_read_frame(lavcfile->fctx, &packet)>=0) {
|
|
||||||
// Check if packet is part of video stream
|
|
||||||
if(packet.stream_index == vidStream) {
|
|
||||||
// Decode frame
|
|
||||||
int frameFinished;
|
|
||||||
if (*startDTS < 0)
|
|
||||||
*startDTS = packet.dts;
|
|
||||||
|
|
||||||
avcodec_decode_video(codecContext, frame, &frameFinished, packet.data, packet.size);
|
|
||||||
|
|
||||||
// Success?
|
|
||||||
if(frameFinished) {
|
|
||||||
// Set time
|
|
||||||
lastDecodeTime = packet.dts;
|
|
||||||
|
|
||||||
// Free packet and return
|
|
||||||
av_free_packet(&packet);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// free packet
|
|
||||||
av_free_packet(&packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No more packets
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////
|
|
||||||
// Get frame
|
|
||||||
const AegiVideoFrame LAVCVideoProvider::GetFrame(int n,int formatType) {
|
|
||||||
// Return stored frame
|
|
||||||
// n = MID(0,n,GetFrameCount()-1);
|
|
||||||
if (n == lastFrameNumber) {
|
|
||||||
if (!validFrame) validFrame = true;
|
|
||||||
return curFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frameNumber < 0)
|
|
||||||
frameNumber = 0;
|
|
||||||
|
|
||||||
// Find closest keyframe to the frame we want
|
|
||||||
int closestKeyFrame = FindClosestKeyframe(n);
|
|
||||||
|
|
||||||
bool hasSeeked = false;
|
|
||||||
|
|
||||||
// do we really need to seek?
|
|
||||||
// 10 frames is used as a margin to prevent excessive seeking since the predicted best keyframe isn't always selected by avformat
|
|
||||||
if (n < frameNumber || closestKeyFrame > frameNumber+10) {
|
|
||||||
// turns out we did need it, just do it
|
|
||||||
av_seek_frame(lavcfile->fctx, vidStream, framesData[closestKeyFrame].DTS, AVSEEK_FLAG_BACKWARD);
|
|
||||||
avcodec_flush_buffers(codecContext);
|
|
||||||
hasSeeked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// regardless of whether we sekeed or not, decode frames until we have the one we want
|
|
||||||
do {
|
|
||||||
int64_t startTime;
|
|
||||||
GetNextFrame(&startTime);
|
|
||||||
|
|
||||||
if (hasSeeked) {
|
|
||||||
hasSeeked = false;
|
|
||||||
|
|
||||||
// is the seek destination known? does it belong to a frame?
|
|
||||||
if (startTime < 0 || (frameNumber = FrameFromDTS(startTime)) < 0) {
|
|
||||||
// guessing destination, may be unsafe
|
|
||||||
if (allowUnsafeSeeking)
|
|
||||||
frameNumber = ClosestFrameFromDTS(startTime);
|
|
||||||
else
|
|
||||||
throw _T("ffmpeg video provider: frame accurate seeking failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
frameNumber++;
|
|
||||||
} while (frameNumber <= n);
|
|
||||||
|
|
||||||
|
|
||||||
// Get aegisub frame
|
|
||||||
AegiVideoFrame &final = curFrame;
|
|
||||||
|
|
||||||
if (frame) {
|
|
||||||
int w = codecContext->width;
|
|
||||||
int h = codecContext->height;
|
|
||||||
PixelFormat srcFormat = codecContext->pix_fmt;
|
|
||||||
PixelFormat dstFormat = PIX_FMT_BGRA;
|
|
||||||
|
|
||||||
// Allocate RGB32 buffer
|
|
||||||
if(!sws_context) //first frame
|
|
||||||
{
|
|
||||||
frameRGB = avcodec_alloc_frame();
|
|
||||||
unsigned int dstSize = avpicture_get_size(dstFormat,w,h);
|
|
||||||
bufferRGB = new uint8_t[dstSize];
|
|
||||||
|
|
||||||
sws_context = sws_getContext(w, h, srcFormat, w, h, dstFormat, SWS_PRINT_INFO | SWS_BICUBIC, NULL, NULL, NULL);
|
|
||||||
// sws_getContext() always returns NULL if context creation failed
|
|
||||||
if (sws_context == NULL)
|
|
||||||
throw _T("ffmpeg video provider: failed to initialize SwScaler colorspace conversion");
|
|
||||||
}
|
|
||||||
avpicture_fill((AVPicture*) frameRGB, bufferRGB, dstFormat, w, h);
|
|
||||||
|
|
||||||
// Set AegiVideoFrame
|
|
||||||
final.w = codecContext->width;
|
|
||||||
final.h = codecContext->height;
|
|
||||||
final.flipped = false;
|
|
||||||
final.invertChannels = true;
|
|
||||||
final.format = FORMAT_RGB32;
|
|
||||||
|
|
||||||
// Allocate
|
|
||||||
for (int i=0;i<4;i++) final.pitch[i] = frameRGB->linesize[i];
|
|
||||||
final.Allocate();
|
|
||||||
|
|
||||||
// Convert to RGB32, and write directly to the output frame
|
|
||||||
sws_scale(sws_context, frame->data, frame->linesize, 0, h, final.data, frameRGB->linesize);
|
|
||||||
|
|
||||||
}
|
|
||||||
else // No frame available
|
|
||||||
{
|
|
||||||
final = AegiVideoFrame(GetWidth(),GetHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set current frame
|
|
||||||
validFrame = true;
|
|
||||||
lastFrameNumber = n;
|
|
||||||
|
|
||||||
// Return
|
|
||||||
return final;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////
|
|
||||||
// Get position
|
|
||||||
int LAVCVideoProvider::GetPosition() {
|
|
||||||
return frameNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// Get number of frames
|
|
||||||
int LAVCVideoProvider::GetFrameCount() {
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
|
||||||
// Get frame rate
|
|
||||||
double LAVCVideoProvider::GetFPS() {
|
|
||||||
return double(stream->r_frame_rate.num) / double(stream->r_frame_rate.den);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// Get original width
|
|
||||||
int LAVCVideoProvider::GetWidth() {
|
|
||||||
return codecContext->width;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// Get original height
|
|
||||||
int LAVCVideoProvider::GetHeight() {
|
|
||||||
return codecContext->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// Find the keyframe we should seek to if we want to seek to a given frame N
|
|
||||||
int LAVCVideoProvider::FindClosestKeyframe(int frameN) {
|
|
||||||
for (int i = frameN; i > 0; i--)
|
|
||||||
if (framesData[i].isKeyFrame)
|
|
||||||
return i;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// Convert a DTS into a frame number
|
|
||||||
int LAVCVideoProvider::FrameFromDTS(int64_t ADTS) {
|
|
||||||
for (int i = 0; i < (int)framesData.size(); i++)
|
|
||||||
if (framesData[i].DTS == ADTS)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// Find closest frame to the given DTS
|
|
||||||
int LAVCVideoProvider::ClosestFrameFromDTS(int64_t ADTS) {
|
|
||||||
int n = 0;
|
|
||||||
int64_t bestDiff = 0xFFFFFFFFFFFFFFLL; // big number
|
|
||||||
for (int i = 0; i < (int)framesData.size(); i++) {
|
|
||||||
int64_t currentDiff = FFABS(framesData[i].DTS - ADTS);
|
|
||||||
if (currentDiff < bestDiff) {
|
|
||||||
bestDiff = currentDiff;
|
|
||||||
n = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // WITH_FFMPEG
|
|
|
@ -1,140 +0,0 @@
|
||||||
// Copyright (c) 2006-2007, Rodrigo Braz Monteiro
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
|
||||||
// and/or other materials provided with the distribution.
|
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
||||||
// may be used to endorse or promote products derived from this software
|
|
||||||
// without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
||||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// AEGISUB
|
|
||||||
//
|
|
||||||
// Website: http://aegisub.cellosoft.com
|
|
||||||
// Contact: mailto:zeratul@cellosoft.com
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Headers
|
|
||||||
|
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define EMULATE_INTTYPES
|
|
||||||
#endif
|
|
||||||
#include <vector>
|
|
||||||
extern "C" {
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
#include <libswscale/swscale.h>
|
|
||||||
}
|
|
||||||
#include "include/aegisub/video_provider.h"
|
|
||||||
#include "include/aegisub/aegisub.h"
|
|
||||||
#include "mkv_wrap.h"
|
|
||||||
#include "lavc_file.h"
|
|
||||||
#include "lavc_keyframes.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
// LibAVCodec provider
|
|
||||||
class LAVCVideoProvider : public VideoProvider {
|
|
||||||
friend class LAVCAudioProvider;
|
|
||||||
private:
|
|
||||||
MatroskaWrapper mkv;
|
|
||||||
|
|
||||||
LAVCFile *lavcfile;
|
|
||||||
AVCodecContext *codecContext;
|
|
||||||
AVStream *stream;
|
|
||||||
AVCodec *codec;
|
|
||||||
AVFrame *frame;
|
|
||||||
int vidStream;
|
|
||||||
|
|
||||||
AVFrame *frameRGB;
|
|
||||||
uint8_t *bufferRGB;
|
|
||||||
SwsContext *sws_context;
|
|
||||||
|
|
||||||
wxArrayInt KeyFramesList;
|
|
||||||
bool keyFramesLoaded;
|
|
||||||
// bool isVfr; // currently unused
|
|
||||||
|
|
||||||
int display_w;
|
|
||||||
int display_h;
|
|
||||||
|
|
||||||
wxArrayInt bytePos;
|
|
||||||
|
|
||||||
bool allowUnsafeSeeking;
|
|
||||||
bool isMkv;
|
|
||||||
int64_t lastDecodeTime;
|
|
||||||
int frameNumber;
|
|
||||||
int lastFrameNumber;
|
|
||||||
int length;
|
|
||||||
AegiVideoFrame curFrame;
|
|
||||||
bool validFrame;
|
|
||||||
LAVCFrameInfoVector framesData;
|
|
||||||
FrameRate timecodes;
|
|
||||||
|
|
||||||
uint8_t *buffer1;
|
|
||||||
uint8_t *buffer2;
|
|
||||||
int buffer1Size;
|
|
||||||
int buffer2Size;
|
|
||||||
|
|
||||||
int FindClosestKeyframe(int frameN);
|
|
||||||
int FrameFromDTS(int64_t ADTS);
|
|
||||||
int ClosestFrameFromDTS(int64_t ADTS);
|
|
||||||
bool GetNextFrame(int64_t *DTS);
|
|
||||||
void LoadVideo(Aegisub::String filename, double fps);
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
public:
|
|
||||||
LAVCVideoProvider(Aegisub::String filename, double fps);
|
|
||||||
~LAVCVideoProvider();
|
|
||||||
|
|
||||||
const AegiVideoFrame GetFrame(int n,int formatType);
|
|
||||||
int GetPosition();
|
|
||||||
int GetFrameCount();
|
|
||||||
|
|
||||||
int GetWidth();
|
|
||||||
int GetHeight();
|
|
||||||
double GetFPS();
|
|
||||||
bool AreKeyFramesLoaded() { return keyFramesLoaded; };
|
|
||||||
wxArrayInt GetKeyFrames() { return KeyFramesList; };
|
|
||||||
bool IsVFR() { return true; };
|
|
||||||
FrameRate GetTrueFrameRate() { return timecodes; };
|
|
||||||
Aegisub::String GetDecoderName() { return L"FFMpeg/libavcodec"; }
|
|
||||||
bool IsNativelyByFrames() { return true; }
|
|
||||||
int GetDesiredCacheSize() { return 8; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////
|
|
||||||
// Factory
|
|
||||||
class LAVCVideoProviderFactory : public VideoProviderFactory {
|
|
||||||
public:
|
|
||||||
VideoProvider *CreateProvider(Aegisub::String video,double fps=0.0) { return new LAVCVideoProvider(video,fps); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -48,9 +48,6 @@
|
||||||
#ifdef WITH_DIRECTSHOW
|
#ifdef WITH_DIRECTSHOW
|
||||||
#include "video_provider_dshow.h"
|
#include "video_provider_dshow.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
#include "video_provider_lavc.h"
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
#include "video_provider_ffmpegsource.h"
|
#include "video_provider_ffmpegsource.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,9 +110,6 @@ void VideoProviderFactoryManager::RegisterProviders() {
|
||||||
#ifdef WITH_DIRECTSHOW
|
#ifdef WITH_DIRECTSHOW
|
||||||
RegisterFactory(new DirectShowVideoProviderFactory(),_T("DirectShow"));
|
RegisterFactory(new DirectShowVideoProviderFactory(),_T("DirectShow"));
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_FFMPEG
|
|
||||||
RegisterFactory(new LAVCVideoProviderFactory(),_T("FFMPEG"));
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
RegisterFactory(new FFmpegSourceVideoProviderFactory(),_T("FFmpegSource"));
|
RegisterFactory(new FFmpegSourceVideoProviderFactory(),_T("FFmpegSource"));
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue