İçeriğe atla

Avidemux/Kendi filtrenizi yazma

Vikikitap, özgür kütüphane

Bu sayfada kendi filtrenizi nasıl yazacağınız anlatılmaktadır.

Kurulum & araçlar

[değiştir]

Öncelikle Avidemux'un kaynak koduna ihtiyacınız var (eğer eklentileri derlemişseniz Avidemux'un kendisini derlemenize gerek yok demektir, ancak halen Avidemux'un kaynak koduna ihtiyacınız var).

Windows için MinGW GCC/g++ (v4.x) veya cygwin GCC/g++ (v4.x) gerekiyor. Bazı C++ bağlantıları olacağı için MSVC çalışmayacaktır. Ayrıca MSVC C++, g++ ile uyumsuzdur.

Her şey birer sınıftır

[değiştir]

Avidemux'taki bütün filtreler AVDMGenericVideoStream sınıfından türetilmiştir. Yalnızca birkaç metodun tanımlanması gerekir:

Yapıcı metot

[değiştir]

Yapıcı metot 2 argüman alır:

  1. Zincirdeki bir önceki filtre, bu filtre "_in"in içine kopyalanacaktır.
  2. CONFcouple * yapılandırmayı içerenleri eşleştirir. Bu eğer "null"sa varsayalın değerinizi kullanmanız gerektiği anlamına gelir.

Yapıcı metodun çıktı formatının açıklamasını içeren _info özelliğini güncellemesi gerekir. Eğer fps veya genişlik/yüksekliği değiştirmiyorsanız _in->getInfo() kodunu kullanarak bir önceki filtreninkini kopyalayabilirsiniz.

Sınıfınızın, parametrelerinizi tanımlayan bir yapı olan _param ismine sahip bir özelliği olmalıdır. Örneğin:

typedef struct rotateParam
 {
   uint32_t angle;
 }rotateParam;

CONFcouple'dan parametre almak için yapıcı metotta kullanışlı *GET* ön ekini kullanabilirsiniz. Örnek: GET(angle);

printConf

[değiştir]

Bir sonraki metot printConf'tur, filtre diyalog kutusundaki yapılandırmayı yazdırmak için kullanılır.

char *yourClassName::printConf (void)
{
  static char buf[[50]];
  sprintf ((char *) buf, " My rotate filter, angle :%d",_param->angle);
  return buf;
}

Kafa karıştırıcı olabilecek tahsis etme/boşaltmadan kaçınmak için buffer statiktir.

GetCouple

[değiştir]

Bu metot aktif yapılandırmayı almak için kullanılır. En basit yol aşağıdaki gibi CSET ön ekini kullanmaktır:

uint8_t sinifIsminiz::getCoupledConf (CONFcouple ** couples)
{
  ADM_assert (_param);
  *couples = new CONFcouple (1); // Yapınızdaki parametre sayısı
  #undef CSET
  #define CSET(x)  (*couples)->setCouple(#x,(_param->x))
  CSET (angle);
  return 1;
}

getCoupledConf ve yapıcı metot birer çifttir. Bunların aynı parametre sayısına ve aynı parametre adlarına sahip olmaları gerekir. Aksi takdirde "asserts popping" yaşarsınız.

Configure

[değiştir]
uint8_t yourClassName::configure (AVDMGenericVideoStream * in)

Bu metot filtreyi yapılandırmak için kullanılır. Parametresi yapıcı metotla aynıdır. Ancak bununla "_in"i güncellemek daha güvenlidir. Hem GTK+ ve hem de Windows (Qt) ile çalıştığından ve kullanması oldukça kolay olduğundan dialogFactory'yi kullanmanız şiddetle tavsiye edilir.

Bazı bilgiler:

  • 0 döndürmesi hiçbir şey değişmediği anlamına gelir.
  • 1 döndürmesi bazı değişikliklerin yapıldığı ve filtre zincirinin yeniden inşa edilmesi gerekebileceği anlamına gelir.

Önemli: Yapılandırmadaki değişiklik hemen yapılmalıdır!

getFrameNoAlloc

[değiştir]

İş burada yapıldığı için bu metot merkezi metottur.

uint8_t sinifIsminiz::getFrameNumberNoAlloc (uint32_t inframe,
                              uint32_t * len,
                              ADMImage * data, uint32_t * flags)

len çıktı resminin bayt olarak boyutudur. flags ihmal edilebilir. inframe renderlemek zorunda olduğunuz frame'dir. data frame renderlemek zorunda olduğunuz zamandaki yerdir.

Filtreler bir zincirdir, bu durumda her bir filtre selefinden frame isteyebilir. Birçok durumda yapıcı metotta geçici bir tampon tahsis etmek isteyecek (bu genellikle _uncompressed olarak isimlendirilir) ve önceki filtrenin sizin için doldurmasını isteyeceksiniz. Örneğin verticalFlip aşağıdaki gibi kolaylaştırılabilir:

uint8_t sinifIsminiz::getFrameNumberNoAlloc (uint32_t inframe,
                              uint32_t * len,
                              ADMImage * data, uint32_t * flags)
{
  ADM_assert(inframe<_info.nb_frames); // Sınırlardan çıkmadığımıza emin olun
  // Önceki için frame'leri okuma
  ADM_assert(_in->getFrameNumberNoAlloc(inframe,len,_uncompressed,flags)); // Şimdi _uncompressed frame'i içeriyor
  // _uncompressed'den son resmi tutan veriye çevirme
  Return 1; // bitti
}

Bazı notlar:

  • Bütün resimler YV12 formatındadır.
  • Eğer birkaç resmi bir resim halinde render etmek için (3:2 pulldown, noise removal,...), VideoCache sınıfı türünden bir nesne oluşturmalısınız.

Filtreyi tanımlama

[değiştir]

Filtrenizi tanımlamanın 2 yolu vardır: paketli veya eklenti. Her ikisini aynı anda, aynı dosyada kullanabilirsiniz.

Paketli filtre

[değiştir]

Bu birazcık daha karmaşıktır. Bunun için şunları yapmak zorundasınız:

  • ADM_filter/video_filters.h dosyasındaki filtreniz için bir etiket tanımlayın.
  • Aşağıdaki kodu kullanarak ADM_filter/filter_declaration.cpp dosyasındaki filtrenizi kaydettirin.
REGISTERX("rotate","Rotate","Rotate the picture by 90, 180 or 270 degrees.",VF_ROTATE,1,rotate_create,rotate_script);

İlk parametre dahili isimdir (tek olmalı). İkinci ve üçüncü parametreler a,d özetini göstermek için kullanılırlar. Dördüncü parametre yukarıda tanımladığınız etikettir. VAR OLAN BİR ETİKETİ YENİDEN KULLANMAYIN. Büyük sorunlarla karşılaşacaksınız, bana inanın. Son iki parametre aşağıdaki tanımlanan fonksiyonunkiyle aynı olmalıdır.

Şimdi filtre C++ dosyamıza geri gidelim. Öncelikle aşağıdaki gibi gözüken bir sabit tanımlamalısınız

static FILTER_PARAM filtreniz_param =  { 1,"angle"};

İlk parametre param yapınızdaki parametre sayısı, ikinci parametre ise ilgili parametrelerin adıdır, kesinlikle yapınızdaki gibi olmalıdır. Sonra aşağıdaki iki makroyu kullanın:

BUILD_CREATE (rotate_create, sinifIsminiz);
SCRIPT_CREATE (rotate_script, sinifIsminiz, filreniz_param);

Bu iki makronun ilk parametrelerinin REGISTERX'te kullandıklarınızla eşleştiğinden emin olun.

Bu kadar :-).

Eklenti

[değiştir]

Bu daha kolaydır. Halen aşağıdaki gibi gözüken sabiti tanımlamak zorundasınız:

static FILTER_PARAM filtreniz_param =  { 1,"angle"};

Sonra

extern "C"
{
  SCRIPT_CREATE(FILTER_create_fromscript,sinifIsminiz,filtreniz_param);
  BUILD_CREATE(FILTER_create,sinifIsminiz);
  char *FILTER_getName(void)
  {
    return "DynRotate";  // Filtrenizin ismi. Tek olmalı!
  }
  char *FILTER_getDesc(void)
  {
    return "Blah blah"; // Filtrenizin kısa tanımı
  }
  uint32_t FILTER_getVersion(void)
  {
    return 1;  // Filtrenizin versiyonu
  }
  uint32_t FILTER_getAPIVersion(void)
  {
    return ADM_FILTER_API_VERSION; 
  }
}

Bu kod, bütün gerekli şeyleri halledecektir, sadece bir eklenti yazdığımızı düşünürsek ADM_filter/xxx klasöründe herhangi bir şeyi değiştirmek zorunda değilsiniz. Her iki tanımı aynı dosyada yapabilirsiniz, böylece filtre Avidemux'un içine paketlenecek veya eklenti filtresi olarak derlenecektir.

Son sözcükler

[değiştir]

En basit yöntem ADM_filter/ADM_vidDummyFilter.cpp dosyasından başlamaktır. Bu, çok basit bir filtredir, bunu aşağıdaki kod ile inşa edebilirsiniz

sh builddummy.sh (Unix'te)

veya

sh builddummy_win32.sh (Windows'ta) (gcc'niz için yolu/adları değiştirmeniz gerekebilir).

Avisynth'le ana farklar şunlardır:

  • Resim formatı her zaman YV12 olmalıdır.
  • stride=width
  • Frame'i döndürmezsiniz, bu size argüman olarak çağırıcı tarafından verilmiştir.