2016-03-30 20 views
1

FFmpeg libav'u kullanarak doğru bir H264 videosu kodlamada sorun yaşıyorum. Kodlanmış videoyu VLC media player'da çalamıyordum ve videoyu MPC-HC üzerinde oynatabilsem de bu süre 00:00/00:00'u gösteriyor. Açıkçası bir şey özlüyorum.H264 Kodlama - VLC Player'ı kullanarak video oynatılamadı

MPC-HC Medya bilgileri bunu gösterir:

Genel
Biçimi: AVC
Biçim/Bilgi: Advanced Video Codec
Dosya boyutu: 110 KiB
Süre: 2s 400ms
Genel bit hızı: 375 Kbps
Yazı kütüphanesi: x264 çekirdek 148 r2665 a01e339
Kodlama ayarları: cabac = 0/ref = 3/deblock = 1: 0: 0/analyze = 0x1: 0x111/me = hex/subme = 7/psy = 1/psy_rd = 1,00: 0,00/mixed_ref = 1/me_range = 16/chroma_me = 1/trellis = 1/8x8dct = 0/cqm = 0/deadzone = 21,11/fast_pskip = 1/chroma_qp_offset = -2/thread = 7/lookahead_threads = 1/dilimlenmiş_dosyalar = 0/nr = 0/decimate = 1/interlaced = 0/bluray_compat = 0/constrained_intra = 0/bframes = 0/weightp = 0/keyint = 12/keyint_min = 1/scenecut = 40/intra_refresh = 0/rc_lookahead = 12/rc = abr/mbtree = 1/bit hızı = 2000/ratetol = 1.0/qcomp = 0.60/qpmin = 0/qpmax = 69/qpstep = 4/ip_ratio = 1.40/aq = 1: 1.00

video
Biçimi: AVC
Biçim/Bilgi: Gelişmiş Görüntü Kodlaması
Biçim profili: [email protected]
Biçim ayarları, CABAC: Resim
Biçim ayarları, ReFrames: 3 kare
Biçim ayarları, GOP: M = 1, n = 12
Süre: 2s 400ms
bit hızı: 2 000 Kbps
genişliği: 320 piksel
Yükseklik: 240 piksel
Boy oranı: 4: 3
Çerçeve hızı modu: Değişken
Kare hızı: 20,833 fps
Renkli alanı: YUV
Renk alt örneklemesi: 4: 2: 0
bit derinliği: 8 bit
Tarama türü: Aşamalı
Bit/(Piksel * Kare): 1.250
Akış boyutu: 586 KiB
yazma kütüphanesi : x264 çekirdek 148 r2665 a01e339
Kodlama ayarları: cabac = 0/ref = 3/deblock = 1: 0: 0/analyze = 0x1: 0x111/me = hex/subme = 7/psy = 1/psy_rd = 1.00: 0.00/mixed_ref = 1/me_range = 16/chroma_me = 1/trellis = 1/8x8dct = 0/cqm = 0/deadzone = 21,11/fast_pskip = 1/chroma_qp_offset = -2/konu = 7/lookahead_threads = 1/diled_threads = 0/nr = 0/decimate = 1/interlaced = 0/bluray _compat = 0/constrained_intra = 0/bframes = 0/weightp = 0/keyint = 12/keyint_min = 1/scenecut = 40/intra_refresh = 0/rc_lookahead = 12/rc = abr/mbtree = 1/bit hızı = 2000/ratetol = 1.0/qcomp = 0.60/qpmin = 0/qpmax = 69/qpstep = 4/ip_ratio = 1.40/aq = 1: 1.

00 Yukarıda bilgi garip bir şey fark: - Kare hızı yerine belirtilen 10 fps, 20.833 fps. - Video, 4 saniyeden daha uzun bir süredir oynatıldığı için 2s 400ms'un sürmesi doğru görünmedi.

Ayrıca, (AVFrame* picture)->pict_type her zaman AV_PICTURE_TYPE_NONE olarak ayarlanır. Bunun normal olduğunu düşünmüyorum.

Kullandığım kitaplık ffmpeg-20160219-git-98a0053-win32-dev'dur. Bu karışıklıktan bana yardım ederseniz gerçekten çok memnun olurum.

/* 
* Video encoding example 
*/ 
char filename[] = "test.mp4"; 
int main(int argc, char** argv) 
{ 
    AVCodec *codec = NULL; 
    AVCodecContext *codecCtx= NULL; 
    AVFormatContext *pFormatCtx = NULL; 
    AVStream * pVideoStream = NULL; 
    AVFrame *picture = NULL; 

    int i, x, y,   // 
     ret,    // Return value 
     got_packet_ptr;  // Data encoded into packet 

    printf("Video encoding\n"); 

    // Register all formats and codecs 
    av_register_all(); 

    // allocate context 
    pFormatCtx = avformat_alloc_context(); 
    memcpy(pFormatCtx->filename,filename, 
     min(strlen(filename), sizeof(pFormatCtx->filename))); 

    // guess format 
    pFormatCtx->oformat = av_guess_format("h264", NULL, NULL); 
    if (NULL==pFormatCtx->oformat) 
    { 
     cerr << "Could not guess output format" << endl; 
     return -1; 
    } 

    // Find the codec. 
    codec = avcodec_find_encoder(pFormatCtx->oformat->video_codec); 
    if (codec == NULL) { 
     fprintf(stderr, "Codec not found\n"); 
     return -1; 
    } 

    // Set context 
    int framerate = 10; 
    codecCtx = avcodec_alloc_context3(codec); 
    avcodec_get_context_defaults3(codecCtx, codec); 
    codecCtx->pix_fmt = AV_PIX_FMT_YUV420P; 
    codecCtx->profile = FF_PROFILE_H264_BASELINE; 
    // Resolution must be a multiple of two. 
    codecCtx->width = 320; 
    codecCtx->height = 240; 

    codecCtx->bit_rate = 2000000; 
    codecCtx->time_base.den = framerate; 
    codecCtx->time_base.num = 1; 
    codecCtx->gop_size = 12; // emit one intra frame every twelve frames at most 

    // Open the codec. 
    if (avcodec_open2(codecCtx, codec, NULL) < 0) 
    { 
     printf("Cannot open video codec\n"); 
     return -1; 
    } 

    // Add stream to pFormatCtx 
    pVideoStream = avformat_new_stream(pFormatCtx, codec); 
    if (!pVideoStream) 
    { 
     printf("Cannot add new video stream\n"); 
     return -1; 
    } 
    pVideoStream->codec = codecCtx; 
    pVideoStream->time_base.den = framerate; 
    pVideoStream->time_base.num = 1; 

    if (avio_open2(&pFormatCtx->pb, filename, AVIO_FLAG_WRITE, NULL, NULL) < 0) 
    { 
     printf("Cannot open file\n"); 
     return -1; 
    } 

    // Write file header. 
    avformat_write_header(pFormatCtx, NULL); 

    // Create frame 
    picture= av_frame_alloc(); 
    picture->format = codecCtx->pix_fmt; 
    picture->width = codecCtx->width; 
    picture->height = codecCtx->height; 

    int bufferImgSize = av_image_get_buffer_size(codecCtx->pix_fmt, codecCtx->width, 
        codecCtx->height,1);  
    av_image_alloc(picture->data, picture->linesize, codecCtx->width, codecCtx->height,     codecCtx->pix_fmt, 32); 

    AVPacket avpkt; 

    /* encode 1 second of video */ 
    for(i=0;i<50;i++) 
    { 
     /* prepare a dummy image */ 
     /* Y */ 
     for(y=0;y<codecCtx->height;y++) 
     { 
      for(x=0;x<codecCtx->width;x++) 
      { 
       picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3; 
      } 
     } 
     /* Cb and Cr */ 
     for(y=0;y<codecCtx->height/2;y++) 
     { 
      for(x=0;x<codecCtx->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; 
      } 
     } 

     // Get timestamp 
     picture->pts = (float) i * (1000.0/(float)(codecCtx->time_base.den)) * 90; 

     // Encode frame to packet 
     av_init_packet(&avpkt); 
     got_packet_ptr = 0; 
     int error = avcodec_encode_video2(codecCtx, &avpkt, picture, &got_packet_ptr); 
     if (!error && got_packet_ptr > 0) 
     { 
      // Write packet with frame. 
      ret = (av_interleaved_write_frame(pFormatCtx, &avpkt) == 0);   
     } 
     av_packet_unref(&avpkt); 
    } 

    // Flush remaining encoded data 
    while(1) 
    { 
     av_init_packet(&avpkt); 
     got_packet_ptr = 0; 
     // Encode frame to packet. 
     int error = avcodec_encode_video2(codecCtx, &avpkt, NULL, &got_packet_ptr); 
     if (!error && got_packet_ptr > 0) 
     { 
      // Write packet with frame. 
      ret = (av_interleaved_write_frame(pFormatCtx, &avpkt) == 0);   
     } 
     else 
     { 
      break; 
     } 
     av_packet_unref(&avpkt); 
    } 
    av_write_trailer(pFormatCtx); 

    av_packet_unref(&avpkt); 
    av_frame_free(&picture); 

    avcodec_close(codecCtx); 
    av_free(codecCtx); 

    cin.get(); 
} 

cevap

0

Libav postalama listesinden bir cevap aldınız (teşekkürler Gonzalo) ve cevabımı burada paylaşmak istiyorum.

Ben biçimi berbat çünkü av_guess_format("h264", NULL, NULL) setleri aşağıdaki içine pFormatCtx->oformat:

pFormatCtx-> oformat.name 0x009df614 "h264"
pFormatCtx-> oformat.long_name 0x009df619 "ham H.264 video"
pFormatCtx-> oformat.mime_type 0x00000000
pFormatCtx-> oformat.extensions 0x009df629 "h264,264"
pFormatCtx-> AV_CODEC_ID_NONE oformat.audio_codec
pFormatCtx-> oformat.video_c odec AV_CODEC_ID_H264
pFormatCtx-> AV_CODEC_ID_NONE
pFormatCtx-> 128
pFormatCtx-> oformat.flags 0x00000000
pFormatCtx-> oformat.codec_tag 0x00000000 oformat.priv_class oformat.subtitle_codec {class_name = ??? item_name = ??? seçenek = ??? ...}
pFormatCtx-> 0x009980c0 {name = 0x009bb03e "HDS" oformat.next long_name = 0x009bb042 "HDS Muxer" MIME_TYPE = 0x00000000 ...}
pFormatCtx-> oformat.priv_data_size 0
pFormatCtx-> oformat.

: write_header 0x005bad70
pFormatCtx-> oformat.write_packet 0x005bac40
pFormatCtx-> 0x00000000

oformat.write_trailer daha doğru çağrı aşağıdaki içine setleri av_guess_format(NULL, filename, NULL) olurdu

pFormatCtx-> 0x009ce84c "MP4"
pFormatCtx-> oformat.long_name 0x009ce850 "MP4 (MPEG-4 bölüm 14)"
pFormatCtx-> oformat.mime_type 0x009ce689 "Video/MP4"
pFormatCtx-> oformat.name oformat.extensions 0x009ce84c "mp4"
pFormatCtx-> AV_CODEC_ID_NONE
pFormatCtx-> oformat.subtitle_codec 327.744
pFormatCtx-> oformat oformat.flags AV_CODEC_ID_H264
pFormatCtx-> oformat.video_codec AV_CODEC_ID_AAC
pFormatCtx-> oformat.audio_codec. codec_tag 0x009ce868
pFormatCtx-> oformat.priv_class 0x009ce880 {class_name = 0x009ce870 "mp4 muxer" öğe_adı = 0x0062bc70 option = 0x009cf300 ...}
pFormatCtx-> oformat.next 0x0099ae00 {name = 0x009d104c "mpeg" long_name = 0x009d1054 "MPEG-1 Sistemler/MPEG program akışı" mime_type = 0x0056a7f0

oformat.write_trailer 0x0056ad20
pFormatCtx-> oformat.write_packet 0x0056a260
pFormatCtx-> oformat.write_header 176
pFormatCtx-> oformat.priv_data_size 0x009d0ec8 "video/mpeg" ...}
pFormatCtx->

Bunu söylediğimde,kullanırsam hayat çok daha kolay olabilir, avformat_alloc_context() ve av_guess_format() ile ihtiyacım olanı gerçekleştirir.