mirror of https://github.com/odrling/Aegisub
FFMS2:
Several bugfixes which should fix crashes in recent versions Added a simple regression test application Removed a few useless functions from the API Add TheFluff's FFmpegSource 1.21 syntax compatibility script Originally committed to SVN as r2843.
This commit is contained in:
parent
45d6e37ee8
commit
83586d2b18
|
@ -112,8 +112,8 @@ int FFAudioSource::DecodeNextAudioBlock(uint8_t *Buf, int64_t *Count, char *Erro
|
||||||
int Ret = -1;
|
int Ret = -1;
|
||||||
*Count = 0;
|
*Count = 0;
|
||||||
AVPacket Packet, TempPacket;
|
AVPacket Packet, TempPacket;
|
||||||
av_init_packet(&Packet);
|
init_null_packet(&Packet);
|
||||||
av_init_packet(&TempPacket);
|
init_null_packet(&TempPacket);
|
||||||
|
|
||||||
while (av_read_frame(FormatContext, &Packet) >= 0) {
|
while (av_read_frame(FormatContext, &Packet) >= 0) {
|
||||||
if (Packet.stream_index == AudioTrack) {
|
if (Packet.stream_index == AudioTrack) {
|
||||||
|
@ -344,7 +344,7 @@ int MatroskaAudioSource::DecodeNextAudioBlock(uint8_t *Buf, int64_t *Count, uint
|
||||||
int Ret = -1;
|
int Ret = -1;
|
||||||
*Count = 0;
|
*Count = 0;
|
||||||
AVPacket TempPacket;
|
AVPacket TempPacket;
|
||||||
av_init_packet(&TempPacket);
|
init_null_packet(&TempPacket);
|
||||||
|
|
||||||
// FIXME check return
|
// FIXME check return
|
||||||
ReadFrame(FilePos, FrameSize, CS, MC, ErrorMsg, MsgSize);
|
ReadFrame(FilePos, FrameSize, CS, MC, ErrorMsg, MsgSize);
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
# FFmpegSource 1.21 syntax compatibility
|
||||||
|
# Created by TheFluff
|
||||||
|
|
||||||
|
function FFmpegSource2(string source, int "vtrack", int "atrack", bool "cache", \
|
||||||
|
string "cachefile", int "fpsnum", int "fpsden", string "pp", int "threads", \
|
||||||
|
string "timecodes", int "seekmode", bool "overwrite") {
|
||||||
|
|
||||||
|
vtrack = default(vtrack,-1)
|
||||||
|
atrack = default(atrack,-2)
|
||||||
|
cache = default(cache,true)
|
||||||
|
cachefile = default(cachefile,source+".ffindex")
|
||||||
|
fpsnum = default(fpsnum,-1)
|
||||||
|
fpsden = default(fpsden,1)
|
||||||
|
pp = default(pp,"")
|
||||||
|
threads = default(threads,-1)
|
||||||
|
timecodes = default(timecodes,"")
|
||||||
|
seekmode = default(seekmode,1)
|
||||||
|
overwrite = default(overwrite,false)
|
||||||
|
|
||||||
|
((cache == true) && (atrack <= -2)) ? ffindex(source=source, cachefile=cachefile, \
|
||||||
|
indexmask=0, overwrite=overwrite) : (cache == true) ? ffindex(source=source, \
|
||||||
|
cachefile=cachefile, indexmask=-1, overwrite=overwrite) : nop
|
||||||
|
|
||||||
|
v = ffvideosource(source=source, track=vtrack, cache=cache, cachefile=cachefile, \
|
||||||
|
fpsnum=fpsnum, fpsden=fpsden, pp=pp, threads=threads, timecodes=timecodes, \
|
||||||
|
seekmode=seekmode)
|
||||||
|
|
||||||
|
a = (atrack <= -2) ? blankclip(audio_rate=0) : ffaudiosource(source=source, \
|
||||||
|
track=atrack, cache=cache, cachefile=cachefile)
|
||||||
|
|
||||||
|
return audiodubex(v,a)
|
||||||
|
}
|
|
@ -234,6 +234,10 @@ Note that --enable-w32threads is required for multithreaded decoding to work.
|
||||||
<h2>Changes</h2>
|
<h2>Changes</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>2.00 beta 7<ul>
|
<li>2.00 beta 7<ul>
|
||||||
|
<li>Fix a crash bug at the end of files with b-frames in beta 6 caused by uninitialized null packets</li>
|
||||||
|
<li>Includes TheFluff's wrapper function for 1.21 style syntax</li>
|
||||||
|
<li>Added a simple regression test application to the source</li>
|
||||||
|
<li>Removed a few pointless functions from the API</li>
|
||||||
<li>Fixed the accessing of codecprivate data with Haali's splitters</li>
|
<li>Fixed the accessing of codecprivate data with Haali's splitters</li>
|
||||||
<li>Timecode output should be fixed to include decimals AND not be in scientific format</li>
|
<li>Timecode output should be fixed to include decimals AND not be in scientific format</li>
|
||||||
<li>Fixed a memory leak when using Haali's splitters</li>
|
<li>Fixed a memory leak when using Haali's splitters</li>
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
// Copyright (c) 2009 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.
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavutil/md5.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include "ffms.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
//#define VERBOSE
|
||||||
|
|
||||||
|
static int FFMS_CC UpdateProgress(int State, int64_t Current, int64_t Total, void *Private) {
|
||||||
|
|
||||||
|
static int LastPercentage = -1;
|
||||||
|
int Percentage = int((double(Current)/double(Total)) * 100);
|
||||||
|
|
||||||
|
if (Percentage <= LastPercentage)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
LastPercentage = Percentage;
|
||||||
|
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "Indexing " << static_cast<char *>(Private) << ", please wait... " << Percentage << "% \r" << flush;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
char ErrorMsg[2000];
|
||||||
|
AVMD5 *ctx = reinterpret_cast<AVMD5 *>(new uint8_t[av_md5_size]);
|
||||||
|
uint8_t md5sum[16];
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
FFMS_Init();
|
||||||
|
#ifndef VERBOSE
|
||||||
|
FFMS_NoLog();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
av_md5_init(ctx);
|
||||||
|
FrameIndex *FI = FFMS_MakeIndex(argv[1], -1, 0, NULL, false, UpdateProgress, argv[1], ErrorMsg, sizeof(ErrorMsg));
|
||||||
|
if (!FI) {
|
||||||
|
cout << "Indexing error: " << ErrorMsg << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int track = FFMS_GetFirstTrackOfType(FI, FFMS_TYPE_VIDEO, ErrorMsg, sizeof(ErrorMsg));
|
||||||
|
if (track < 0) {
|
||||||
|
cout << "No usable track error: " << ErrorMsg << endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoBase *FV = FFMS_CreateVideoSource(argv[1], track, FI, "", 1, 1, ErrorMsg, sizeof(ErrorMsg));
|
||||||
|
FFMS_DestroyFrameIndex(FI);
|
||||||
|
if (!FV) {
|
||||||
|
cout << "Video source error: " << ErrorMsg << endl;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VideoProperties *VP = FFMS_GetVideoProperties(FV);
|
||||||
|
for (int i = 0; i < VP->NumFrames; i++) {
|
||||||
|
const AVFrameLite *AVF = FFMS_GetFrame(FV, i, ErrorMsg, sizeof(ErrorMsg));
|
||||||
|
if (!AVF) {
|
||||||
|
cout << "Frame request error: " << ErrorMsg << " at frame " << i << endl;
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VERBOSE
|
||||||
|
int LastPercentage = -1;
|
||||||
|
int Percentage = int((double(i)/double(VP->NumFrames)) * 100);
|
||||||
|
|
||||||
|
if (Percentage > LastPercentage) {
|
||||||
|
LastPercentage = Percentage;
|
||||||
|
cout << "Requesting frames " << argv[1] << ", please wait... " << Percentage << "% \r" << flush;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t *Data[3];
|
||||||
|
Data[0] = AVF->Data[0];
|
||||||
|
Data[1] = AVF->Data[1];
|
||||||
|
Data[2] = AVF->Data[2];
|
||||||
|
|
||||||
|
switch (VP->VPixelFormat) {
|
||||||
|
case PIX_FMT_YUV420P:
|
||||||
|
case PIX_FMT_YUVJ420P:
|
||||||
|
for (int j = 0; j < VP->Height / 2; j++) {
|
||||||
|
av_md5_update(ctx, Data[0], VP->Width);
|
||||||
|
Data[0] += AVF->Linesize[0];
|
||||||
|
av_md5_update(ctx, Data[0], VP->Width);
|
||||||
|
Data[0] += AVF->Linesize[0];
|
||||||
|
av_md5_update(ctx, Data[1], VP->Width / 2);
|
||||||
|
Data[1] += AVF->Linesize[1];
|
||||||
|
av_md5_update(ctx, Data[2], VP->Width / 2);
|
||||||
|
Data[2] += AVF->Linesize[2];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PIX_FMT_YUV422P:
|
||||||
|
for (int j = 0; j < VP->Height / 2; j++) {
|
||||||
|
av_md5_update(ctx, Data[0], VP->Width);
|
||||||
|
Data[0] += AVF->Linesize[0];
|
||||||
|
av_md5_update(ctx, Data[0], VP->Width);
|
||||||
|
Data[0] += AVF->Linesize[0];
|
||||||
|
av_md5_update(ctx, Data[1], VP->Width / 2);
|
||||||
|
Data[1] += AVF->Linesize[1];
|
||||||
|
av_md5_update(ctx, Data[2], VP->Width / 2);
|
||||||
|
Data[2] += AVF->Linesize[2];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FFMS_DestroyVideoSource(FV);
|
||||||
|
av_md5_final(ctx, md5sum);
|
||||||
|
|
||||||
|
delete[] reinterpret_cast<uint8_t *>(ctx);
|
||||||
|
|
||||||
|
cout << "Test successful, MD5: " << hex;
|
||||||
|
for (int i = 0; i < sizeof(md5sum); i++)
|
||||||
|
cout << static_cast<unsigned>(md5sum[i]);
|
||||||
|
cout << endl;
|
||||||
|
// cin >> argc;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -175,7 +175,7 @@ void FFVideoSource::Free(bool CloseCodec) {
|
||||||
if (CloseCodec)
|
if (CloseCodec)
|
||||||
avcodec_close(CodecContext);
|
avcodec_close(CodecContext);
|
||||||
av_close_input_file(FormatContext);
|
av_close_input_file(FormatContext);
|
||||||
// how was it allocated? how was it deallocate? nobody knows
|
//FIXME how was it allocated? how was it deallocate? nobody knows
|
||||||
//av_free(FormatContext);
|
//av_free(FormatContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ FFVideoSource::~FFVideoSource() {
|
||||||
|
|
||||||
int FFVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AStartTime, char *ErrorMsg, unsigned MsgSize) {
|
int FFVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AStartTime, char *ErrorMsg, unsigned MsgSize) {
|
||||||
AVPacket Packet;
|
AVPacket Packet;
|
||||||
av_init_packet(&Packet);
|
init_null_packet(&Packet);
|
||||||
int FrameFinished = 0;
|
int FrameFinished = 0;
|
||||||
*AStartTime = -1;
|
*AStartTime = -1;
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ int FFVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AStartTime, char *E
|
||||||
// Flush the last frames
|
// Flush the last frames
|
||||||
if (CodecContext->has_b_frames) {
|
if (CodecContext->has_b_frames) {
|
||||||
AVPacket NullPacket;
|
AVPacket NullPacket;
|
||||||
av_init_packet(&NullPacket);
|
init_null_packet(&NullPacket);
|
||||||
avcodec_decode_video2(CodecContext, AFrame, &FrameFinished, &NullPacket);
|
avcodec_decode_video2(CodecContext, AFrame, &FrameFinished, &NullPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,7 +516,7 @@ int MatroskaVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTi
|
||||||
int FrameFinished = 0;
|
int FrameFinished = 0;
|
||||||
*AFirstStartTime = -1;
|
*AFirstStartTime = -1;
|
||||||
AVPacket Packet;
|
AVPacket Packet;
|
||||||
av_init_packet(&Packet);
|
init_null_packet(&Packet);
|
||||||
|
|
||||||
ulonglong StartTime, EndTime, FilePos;
|
ulonglong StartTime, EndTime, FilePos;
|
||||||
unsigned int Track, FrameFlags, FrameSize;
|
unsigned int Track, FrameFlags, FrameSize;
|
||||||
|
@ -543,7 +543,7 @@ int MatroskaVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTi
|
||||||
// Flush the last frames
|
// Flush the last frames
|
||||||
if (CodecContext->has_b_frames) {
|
if (CodecContext->has_b_frames) {
|
||||||
AVPacket NullPacket;
|
AVPacket NullPacket;
|
||||||
av_init_packet(&NullPacket);
|
init_null_packet(&NullPacket);
|
||||||
avcodec_decode_video2(CodecContext, AFrame, &FrameFinished, &NullPacket);
|
avcodec_decode_video2(CodecContext, AFrame, &FrameFinished, &NullPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +773,7 @@ int HaaliVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime,
|
||||||
int FrameFinished = 0;
|
int FrameFinished = 0;
|
||||||
*AFirstStartTime = -1;
|
*AFirstStartTime = -1;
|
||||||
AVPacket Packet;
|
AVPacket Packet;
|
||||||
av_init_packet(&Packet);
|
init_null_packet(&Packet);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
CComPtr<IMMFrame> pMMF;
|
CComPtr<IMMFrame> pMMF;
|
||||||
|
@ -806,7 +806,7 @@ int HaaliVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime,
|
||||||
// Flush the last frames
|
// Flush the last frames
|
||||||
if (CodecContext->has_b_frames) {
|
if (CodecContext->has_b_frames) {
|
||||||
AVPacket NullPacket;
|
AVPacket NullPacket;
|
||||||
av_init_packet(&NullPacket);
|
init_null_packet(&NullPacket);
|
||||||
avcodec_decode_video2(CodecContext, AFrame, &FrameFinished, &NullPacket);
|
avcodec_decode_video2(CodecContext, AFrame, &FrameFinished, &NullPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -324,7 +324,7 @@ static FrameIndex *MakeHaaliIndex(const char *SourceFile, int IndexMask, int Dum
|
||||||
//
|
//
|
||||||
|
|
||||||
AVPacket TempPacket;
|
AVPacket TempPacket;
|
||||||
av_init_packet(&TempPacket);
|
init_null_packet(&TempPacket);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (IP) {
|
if (IP) {
|
||||||
|
@ -481,7 +481,7 @@ static FrameIndex *MakeMatroskaIndex(const char *SourceFile, int IndexMask, int
|
||||||
ulonglong StartTime, EndTime, FilePos;
|
ulonglong StartTime, EndTime, FilePos;
|
||||||
unsigned int Track, FrameFlags, FrameSize;
|
unsigned int Track, FrameFlags, FrameSize;
|
||||||
AVPacket TempPacket;
|
AVPacket TempPacket;
|
||||||
av_init_packet(&TempPacket);
|
init_null_packet(&TempPacket);
|
||||||
|
|
||||||
while (mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0) {
|
while (mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0) {
|
||||||
// Update progress
|
// Update progress
|
||||||
|
@ -621,8 +621,8 @@ FrameIndex *MakeIndex(const char *SourceFile, int IndexMask, int DumpMask, const
|
||||||
FormatContext->streams[i]->codec->codec_type));
|
FormatContext->streams[i]->codec->codec_type));
|
||||||
|
|
||||||
AVPacket Packet, TempPacket;
|
AVPacket Packet, TempPacket;
|
||||||
av_init_packet(&Packet);
|
init_null_packet(&Packet);
|
||||||
av_init_packet(&TempPacket);
|
init_null_packet(&TempPacket);
|
||||||
while (av_read_frame(FormatContext, &Packet) >= 0) {
|
while (av_read_frame(FormatContext, &Packet) >= 0) {
|
||||||
// Update progress
|
// Update progress
|
||||||
if (IP) {
|
if (IP) {
|
||||||
|
|
|
@ -131,6 +131,12 @@ bool AudioFMTIsFloat(SampleFormat FMT){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init_null_packet(AVPacket *pkt) {
|
||||||
|
av_init_packet(pkt);
|
||||||
|
pkt->data = NULL;
|
||||||
|
pkt->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// used for matroska<->ffmpeg codec ID mapping to avoid Win32 dependency
|
// used for matroska<->ffmpeg codec ID mapping to avoid Win32 dependency
|
||||||
typedef struct BITMAPINFOHEADER {
|
typedef struct BITMAPINFOHEADER {
|
||||||
uint32_t biSize;
|
uint32_t biSize;
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
int GetCPUFlags();
|
int GetCPUFlags();
|
||||||
int ReadFrame(uint64_t FilePos, unsigned int &FrameSize, CompressedStream *CS, MatroskaReaderContext &Context, char *ErrorMsg, unsigned MsgSize);
|
int ReadFrame(uint64_t FilePos, unsigned int &FrameSize, CompressedStream *CS, MatroskaReaderContext &Context, char *ErrorMsg, unsigned MsgSize);
|
||||||
bool AudioFMTIsFloat(SampleFormat FMT);
|
bool AudioFMTIsFloat(SampleFormat FMT);
|
||||||
|
void init_null_packet(AVPacket *pkt);
|
||||||
CodecID MatroskaToFFCodecID(char *Codec, void *CodecPrivate);
|
CodecID MatroskaToFFCodecID(char *Codec, void *CodecPrivate);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue