📄 edit.cpp
字号:
void DoubleWeaveFrames::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->num_frames *= 2;
pvi->fps_numerator *= 2;
}
DoubleWeaveFrames::~DoubleWeaveFrames() { if (frame) delete[] frame; }
/********************************************************************
********************************************************************/
SelectEvery::SelectEvery(int _every, int _from, PVideoFilter _child) : GenericVideoFilter(_child), every(_every), from(_from) {}
void SelectEvery::GetFrame(int n, unsigned char* buf) { child->GetFrame(n*every+from, buf); }
bool SelectEvery::GetParity(int n) { return child->GetParity(n*every+from); }
void SelectEvery::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->fps_denominator *= every;
pvi->num_frames = (pvi->num_frames-1-from) / every + 1;
}
/********************************************************************
********************************************************************/
FreezeFrame::FreezeFrame(int _first, int _last, int _source, PVideoFilter _child)
: GenericVideoFilter(_child), first(_first), last(_last), source(_source) {}
void FreezeFrame::GetFrame(int n, unsigned char* buf) {
child->GetFrame((n >= first && n <= last) ? source : n, buf);
}
bool FreezeFrame::GetParity(int n) {
return child->GetParity((n >= first && n <= last) ? source : n);
}
/********************************************************************
********************************************************************/
DeleteFrame::DeleteFrame(int _frame, PVideoFilter _child) : GenericVideoFilter(_child), frame(_frame) {}
void DeleteFrame::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
--pvi->num_frames;
}
void DeleteFrame::GetFrame(int n, unsigned char* buf) { child->GetFrame(n + (n>=frame), buf); }
bool DeleteFrame::GetParity(int n) { return child->GetParity(n + (n>=frame)); }
/********************************************************************
********************************************************************/
DuplicateFrame::DuplicateFrame(int _frame, PVideoFilter _child) : GenericVideoFilter(_child), frame(_frame) {}
void DuplicateFrame::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
++pvi->num_frames;
}
void DuplicateFrame::GetFrame(int n, unsigned char* buf) { child->GetFrame(n - (n>frame), buf); }
bool DuplicateFrame::GetParity(int n) { return child->GetParity(n - (n>frame)); }
/********************************************************************
********************************************************************/
Trim::Trim(int _firstframe, int _lastframe, PVideoFilter _child) : GenericVideoFilter(_child) {
if (_lastframe == 0) _lastframe = vi.num_frames-1;
firstframe = min(max(_firstframe, 0), vi.num_frames-1);
lastframe = min(max(_lastframe, firstframe), vi.num_frames-1);
audio_offset = vi.AudioSamplesFromFrames(firstframe);
}
void Trim::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->num_frames = lastframe+1 - firstframe;
pvi->num_audio_samples = vi.AudioSamplesFromFrames(lastframe+1) - audio_offset;
}
void Trim::GetFrame(int n, unsigned char* buf) { child->GetFrame(n+firstframe, buf); }
void Trim::GetAudio(void* buf, int start, int count) { child->GetAudio(buf, start+audio_offset, count); }
bool Trim::GetParity(int n) { return child->GetParity(n+firstframe); }
/********************************************************************
********************************************************************/
Splice::Splice(bool realign_sound, PVideoFilter _child1, PVideoFilter _child2) : child1(_child1), child2(_child2) {
child1->GetVideoInfo(&vi1);
child2->GetVideoInfo(&vi2);
if (vi1.width != vi2.width || vi1.height != vi2.height)
throw FilterChainError("Splice: frame sizes don't match");
if (vi1.HasVideo() && vi2.HasVideo() && vi1.pixel_type != vi2.pixel_type)
throw FilterChainError("Splice: video formats don't match");
if (vi1.HasAudio() && vi2.HasAudio() && (vi1.stereo != vi2.stereo || vi1.sixteen_bit != vi2.sixteen_bit))
throw FilterChainError("Splice: sound formats don't match");
if (realign_sound)
audio_switchover_point = vi1.AudioSamplesFromFrames(vi1.num_frames);
else
audio_switchover_point = vi1.num_audio_samples;
}
void Splice::GetFrame(int n, unsigned char* buf) {
if (n < vi1.num_frames)
child1->GetFrame(n, buf);
else
child2->GetFrame(n - vi1.num_frames, buf);
}
void Splice::GetAudio(void* buf, int start, int count) {
VideoInfo& viSound = vi1.HasAudio() ? vi1 : vi2;
int samples = viSound.AudioSamplesFromBytes(count);
if (start+samples <= audio_switchover_point)
child1->GetAudio(buf, start, count);
else if (start >= audio_switchover_point)
child2->GetAudio(buf, start - audio_switchover_point, count);
else {
int count1 = viSound.BytesFromAudioSamples(audio_switchover_point - start);
child1->GetAudio(buf, start, count1);
child2->GetAudio((char*)buf+count1, 0, count-count1);
}
}
void Splice::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi1;
pvi->num_frames += vi2.num_frames;
pvi->num_audio_samples = audio_switchover_point + vi2.num_audio_samples;
}
bool Splice::GetParity(int n) {
return (n < vi1.num_frames) ? child1->GetParity(n) : child2->GetParity(n - vi1.num_frames);
}
/********************************************************************
********************************************************************/
Dissolve::Dissolve(int _overlap, PVideoFilter _child1, PVideoFilter _child2)
: overlap(_overlap), child1(_child1), child2(_child2), vidbuffer(0), audbuffer(0), audbufsize(0)
{
child1->GetVideoInfo(&vi1);
child2->GetVideoInfo(&vi2);
if (vi1.width != vi2.width || vi1.height != vi2.height)
throw FilterChainError("Dissolve: frame sizes don't match");
if (vi1.HasVideo() && vi2.HasVideo() && vi1.pixel_type != vi2.pixel_type)
throw FilterChainError("Dissolve: video formats don't match");
if (vi1.HasAudio() && vi2.HasAudio() && (vi1.stereo != vi2.stereo || vi1.sixteen_bit != vi2.sixteen_bit))
throw FilterChainError("Dissolve: sound formats don't match");
audio_fade_end = vi1.AudioSamplesFromFrames(vi1.num_frames)-1;
audio_fade_start = vi1.AudioSamplesFromFrames(vi1.num_frames - overlap);
}
void Dissolve::GetFrame(int n, unsigned char* buf) {
if (n < vi1.num_frames - overlap) {
child1->GetFrame(n, buf);
return;
}
if (n >= vi1.num_frames) {
child2->GetFrame(n - vi1.num_frames + overlap, buf);
return;
}
if (!vidbuffer)
vidbuffer = new unsigned char[vi1.ImageSize()];
child1->GetFrame(n, buf);
child2->GetFrame(n - vi1.num_frames + overlap, vidbuffer);
int multiplier = max(0, vi1.num_frames-n);
for (int z=0; z<vi1.ImageSize(); ++z)
buf[z] = vidbuffer[z] + ((buf[z]-vidbuffer[z]) * multiplier + (overlap>>1)) / (overlap+1);
}
void Dissolve::GetAudio(void* buf, int start, int count) {
if (start+vi1.AudioSamplesFromBytes(count) <= audio_fade_start)
child1->GetAudio(buf, start, count);
else if (start > audio_fade_end)
child2->GetAudio(buf, start - audio_fade_start, count);
else {
if (audbufsize < count) {
if (audbuffer) delete[] audbuffer;
audbuffer = new unsigned char[count];
audbufsize = count;
}
child1->GetAudio(buf, start, count);
child2->GetAudio(audbuffer, start - audio_fade_start, count);
int denominator = (audio_fade_end - audio_fade_start);
int numerator = (audio_fade_end - start);
if (vi1.sixteen_bit) {
short *a = (short*)buf, *b = (short*)audbuffer;
count >>= 1;
for (int i=0; i<count; ++i) {
if (numerator <= 0)
a[i] = b[i];
else if (numerator < denominator)
a[i] = b[i] + MulDiv(a[i]-b[i], numerator, denominator);
numerator -= ((i&1) | !vi1.stereo);
}
} else {
unsigned char *a = (unsigned char*)buf, *b = (unsigned char*)audbuffer;
for (int i=0; i<count; ++i) {
if (numerator <= 0)
a[i] = b[i];
else if (numerator < denominator)
a[i] = b[i] + MulDiv(a[i]-b[i], numerator, denominator);
numerator -= ((i&1) | !vi1.stereo);
}
}
}
}
void Dissolve::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi1;
pvi->num_frames += vi2.num_frames - overlap;
pvi->num_audio_samples = audio_fade_start + vi2.num_audio_samples;
}
bool Dissolve::GetParity(int n) {
return (n < vi1.num_frames) ? child1->GetParity(n) : child2->GetParity(n - vi1.num_frames + overlap);
}
/********************************************************************
********************************************************************/
AudioDub::AudioDub(PVideoFilter child1, PVideoFilter child2) {
VideoInfo vi1, vi2;
child1->GetVideoInfo(&vi1);
child2->GetVideoInfo(&vi2);
if (vi1.HasVideo() && vi2.HasAudio()) {
vchild = child1; achild = child2;
} else if (vi2.HasVideo() && vi1.HasAudio()) {
vchild = child2; achild = child1;
} else {
throw FilterChainError("AudioDub: need an audio and a video track");
}
}
void AudioDub::GetVideoInfo(VideoInfo* pvi) {
vchild->GetVideoInfo(pvi);
VideoInfo via;
achild->GetVideoInfo(&via);
pvi->audio_samples_per_second = via.audio_samples_per_second;
pvi->num_audio_samples = via.num_audio_samples;
pvi->sixteen_bit = via.sixteen_bit;
pvi->stereo = via.stereo;
}
void AudioDub::GetFrame(int n, unsigned char* buf) { vchild->GetFrame(n, buf); }
bool AudioDub::GetParity(int n) { return vchild->GetParity(n); }
void AudioDub::GetAudio(void* buf, int start, int count) { achild->GetAudio(buf, start, count); }
/********************************************************************
********************************************************************/
DelayAudio::DelayAudio(float delay, PVideoFilter _child)
: GenericVideoFilter(_child), delay_samples(int(delay * vi.audio_samples_per_second + 0.5)) {}
void DelayAudio::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->num_audio_samples += delay_samples;
}
void DelayAudio::GetAudio(void* buf, int start, int count) {
child->GetAudio(buf, start-delay_samples, count);
}
/********************************************************************
********************************************************************/
Reverse::Reverse(PVideoFilter _child) : GenericVideoFilter(_child) {}
void Reverse::GetFrame(int n, unsigned char* buf) {
child->GetFrame(vi.num_frames-n-1, buf);
}
bool Reverse::GetParity(int n) { return child->GetParity(vi.num_frames-n-1); }
void Reverse::GetAudio(void* buf, int start, int count) {
int count_samples = vi.AudioSamplesFromBytes(count);
child->GetAudio(buf, vi.num_audio_samples-start-count_samples, count);
int xor = vi.BytesFromAudioSamples(1) - 1;
char* buf2 = (char*)buf;
for (int i=0; i<(count>>1); ++i) {
char temp = buf2[i]; buf2[i] = buf2[count-1-(i^xor)]; buf2[count-1-(i^xor)] = temp;
}
}
/********************************************************************
********************************************************************/
PVideoFilter __cdecl Create_DoubleWeave(const FilterInfo*, const Arg* args, const char*) {
PVideoFilter clip = args[0].clip;
VideoInfo vi; clip->GetVideoInfo(&vi);
if (vi.field_based)
return new DoubleWeaveFields(clip);
else
return new DoubleWeaveFrames(clip);
}
PVideoFilter __cdecl Create_Weave(const FilterInfo* self, const Arg* args, const char* arg_types) {
return new SelectEvery(2, 0, Create_DoubleWeave(self, args, arg_types));
}
PVideoFilter __cdecl Create_Pulldown(const FilterInfo* self, const Arg* args, const char* arg_types) {
PVideoFilter clip = args[2].clip;
PVideoFilter* child_array = new PVideoFilter[2];
child_array[0] = new SelectEvery(5, args[0].integer % 5, clip);
child_array[1] = new SelectEvery(5, args[0].integer % 5, clip);
return new AssumeFrameBased(new Interleave(2, child_array));
}
PVideoFilter __cdecl Create_SwapFields(const FilterInfo*, const Arg* args, const char*) {
return new SelectEvery(2, 0, new DoubleWeaveFields(new ComplementParity(new SeparateFields(args[0].clip))));
}
PVideoFilter __cdecl Create_FadeOut(const FilterInfo*, const Arg* args, const char*) {
int duration = args[0].integer;
PVideoFilter a = args[1].clip;
PVideoFilter b = new_Blackness(a, duration+1);
return new Dissolve(duration, a, b);
}
PVideoFilter __cdecl Create_FadeOut2(const FilterInfo*, const Arg* args, const char*) {
int duration = args[0].integer;
PVideoFilter a = args[1].clip;
PVideoFilter b = new_Blackness(a, duration+2);
return new Dissolve(duration, a, b);
}
FilterInfo edit_filters[] = {
{ "ComplementParity", "c", ComplementParity::Create },
{ "AssumeFieldBased", "c", AssumeFieldBased::Create },
{ "AssumeFrameBased", "c", AssumeFrameBased::Create },
{ "SeparateFields", "c", SeparateFields::Create },
{ "Weave", "c", Create_Weave },
{ "DoubleWeave", "c", Create_DoubleWeave },
{ "Pulldown", "iic", Create_Pulldown },
{ "SelectEvery", "i+c", SelectEvery::Create },
{ "SelectEven", "c", SelectEvery::Create_SelectEven },
{ "SelectOdd", "c", SelectEvery::Create_SelectOdd },
{ "Interleave", "cc+", Interleave::Create },
{ "Trim", "iic", Trim::Create },
{ "FreezeFrame", "iiic", FreezeFrame::Create },
{ "DeleteFrame", "ic", DeleteFrame::Create },
{ "DuplicateFrame", "ic", DuplicateFrame::Create },
{ "UnalignedSplice", "cc+", Splice::CreateUnaligned },
{ "AlignedSplice", "cc+", Splice::CreateAligned },
{ "Dissolve", "icc+", Dissolve::Create },
{ "AudioDub", "cc", AudioDub::Create },
{ "DelayAudio", "fc", DelayAudio::Create },
{ "Reverse", "c", Reverse::Create },
{ "SwapFields", "c", Create_SwapFields },
{ "FadeOut", "ic", Create_FadeOut },
{ "FadeOut2", "ic", Create_FadeOut2 },
{ 0,0,0 }
};
PVideoFilter new_Splice(bool realign_sound, PVideoFilter _child1, PVideoFilter _child2) {
return new Splice(realign_sound, _child1, _child2);
}
PVideoFilter new_SeparateFields(PVideoFilter _child) {
return new SeparateFields(_child);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -