FFmpegSource 1.11

Originally committed to SVN as r1556.
This commit is contained in:
Fredrik Mellbin 2007-09-07 20:07:27 +00:00
parent 67d8412a9a
commit 4b87a7a9ad
9 changed files with 427 additions and 316 deletions

View file

@ -107,7 +107,7 @@ bool FFBase::SaveTimecodesToFile(const char *ATimecodeFile, int64_t ScaleD, int6
return true; return true;
} }
#ifdef FLAC_CACHE
static FLAC__StreamDecoderReadStatus FLACStreamDecoderReadCallback(const FLAC__StreamDecoder *ADecoder, FLAC__byte ABuffer[], size_t *ABytes, FFBase *AOwner) { static FLAC__StreamDecoderReadStatus FLACStreamDecoderReadCallback(const FLAC__StreamDecoder *ADecoder, FLAC__byte ABuffer[], size_t *ABytes, FFBase *AOwner) {
if(*ABytes > 0) { if(*ABytes > 0) {
*ABytes = fread(ABuffer, sizeof(FLAC__byte), *ABytes, AOwner->FCFile); *ABytes = fread(ABuffer, sizeof(FLAC__byte), *ABytes, AOwner->FCFile);
@ -182,6 +182,7 @@ static void FLACStreamDecoderMetadataCallback(const FLAC__StreamDecoder *ADecode
static void FLACStreamDecoderErrorCallback(const FLAC__StreamDecoder *ADecoder, FLAC__StreamDecoderErrorStatus AStatus, FFBase *AOwner) { static void FLACStreamDecoderErrorCallback(const FLAC__StreamDecoder *ADecoder, FLAC__StreamDecoderErrorStatus AStatus, FFBase *AOwner) {
AOwner->FCError = true; AOwner->FCError = true;
} }
#endif // FLAC_CACHE
bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env) { bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env) {
char DefaultCacheFilename[1024]; char DefaultCacheFilename[1024];
@ -205,7 +206,8 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in
return false; return false;
} }
// If FLAC? #ifdef FLAC_CACHE
// is FLAC?
FLACAudioCache = FLAC__stream_decoder_new(); FLACAudioCache = FLAC__stream_decoder_new();
if (FLAC__stream_decoder_init_stream(FLACAudioCache, if (FLAC__stream_decoder_init_stream(FLACAudioCache,
&(FLAC__StreamDecoderReadCallback)FLACStreamDecoderReadCallback, &(FLAC__StreamDecoderReadCallback)FLACStreamDecoderReadCallback,
@ -225,6 +227,7 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in
} }
FLAC__stream_decoder_delete(FLACAudioCache); FLAC__stream_decoder_delete(FLACAudioCache);
FLACAudioCache = NULL; FLACAudioCache = NULL;
#endif // FLAC_CACHE
// Raw audio // Raw audio
VI.num_audio_samples = VI.AudioSamplesFromBytes(CacheSize); VI.num_audio_samples = VI.AudioSamplesFromBytes(CacheSize);
@ -234,6 +237,7 @@ bool FFBase::OpenAudioCache(const char *AAudioCacheFile, const char *ASource, in
return true; return true;
} }
#ifdef FLAC_CACHE
static FLAC__StreamEncoderWriteStatus FLACStreamEncoderWriteCallback(const FLAC__StreamEncoder *ASncoder, const FLAC__byte ABuffer[], size_t ABytes, unsigned ABamples, unsigned ACurrentFrame, FFBase *AOwner) { static FLAC__StreamEncoderWriteStatus FLACStreamEncoderWriteCallback(const FLAC__StreamEncoder *ASncoder, const FLAC__byte ABuffer[], size_t ABytes, unsigned ABamples, unsigned ACurrentFrame, FFBase *AOwner) {
fwrite(ABuffer, sizeof(FLAC__byte), ABytes, AOwner->FCFile); fwrite(ABuffer, sizeof(FLAC__byte), ABytes, AOwner->FCFile);
if(ferror(AOwner->FCFile)) if(ferror(AOwner->FCFile))
@ -289,6 +293,7 @@ void FFBase::CloseFLACCacheWriter(FLAC__StreamEncoder *AFSE) {
fclose(FCFile); fclose(FCFile);
FCFile = NULL; FCFile = NULL;
} }
#endif // FLAC_CACHE
FILE *FFBase::NewRawCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env) { FILE *FFBase::NewRawCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env) {
char DefaultCacheFilename[1024]; char DefaultCacheFilename[1024];
@ -392,16 +397,18 @@ PVideoFrame FFBase::OutputFrame(AVFrame *AFrame, IScriptEnvironment *Env) {
return Dst; return Dst;
} }
void __stdcall FFBase::GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment* Env) { void FFBase::GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment* Env) {
if (AudioCacheType == acRaw) { if (AudioCacheType == acRaw) {
_fseeki64(RawAudioCache, VI.BytesFromAudioSamples(Start), SEEK_SET); _fseeki64(RawAudioCache, VI.BytesFromAudioSamples(Start), SEEK_SET);
fread(Buf, 1, VI.BytesFromAudioSamples(Count), RawAudioCache); fread(Buf, 1, VI.BytesFromAudioSamples(Count), RawAudioCache);
#ifdef FLAC_CACHE
} else if (AudioCacheType == acFLAC) { } else if (AudioCacheType == acFLAC) {
FCCount = Count; FCCount = Count;
FCBuffer = Buf; FCBuffer = Buf;
FLAC__stream_decoder_seek_absolute(FLACAudioCache, Start); FLAC__stream_decoder_seek_absolute(FLACAudioCache, Start);
while (FCCount > 0) while (FCCount > 0)
FLAC__stream_decoder_process_single(FLACAudioCache); FLAC__stream_decoder_process_single(FLACAudioCache);
#endif // FLAC_CACHE
} else { } else {
Env->ThrowError("FFmpegSource: Audio requested but none available"); Env->ThrowError("FFmpegSource: Audio requested but none available");
} }
@ -412,12 +419,14 @@ FFBase::FFBase() {
AudioCacheType = acNone; AudioCacheType = acNone;
FCError = false; FCError = false;
RawAudioCache = NULL; RawAudioCache = NULL;
FLACAudioCache = NULL;
PPContext = NULL; PPContext = NULL;
PPMode = NULL; PPMode = NULL;
SWS = NULL; SWS = NULL;
DecodingBuffer = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE]; DecodingBuffer = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE];
#ifdef FLAC_CACHE
FLACAudioCache = NULL;
FLACBuffer = new FLAC__int32[AVCODEC_MAX_AUDIO_FRAME_SIZE]; FLACBuffer = new FLAC__int32[AVCODEC_MAX_AUDIO_FRAME_SIZE];
#endif // FLAC_CACHE
FCFile = NULL; FCFile = NULL;
ConvertToFormat = PIX_FMT_NONE; ConvertToFormat = PIX_FMT_NONE;
memset(&PPPicture, 0, sizeof(PPPicture)); memset(&PPPicture, 0, sizeof(PPPicture));
@ -426,13 +435,15 @@ FFBase::FFBase() {
FFBase::~FFBase() { FFBase::~FFBase() {
delete [] DecodingBuffer; delete [] DecodingBuffer;
delete [] FLACBuffer;
if (RawAudioCache) if (RawAudioCache)
fclose(RawAudioCache); fclose(RawAudioCache);
#ifdef FLAC_CACHE
delete [] FLACBuffer;
if (FLACAudioCache) { if (FLACAudioCache) {
FLAC__stream_decoder_finish(FLACAudioCache); FLAC__stream_decoder_finish(FLACAudioCache);
FLAC__stream_decoder_delete(FLACAudioCache); FLAC__stream_decoder_delete(FLACAudioCache);
} }
#endif // FLAC_CACHE
if (FCFile) if (FCFile)
fclose(FCFile); fclose(FCFile);
if (SWS) if (SWS)

View file

@ -19,27 +19,8 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "ffmpegsource.h" #include "ffmpegsource.h"
#include "stdiostream.c"
class FFMatroskaSource : public FFBase { int FFMatroskaSource::GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env) {
private:
StdIoStream ST;
unsigned int BufferSize;
CompressedStream *VideoCS;
CompressedStream *AudioCS;
AVCodecContext *VideoCodecContext;
MatroskaFile *MF;
char ErrorMessage[256];
uint8_t *Buffer;
int CurrentFrame;
int ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, CompressedStream *ACS, IScriptEnvironment *Env);
int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, IScriptEnvironment* Env);
int GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env) {
if (Index == -1) if (Index == -1)
for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++) for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++)
if (mkv_GetTrackInfo(MF, i)->Type == ATrackType) { if (mkv_GetTrackInfo(MF, i)->Type == ATrackType) {
@ -63,8 +44,7 @@ private:
return Index; return Index;
} }
public: FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, int AACCompression, const char *APPString, int AQuality, IScriptEnvironment* Env) {
FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, int AACCompression, const char *APPString, int AQuality, IScriptEnvironment* Env) {
CurrentFrame = 0; CurrentFrame = 0;
int VideoTrack; int VideoTrack;
int AudioTrack; int AudioTrack;
@ -216,8 +196,9 @@ public:
// Needs to be indexed? // Needs to be indexed?
if (!ACacheIsValid || !VCacheIsValid) { if (!ACacheIsValid || !VCacheIsValid) {
#ifdef FLAC_CACHE
FLAC__StreamEncoder *FSE = NULL; FLAC__StreamEncoder *FSE = NULL;
#endif // FLAC_CACHE
FILE *RawCache = NULL; FILE *RawCache = NULL;
if (!ACacheIsValid) if (!ACacheIsValid)
if (AACCompression >= 0) if (AACCompression >= 0)
@ -226,7 +207,9 @@ public:
AudioCacheType = acRaw; AudioCacheType = acRaw;
switch (AudioCacheType) { switch (AudioCacheType) {
#ifdef FLAC_CACHE
case acFLAC: FSE = NewFLACCacheWriter(AAudioCache, ASource, AudioTrack, AACCompression, Env); break; case acFLAC: FSE = NewFLACCacheWriter(AAudioCache, ASource, AudioTrack, AACCompression, Env); break;
#endif // FLAC_CACHE
case acRaw: RawCache = NewRawCacheWriter(AAudioCache, ASource, AudioTrack, Env); break; case acRaw: RawCache = NewRawCacheWriter(AAudioCache, ASource, AudioTrack, Env); break;
} }
@ -253,19 +236,23 @@ public:
Data += Ret; Data += Ret;
VI.num_audio_samples += DecodedSamples; VI.num_audio_samples += DecodedSamples;
if (AudioCacheType == acFLAC) { if (AudioCacheType == acRaw) {
fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache);
#ifdef FLAC_CACHE
} else if (AudioCacheType == acFLAC) {
for (int i = 0; i < DecodedSamples * VI.nchannels; i++) for (int i = 0; i < DecodedSamples * VI.nchannels; i++)
FLACBuffer[i] = ((int16_t *)DecodingBuffer)[i]; FLACBuffer[i] = ((int16_t *)DecodingBuffer)[i];
FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples); FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples);
} else if (AudioCacheType == acRaw) { #endif // FLAC_CACHE
fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache);
} }
} }
} }
if (!ACacheIsValid) { if (!ACacheIsValid) {
switch (AudioCacheType) { switch (AudioCacheType) {
#ifdef FLAC_CACHE
case acFLAC: CloseFLACCacheWriter(FSE); break; case acFLAC: CloseFLACCacheWriter(FSE); break;
#endif // FLAC_CACHE
case acRaw: CloseRawCacheWriter(RawCache); break; case acRaw: CloseRawCacheWriter(RawCache); break;
} }
@ -308,7 +295,7 @@ public:
} }
} }
~FFMatroskaSource() { FFMatroskaSource::~FFMatroskaSource() {
free(Buffer); free(Buffer);
mkv_Close(MF); mkv_Close(MF);
fclose(ST.fp); fclose(ST.fp);
@ -317,9 +304,6 @@ public:
av_free(VideoCodecContext); av_free(VideoCodecContext);
} }
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env);
};
int FFMatroskaSource::ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, CompressedStream *ACS, IScriptEnvironment *Env) { int FFMatroskaSource::ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, CompressedStream *ACS, IScriptEnvironment *Env) {
if (ACS) { if (ACS) {
char CSBuffer[4096]; char CSBuffer[4096];
@ -401,7 +385,7 @@ Done:
return Ret; return Ret;
} }
PVideoFrame __stdcall FFMatroskaSource::GetFrame(int n, IScriptEnvironment* Env) { PVideoFrame FFMatroskaSource::GetFrame(int n, IScriptEnvironment* Env) {
bool HasSeeked = false; bool HasSeeked = false;
if (n < CurrentFrame || FindClosestKeyFrame(n) > CurrentFrame) { if (n < CurrentFrame || FindClosestKeyFrame(n) > CurrentFrame) {
@ -426,53 +410,3 @@ PVideoFrame __stdcall FFMatroskaSource::GetFrame(int n, IScriptEnvironment* Env)
return OutputFrame(DecodeFrame, Env); return OutputFrame(DecodeFrame, Env);
} }
AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
if (!UserData) {
av_register_all();
UserData = (void *)-1;
}
if (!Args[0].Defined())
Env->ThrowError("FFmpegSource: No source specified");
const char *Source = Args[0].AsString();
int VTrack = Args[1].AsInt(-1);
int ATrack = Args[2].AsInt(-2);
const char *Timecodes = Args[3].AsString("");
bool VCache = Args[4].AsBool(true);
const char *VCacheFile = Args[5].AsString("");
const char *ACacheFile = Args[6].AsString("");
int ACCompression = Args[7].AsInt(-1);
const char *PPString = Args[8].AsString("");
int PPQuality = Args[9].AsInt(PP_QUALITY_MAX);
int SeekMode = Args[10].AsInt(1);
if (VTrack <= -2 && ATrack <= -2)
Env->ThrowError("FFmpegSource: No tracks selected");
if (ACCompression < -1 || ACCompression > 8)
Env->ThrowError("FFmpegSource: Invalid audio cache compression selected");
AVFormatContext *FormatContext;
if (av_open_input_file(&FormatContext, Source, NULL, 0, NULL) != 0)
Env->ThrowError("FFmpegSource: Couldn't open %s", Args[0].AsString());
bool IsMatroska = !strcmp(FormatContext->iformat->name, "matroska");
av_close_input_file(FormatContext);
if (IsMatroska)
return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, Env);
else
return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, SeekMode, Env);
}
AVSValue __cdecl CreateFFPP(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
return new FFPP(Args[0].AsClip(), Args[1].AsString(""), Args[2].AsInt(PP_QUALITY_MAX), Env);
}
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) {
Env->AddFunction("FFmpegSource", "[source]s[vtrack]i[atrack]i[timecodes]s[vcache]b[vcachefile]s[acachefile]s[accompression]i[pp]s[ppquality]i[seekmode]i", CreateFFmpegSource, 0);
Env->AddFunction("FFPP", "c[pp]s[ppquality]i", CreateFFPP, 0);
return "FFmpegSource";
};

View file

@ -126,8 +126,9 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack
// Needs to be indexed? // Needs to be indexed?
if (!ACacheIsValid || !VCacheIsValid) { if (!ACacheIsValid || !VCacheIsValid) {
#ifdef FLAC_CACHE
FLAC__StreamEncoder *FSE = NULL; FLAC__StreamEncoder *FSE = NULL;
#endif // FLAC_CACHE
FILE *RawCache = NULL; FILE *RawCache = NULL;
if (!ACacheIsValid) if (!ACacheIsValid)
if (AACCompression >= 0) if (AACCompression >= 0)
@ -136,7 +137,9 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack
AudioCacheType = acRaw; AudioCacheType = acRaw;
switch (AudioCacheType) { switch (AudioCacheType) {
#ifdef FLAC_CACHE
case acFLAC: FSE = NewFLACCacheWriter(AAudioCache, ASource, AudioTrack, AACCompression, Env); break; case acFLAC: FSE = NewFLACCacheWriter(AAudioCache, ASource, AudioTrack, AACCompression, Env); break;
#endif // FLAC_CACHE
case acRaw: RawCache = NewRawCacheWriter(AAudioCache, ASource, AudioTrack, Env); break; case acRaw: RawCache = NewRawCacheWriter(AAudioCache, ASource, AudioTrack, Env); break;
} }
@ -161,12 +164,14 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack
Data += Ret; Data += Ret;
VI.num_audio_samples += DecodedSamples; VI.num_audio_samples += DecodedSamples;
if (AudioCacheType == acFLAC) { if (AudioCacheType == acRaw) {
fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache);
#ifdef FLAC_CACHE
} else if (AudioCacheType == acFLAC) {
for (int i = 0; i < DecodedSamples * VI.nchannels; i++) for (int i = 0; i < DecodedSamples * VI.nchannels; i++)
FLACBuffer[i] = ((int16_t *)DecodingBuffer)[i]; FLACBuffer[i] = ((int16_t *)DecodingBuffer)[i];
FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples); FLAC__stream_encoder_process_interleaved(FSE, FLACBuffer, DecodedSamples);
} else if (AudioCacheType == acRaw) { #endif // FLAC_CACHE
fwrite(DecodingBuffer, 1, TempOutputBufSize, RawCache);
} }
} }
} }
@ -176,7 +181,9 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack
if (!ACacheIsValid) { if (!ACacheIsValid) {
switch (AudioCacheType) { switch (AudioCacheType) {
#ifdef FLAC_CACHE
case acFLAC: CloseFLACCacheWriter(FSE); break; case acFLAC: CloseFLACCacheWriter(FSE); break;
#endif // FLAC_CACHE
case acRaw: CloseRawCacheWriter(RawCache); break; case acRaw: CloseRawCacheWriter(RawCache); break;
} }
@ -249,7 +256,7 @@ Done:
return Ret; return Ret;
} }
PVideoFrame __stdcall FFmpegSource::GetFrame(int n, IScriptEnvironment* Env) { PVideoFrame FFmpegSource::GetFrame(int n, IScriptEnvironment* Env) {
bool HasSeeked = false; bool HasSeeked = false;
int ClosestKF = FindClosestKeyFrame(n); int ClosestKF = FindClosestKeyFrame(n);

View file

@ -1,3 +1,28 @@
// Copyright (c) 2007 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFMPEGSOURCE_H
#define FFMPEGSOURCE_H
#define FLAC_CACHE
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
#include <vector> #include <vector>
@ -7,14 +32,18 @@
#include <fcntl.h> #include <fcntl.h>
#include <io.h> #include <io.h>
#ifdef FLAC_CACHE
#include <stream_decoder.h> #include <stream_decoder.h>
#include <stream_encoder.h> #include <stream_encoder.h>
#endif // FLAC_CACHE
extern "C" { extern "C" {
#include <ffmpeg\avformat.h> #include <ffmpeg\avformat.h>
#include <ffmpeg\avcodec.h> #include <ffmpeg\avcodec.h>
#include <ffmpeg\swscale.h> #include <ffmpeg\swscale.h>
#include <postproc\postprocess.h> #include <postproc\postprocess.h>
#include "stdiostream.h"
} }
#include "MatroskaParser.h" #include "MatroskaParser.h"
@ -50,12 +79,15 @@ private:
protected: protected:
VideoInfo VI; VideoInfo VI;
AVFrame *DecodeFrame; AVFrame *DecodeFrame;
FILE *RawAudioCache;
FLAC__StreamDecoder *FLACAudioCache;
AudioCacheFormat AudioCacheType; AudioCacheFormat AudioCacheType;
FILE *RawAudioCache;
#ifdef FLAC_CACHE
FLAC__StreamDecoder *FLACAudioCache;
FLAC__int32 *FLACBuffer;
#endif // FLAC_CACHE
uint8_t *DecodingBuffer; uint8_t *DecodingBuffer;
FLAC__int32 *FLACBuffer;
struct FrameInfo { struct FrameInfo {
int64_t DTS; int64_t DTS;
@ -73,8 +105,10 @@ protected:
bool SaveTimecodesToFile(const char *ATimecodeFile, int64_t ScaleD, int64_t ScaleN); bool SaveTimecodesToFile(const char *ATimecodeFile, int64_t ScaleD, int64_t ScaleN);
bool OpenAudioCache(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env); bool OpenAudioCache(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env);
#ifdef FLAC_CACHE
FLAC__StreamEncoder *FFBase::NewFLACCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, int ACompression, IScriptEnvironment *Env); FLAC__StreamEncoder *FFBase::NewFLACCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, int ACompression, IScriptEnvironment *Env);
void FFBase::CloseFLACCacheWriter(FLAC__StreamEncoder *AFSE); void FFBase::CloseFLACCacheWriter(FLAC__StreamEncoder *AFSE);
#endif // FLAC_CACHE
FILE *FFBase::NewRawCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env); FILE *FFBase::NewRawCacheWriter(const char *AAudioCacheFile, const char *ASource, int AAudioTrack, IScriptEnvironment *Env);
void FFBase::CloseRawCacheWriter(FILE *ARawCache); void FFBase::CloseRawCacheWriter(FILE *ARawCache);
@ -113,3 +147,26 @@ public:
~FFmpegSource(); ~FFmpegSource();
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env); PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env);
}; };
class FFMatroskaSource : public FFBase {
private:
StdIoStream ST;
unsigned int BufferSize;
CompressedStream *VideoCS;
CompressedStream *AudioCS;
AVCodecContext *VideoCodecContext;
MatroskaFile *MF;
char ErrorMessage[256];
uint8_t *Buffer;
int CurrentFrame;
int ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, CompressedStream *ACS, IScriptEnvironment *Env);
int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, IScriptEnvironment* Env);
int GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env);
public:
FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, int AACCompression, const char *APPString, int AQuality, IScriptEnvironment* Env);
~FFMatroskaSource();
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env);
};
#endif

View file

@ -11,9 +11,12 @@ FFmpegSource Documentation
<ul> <ul>
<li>1.11<ul> <li>1.11<ul>
<li>Now officially uses the MIT license</li> <li>Now officially uses the MIT license</li>
<li>Much cleaner source</li>
<li>Can be compiled without support for compressing the audio cache with FLAC</li>
<li>Supports more audio formats in matroska</li> <li>Supports more audio formats in matroska</li>
<li>RGB24 output no longer has swapped colors if the video is converted to it for output</li> <li>RGB24 output no longer has swapped colors if the video is converted to it for output (there still seems to be some bugs lurking when conversion is done with libswscale)</li>
<li>Fixed an access violation on close when no audio is opened (introduced in 1.10)</li> <li>Fixed an access violation on close when no audio is opened (introduced in 1.10)</li>
<li>Updated FFmpeg to rev 10423</li>
</ul></li> </ul></li>
<li>1.10<ul> <li>1.10<ul>
@ -222,7 +225,9 @@ tn:64:128:256
<p><b>FFmpeg svn</b> from http://ffmpeg.mplayerhq.hu/</p> <p><b>FFmpeg svn</b> from http://ffmpeg.mplayerhq.hu/</p>
<p><b>Required Configuration:</b> <p><b>FLAC (optional)</b> from http://flac.sourceforge.net/</p>
<p><b>Required FFmpeg Configuration:</b>
./configure --enable-shared --disable-static --enable-memalign-hack --enable-gpl --enable-swscaler</p> ./configure --enable-shared --disable-static --enable-memalign-hack --enable-gpl --enable-swscaler</p>
<p><b>Suggested Additional Options:</b> <p><b>Suggested Additional Options:</b>

View file

@ -70,7 +70,7 @@ FFPP::~FFPP() {
avpicture_free(&OutputPicture); avpicture_free(&OutputPicture);
} }
PVideoFrame __stdcall FFPP::GetFrame(int n, IScriptEnvironment* Env) { PVideoFrame FFPP::GetFrame(int n, IScriptEnvironment* Env) {
PVideoFrame Src = child->GetFrame(n, Env); PVideoFrame Src = child->GetFrame(n, Env);
PVideoFrame Dst = Env->NewVideoFrame(vi); PVideoFrame Dst = Env->NewVideoFrame(vi);

View file

@ -47,3 +47,58 @@ int GetSWSCPUFlags(IScriptEnvironment *Env) {
return Flags; return Flags;
} }
AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
if (!UserData) {
av_register_all();
UserData = (void *)-1;
}
if (!Args[0].Defined())
Env->ThrowError("FFmpegSource: No source specified");
const char *Source = Args[0].AsString();
int VTrack = Args[1].AsInt(-1);
int ATrack = Args[2].AsInt(-2);
const char *Timecodes = Args[3].AsString("");
bool VCache = Args[4].AsBool(true);
const char *VCacheFile = Args[5].AsString("");
const char *ACacheFile = Args[6].AsString("");
int ACCompression = Args[7].AsInt(-1);
const char *PPString = Args[8].AsString("");
int PPQuality = Args[9].AsInt(PP_QUALITY_MAX);
int SeekMode = Args[10].AsInt(1);
if (VTrack <= -2 && ATrack <= -2)
Env->ThrowError("FFmpegSource: No tracks selected");
#ifdef FLAC_CACHE
if (ACCompression < -1 || ACCompression > 8)
#else
if (ACCompression != -1)
#endif // FLAC_CACHE
Env->ThrowError("FFmpegSource: Invalid audio cache compression selected");
AVFormatContext *FormatContext;
if (av_open_input_file(&FormatContext, Source, NULL, 0, NULL) != 0)
Env->ThrowError("FFmpegSource: Couldn't open %s", Args[0].AsString());
bool IsMatroska = !strcmp(FormatContext->iformat->name, "matroska");
av_close_input_file(FormatContext);
if (IsMatroska)
return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, Env);
else
return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, ACCompression, PPString, PPQuality, SeekMode, Env);
}
AVSValue __cdecl CreateFFPP(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
return new FFPP(Args[0].AsClip(), Args[1].AsString(""), Args[2].AsInt(PP_QUALITY_MAX), Env);
}
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) {
Env->AddFunction("FFmpegSource", "[source]s[vtrack]i[atrack]i[timecodes]s[vcache]b[vcachefile]s[acachefile]s[accompression]i[pp]s[ppquality]i[seekmode]i", CreateFFmpegSource, 0);
Env->AddFunction("FFPP", "c[pp]s[ppquality]i", CreateFFPP, 0);
return "FFmpegSource";
};

View file

@ -1,6 +1,24 @@
#include "stdiostream.h" // Copyright (c) 2007 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define CACHESIZE 65536 #include "stdiostream.h"
/* StdIoStream methods */ /* StdIoStream methods */

View file

@ -1,14 +1,40 @@
// Copyright (c) 2007 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef STDIOSTREAM_H #ifndef STDIOSTREAM_H
#define STDIOSTREAM_H #define STDIOSTREAM_H
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include "MatroskaParser.h" #include "MatroskaParser.h"
#define CACHESIZE 65536
/************\ /************\
* Structures * * Structures *
\************/ \************/
/* first we need to create an I/O object that the parser will use to read the /* first we need to create an I/O object that the parser will use to read the
* source file * source file
*/ */
@ -20,8 +46,6 @@ struct StdIoStream {
typedef struct StdIoStream StdIoStream; typedef struct StdIoStream StdIoStream;
/***********\ /***********\
* Functions * * Functions *
\***********/ \***********/