2012-05-30 13 views
6

Bunu, ffmpeg'deki kodlama örneğinden aldım. Ben biraz ses kodlama için yazarlar örneği takip edebilirsiniz, ama kendimi C kodu incelemeden sersem cok FFMPEG Video Kodlamasını Anlama

static void video_encode_example(const char *filename) 
{ 
AVCodec *codec; 
AVCodecContext *c= NULL; 
int i, out_size, size, x, y, outbuf_size; 
FILE *f; 
AVFrame *picture; 
uint8_t *outbuf, *picture_buf;    //BLOCK ONE 
printf("Video encoding\n"); 

/* find the mpeg1 video encoder */ 
codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); 
if (!codec) { 
    fprintf(stderr, "codec not found\n"); 
    exit(1);        //BLOCK TWO 
} 

c= avcodec_alloc_context(); 
picture= avcodec_alloc_frame(); 
/* put sample parameters */ 
c->bit_rate = 400000; 
/* resolution must be a multiple of two */ 
c->width = 352; 
c->height = 288; 
/* frames per second */ 
c->time_base= (AVRational){1,25}; 
c->gop_size = 10; /* emit one intra frame every ten frames */ 
c->max_b_frames=1; 
c->pix_fmt = PIX_FMT_YUV420P;     //BLOCK THREE 

/* open it */ 
if (avcodec_open(c, codec) < 0) { 
    fprintf(stderr, "could not open codec\n"); 
    exit(1); 
} 
f = fopen(filename, "wb"); 
if (!f) { 
    fprintf(stderr, "could not open %s\n", filename); 
    exit(1); 
}            //BLOCK FOUR 

/* alloc image and output buffer */ 
outbuf_size = 100000; 
outbuf = malloc(outbuf_size); 
size = c->width * c->height; 
picture_buf = malloc((size * 3)/2); /* size for YUV 420 */ 
picture->data[0] = picture_buf; 
picture->data[1] = picture->data[0] + size; 
picture->data[2] = picture->data[1] + size/4; 
picture->linesize[0] = c->width; 
picture->linesize[1] = c->width/2; 
picture->linesize[2] = c->width/2;    //BLOCK FIVE 

/* encode 1 second of video */ 
for(i=0;i<25;i++) { 
    fflush(stdout); 
    /* prepare a dummy image */ 
    /* Y */ 
    for(y=0;y<c->height;y++) { 
     for(x=0;x<c->width;x++) { 
      picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3; 
     } 
    }           //BLOCK SIX 

    /* Cb and Cr */ 
    for(y=0;y<c->height/2;y++) { 
     for(x=0;x<c->width/2;x++) { 
      picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2; 
      picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5; 
     } 
    }           //BLOCK SEVEN 

    /* encode the image */ 
    out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); 
    printf("encoding frame %3d (size=%5d)\n", i, out_size); 
    fwrite(outbuf, 1, out_size, f); 
}            //BLOCK EIGHT 

/* get the delayed frames */ 
for(; out_size; i++) { 
    fflush(stdout); 
    out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); 
    printf("write frame %3d (size=%5d)\n", i, out_size); 
    fwrite(outbuf, 1, out_size, f); 
}            //BLOCK NINE 

/* add sequence end code to have a real mpeg file */ 
outbuf[0] = 0x00; 
outbuf[1] = 0x00; 
outbuf[2] = 0x01; 
outbuf[3] = 0xb7; 
fwrite(outbuf, 1, 4, f); 
fclose(f); 
free(picture_buf); 
free(outbuf); 
avcodec_close(c); 
av_free(c); 
av_free(picture); 
}           //BLOCK TEN 

var ... (Beni, neden bahsettiğimi referans yardımcı blok sayıları yorumladı) Ne Yazar blok kod bloğundan şu şekilde alabilirim ...

BLOK ONE: Değişkenler ve göstergelerin başlatılması. AVFrame yapısını henüz ffmpeg kaynak kodunda bulamadım, bu yüzden referansının ne olduğunu bilmiyorum.

BLOK İKİ: Yakınlarda bulunmadığı takdirde dosyadan bir codec bileşeni kullanır.

BLOK ÜÇ: Örnek video parametrelerini ayarlar. Gerçekten anlamadığım tek şey, gop büyüklüğü. İç çerçeveler hakkında okudum ve hala ne olduklarını anlamıyorum.

BLOK DÖRT: yazma dosyayı açın ...

BLOK BEŞ: onlar gerçekten beni kaybetmekten başlamak burada. Muhtemelen, AVFrame'in ne olduğunu tam olarak bilmediğimden, fakat neden sadece görüntü boyutunun 3/2'sini kullanıyorlar?

BLOK ALTI & YEDI: Bu matematikle neyi başarmaya çalıştıklarını anlamıyorum.

BLOK SEKİZ: Bu avcodec fonksiyonu benziyor süre olduğu için bununla ilgili burada değil tüm çalışmaları, ..

BLOK DOKUZ yapar: o döngü 25 çerçevenin dışında olduğu için bunu tamamını kullanmadığı alır varsayalım çerçeveler?

BLOK TEN: Kapat, ücretsiz Mem, vs ... Bu karıştırılmamalıdır kod büyük bloktur biliyorum

, herhangi bir giriş yararlı olacaktır. Kafamın üzerine işten atıldım. Şimdiden teşekkürler SO.

+0

Bu sabah 6 ve 6 bloklarına bakmak için çok zaman harcadım Matematik çok boyutlu dizide yapıldığında, ve ben de işten çıkarken dün olduğu gibi sıkışıp kaldım :( – SetSlapShot

+0

Altı ve yedi blokla gizemli olan ne?/* bir kukla resim hazırla/'size ihtiyacınız olan tüm bilgileri vermeli.Tüm bunlar çerçeve indeksi ile değişebilen bir gradyan olarak sonuçlanacak bazı piksel verilerini üretiyor – HonkyTonk

+0

Çok geniş kapatabilme Oylama Soru başına bir noktaya odaklanın. –

cevap

3

HonkyTonk zaten yanıtladığı gibi, yorumlar hecelemekte: kukla bir görüntü hazırlamak. Sanırım, özellikle YUV/YCbCr colorspace'ına aşina değilseniz, tam olarak hakkında kukla görüntünün nasıl üretildiğini tahmin edebilirsiniz. Read the Wikipedia treatment for the basics.

YUV renk uzayında birçok video codec bileşeni çalışır. Bu genellikle sadece RGB ile uğraşmak için kullanılan programcılar için kafa karıştırıcıdır. Yönetici özeti, bu varyasyon için (YUV 4: 2: 0 düzlemsel), görüntüdeki her pikselin Y örneğini almasıdır (Y düğmesinin her (x, y) çifti üzerinde yinelemediğini unutmayın), her biri 2x2 piksel dörtlüdür Bir U/Cb örneğini ve bir V/Cr örneğini paylaşın (blok 7'de, yinelemenin genişlik/2 ve yükseklik/2'nin üzerinde olduğunu not edin).

Oluşan modelin bir tür degrade olduğu anlaşılıyor. Bilinen bir değişiklik üretmek istiyorsanız, Y/Cb/Cr değerini 0 olarak ayarlayın ve kukla görüntünün tümü yeşil olacaktır. Cb ve Cr'yi 128'e ayarlayın ve Y'yi 255'e ayarlayın ve beyaz bir çerçeve alın; siyah görmek için Y'yi 0'a kaydırın; gri tonlarını görmek için Y'de Cb ve Cr tuşlarını basılı tutarken, herhangi bir değere Y'yi ayarlayın.

4

Anlayışımı paylaşıyorum [Sessiz geç cevap!]

YUV420P:

YUV 420P ya da YCbCr RGB repersetation alternatif olan ve 3

uçak, yani Y'nin (luma bileşeni), U (E-Cb) & V (Y = Cr içeren) bileşenler. [Ans-Y-Cb-Cr-Cs =

sabit genellikle hesaplanabilir, biz, CS bileşeni depolamak için gerek yoktur.] sadece 3 bayt piksel gerektirir RGB888 gibi, YUV420 1.5 bayt gerektirir bir piksel [@Find (How

12 bit, hangi oranda hangi bileşen için kullanılır)] Burada Progressive için P -standları, yani çerçeve ilerleyici, yani V, U, U, Y ve YUV Frame'in izlendiği anlamına gelir sadece bir bayt dizisidir! Bir diğeri, serpiştirmek için olan I-standlarıdır, UV düzlemsel verileri, belirli bir şekilde Y düzlemi verileri arasında aralıklarla ayırma anlamına gelir [@Find (Hangi yöntem)]