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:
Fredrik Mellbin 2009-04-24 17:42:21 +00:00
parent 4777905b0a
commit b8cf6fce8e
8 changed files with 203 additions and 14 deletions

View File

@ -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);

View File

@ -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)
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
} }

View File

@ -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) {

View File

@ -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;

View File

@ -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