forked from mia/Aegisub
FFmpegSource 1.5
Originally committed to SVN as r1459.
This commit is contained in:
parent
8d69e930f6
commit
c62c674975
4 changed files with 45 additions and 16 deletions
|
@ -23,7 +23,7 @@ int FFBase::FrameFromDTS(int64_t ADTS) {
|
|||
|
||||
int FFBase::ClosestFrameFromDTS(int64_t ADTS) {
|
||||
int Frame = 0;
|
||||
int64_t BestDiff = 0xFFFFFFFFFFFFFF;
|
||||
int64_t BestDiff = 0xFFFFFFFFFFFFFFLL;
|
||||
for (int i = 0; i < (int)FrameToDTS.size(); i++) {
|
||||
int64_t CurrentDiff = FFABS(FrameToDTS[i].DTS - ADTS);
|
||||
if (CurrentDiff < BestDiff) {
|
||||
|
@ -51,7 +51,8 @@ bool FFBase::LoadFrameInfoFromFile(const char *AVideoCacheFile, const char *ASou
|
|||
if (!CacheFile)
|
||||
return false;
|
||||
|
||||
if (fscanf(CacheFile, "%d\r\n", &VI.num_frames) <= 0) {
|
||||
if (fscanf(CacheFile, "%d\r\n", &VI.num_frames) <= 0 || VI.num_frames <= 0) {
|
||||
VI.num_frames = 0;
|
||||
fclose(CacheFile);
|
||||
return false;
|
||||
}
|
||||
|
@ -106,11 +107,14 @@ bool FFBase::PrepareAudioCache(const char *AAudioCacheFile, const char *ASource,
|
|||
if (!strcmp(AAudioCacheFile, ""))
|
||||
AAudioCacheFile = DefaultCacheFilename;
|
||||
|
||||
bool IsWritable = false;
|
||||
|
||||
AudioCache = fopen(AAudioCacheFile, "rb");
|
||||
if (!AudioCache) {
|
||||
AudioCache = fopen(AAudioCacheFile, "wb+");
|
||||
if (!AudioCache)
|
||||
Env->ThrowError("FFmpegSource: Failed to open the audio cache file for writing");
|
||||
IsWritable = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -121,9 +125,11 @@ bool FFBase::PrepareAudioCache(const char *AAudioCacheFile, const char *ASource,
|
|||
return true;
|
||||
}
|
||||
|
||||
AudioCache = freopen(AAudioCacheFile, "wb", AudioCache);
|
||||
if (!AudioCache)
|
||||
Env->ThrowError("FFmpegSource: Failed to open the audio cache file for writing");
|
||||
if (!IsWritable) {
|
||||
AudioCache = freopen(AAudioCacheFile, "wb+", AudioCache);
|
||||
if (!AudioCache)
|
||||
Env->ThrowError("FFmpegSource: Failed to open the audio cache file for writing");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -149,7 +155,9 @@ void FFBase::InitPP(int AWidth, int AHeight, const char *APPString, int AQuality
|
|||
default:
|
||||
Env->ThrowError("FFmpegSource: Input format is not supported for postprocessing");
|
||||
}
|
||||
|
||||
PPContext = pp_get_context(VI.width, VI.height, Flags);
|
||||
|
||||
if (avpicture_alloc(&PPPicture, APixelFormat, AWidth, AHeight) < 0)
|
||||
Env->ThrowError("FFmpegSource: Failed to allocate picture");
|
||||
}
|
||||
|
@ -236,4 +244,4 @@ FFBase::~FFBase() {
|
|||
pp_free_context(PPContext);
|
||||
avpicture_free(&PPPicture);
|
||||
av_free(DecodeFrame);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,13 @@ public:
|
|||
if (avcodec_open(VideoCodecContext, VideoCodec) < 0)
|
||||
Env->ThrowError("FFmpegSource: Could not open video codec");
|
||||
|
||||
// Fix for mpeg2 and other formats where decoding a frame is necessary to get information about the stream
|
||||
if (VideoCodecContext->pix_fmt == PIX_FMT_NONE) {
|
||||
int64_t Dummy;
|
||||
DecodeNextFrame(DecodeFrame, &Dummy, Env);
|
||||
mkv_Seek(MF, 0, MKVF_SEEK_TO_PREV_KEYFRAME);
|
||||
}
|
||||
|
||||
VI.image_type = VideoInfo::IT_TFF;
|
||||
VI.width = VideoTI->AV.Video.PixelWidth;
|
||||
VI.height = VideoTI->AV.Video.PixelHeight;
|
||||
|
@ -204,7 +211,7 @@ public:
|
|||
|
||||
if (VideoTrack >= 0) {
|
||||
mkv_SetTrackMask(MF, ~(1 << VideoTrack));
|
||||
mkv_Seek(MF, FrameToDTS[0].DTS, MKVF_SEEK_TO_PREV_KEYFRAME);
|
||||
mkv_Seek(MF, FrameToDTS.front().DTS, MKVF_SEEK_TO_PREV_KEYFRAME);
|
||||
|
||||
if (FrameToDTS.size() >= 2) {
|
||||
double DTSDiff = (double)(FrameToDTS.back().DTS - FrameToDTS.front().DTS);
|
||||
|
@ -259,7 +266,7 @@ int FFMatroskaSource::ReadFrame(uint64_t AFilePos, unsigned int AFrameSize, Comp
|
|||
DecompressedFrameSize += ReadBytes;
|
||||
}
|
||||
} else {
|
||||
if (fseek(ST.fp, AFilePos, SEEK_SET))
|
||||
if (_fseeki64(ST.fp, AFilePos, SEEK_SET))
|
||||
Env->ThrowError("FFmpegSource: fseek(): %s", strerror(errno));
|
||||
|
||||
if (BufferSize < AFrameSize) {
|
||||
|
@ -414,7 +421,6 @@ public:
|
|||
VI.height = VideoCodecContext->height;
|
||||
VI.fps_denominator = FormatContext->streams[VideoTrack]->time_base.num;
|
||||
VI.fps_numerator = FormatContext->streams[VideoTrack]->time_base.den;
|
||||
VI.num_frames = (int)FormatContext->streams[VideoTrack]->duration;
|
||||
|
||||
// sanity check framerate
|
||||
if (VI.fps_denominator > VI.fps_numerator || VI.fps_denominator <= 0 || VI.fps_numerator <= 0) {
|
||||
|
@ -457,10 +463,9 @@ public:
|
|||
// Needs to be indexed?
|
||||
if (!ACacheIsValid || !VCacheIsValid) {
|
||||
AVPacket Packet;
|
||||
VI.num_frames = 0;
|
||||
while (av_read_frame(FormatContext, &Packet) >= 0) {
|
||||
if (Packet.stream_index == VideoTrack && !VCacheIsValid) {
|
||||
FrameToDTS.push_back(FrameInfo(Packet.dts, (Packet.flags & PKT_FLAG_KEY) != 0));
|
||||
FrameToDTS.push_back(FrameInfo(Packet.dts, (Packet.flags & PKT_FLAG_KEY) ? 1 : 0));
|
||||
VI.num_frames++;
|
||||
} else if (Packet.stream_index == AudioTrack && !ACacheIsValid) {
|
||||
int Size = Packet.size;
|
||||
|
@ -492,10 +497,15 @@ public:
|
|||
avcodec_close(AudioCodecContext);
|
||||
|
||||
if (VideoTrack >= 0) {
|
||||
av_seek_frame(FormatContext, VideoTrack, FrameToDTS[0].DTS, AVSEEK_FLAG_BACKWARD);
|
||||
av_seek_frame(FormatContext, VideoTrack, FrameToDTS.front().DTS, AVSEEK_FLAG_BACKWARD);
|
||||
|
||||
if (!SaveTimecodesToFile(ATimecodes, FormatContext->streams[VideoTrack]->time_base.num * 1000, FormatContext->streams[VideoTrack]->time_base.den))
|
||||
Env->ThrowError("FFmpegSource: Failed to write timecodes");
|
||||
|
||||
if (FrameToDTS.size() >= 2) {
|
||||
int64_t DTSDiff = (double)(FrameToDTS[1].DTS - FrameToDTS[0].DTS);
|
||||
VI.fps_denominator *= DTSDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -542,7 +552,7 @@ PVideoFrame __stdcall FFmpegSource::GetFrame(int n, IScriptEnvironment* Env) {
|
|||
|
||||
if (SeekMode == 0) {
|
||||
if (n < CurrentFrame) {
|
||||
av_seek_frame(FormatContext, VideoTrack, FrameToDTS[0].DTS, AVSEEK_FLAG_BACKWARD);
|
||||
av_seek_frame(FormatContext, VideoTrack, FrameToDTS.front().DTS, AVSEEK_FLAG_BACKWARD);
|
||||
avcodec_flush_buffers(VideoCodecContext);
|
||||
CurrentFrame = 0;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,19 @@ FFmpegSource Documentation
|
|||
|
||||
<h2>Changes</h2>
|
||||
<ul>
|
||||
<li>1.5<ul>
|
||||
<li>Fixed a bug that made avformat opened files only return audio if only the audio cache needed to be created</li>
|
||||
<li>Rejects more corrupt cache files</li>
|
||||
<li>Fixed crash when a 0 byte audio cache file is present</li>
|
||||
<li>Improved framerate guessing for avformat which now takes takes the duration of the first frame into account</li>
|
||||
<li>Fixed a bug introduced in 1.4 that would make the number of reported frames too high for files opened with avformat</li>
|
||||
<li>Fixed mpeg2 and probably some other formats stored in mkv</li>
|
||||
<li>Fixed issues with large mkv files and large audio cache files</li>
|
||||
<li>FFmpeg is now compiled with liba52 and faad2</li>
|
||||
</ul></li>
|
||||
|
||||
<li>1.4<ul>
|
||||
<li>Uses the average framerate for mkv files</li>
|
||||
<li>Naming scheme of cache files changed to prevent confusion with the default names in files with multiple tracks of the same type</li>
|
||||
<li>Use mmx optimizations in swscaler when possible</li>
|
||||
<li>Now uses normal windows linebreaks in all files</li>
|
||||
|
|
|
@ -17,7 +17,7 @@ typedef struct StdIoStream StdIoStream;
|
|||
*/
|
||||
int StdIoRead(StdIoStream *st, ulonglong pos, void *buffer, int count) {
|
||||
size_t rd;
|
||||
if (fseek(st->fp, pos, SEEK_SET)) {
|
||||
if (_fseeki64(st->fp, pos, SEEK_SET)) {
|
||||
st->error = errno;
|
||||
return -1;
|
||||
}
|
||||
|
@ -39,13 +39,13 @@ longlong StdIoScan(StdIoStream *st, ulonglong start, unsigned signature) {
|
|||
unsigned cmp = 0;
|
||||
FILE *fp = st->fp;
|
||||
|
||||
if (fseek(fp, start, SEEK_SET))
|
||||
if (_fseeki64(fp, start, SEEK_SET))
|
||||
return -1;
|
||||
|
||||
while ((c = getc(fp)) != EOF) {
|
||||
cmp = ((cmp << 8) | c) & 0xffffffff;
|
||||
if (cmp == signature)
|
||||
return ftell(fp) - 4;
|
||||
return _ftelli64(fp) - 4;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
|
Loading…
Reference in a new issue