2014-04-23 6 views
0

J'essaye d'écrire un programme qui utilise libx264 pour coder les images vidéo. J'ai enveloppé ce code dans une petite classe (voir ci-dessous). J'ai des cadres qui sont au format YUV420. libx264 encode les cadres et je les sauvegarde dans un fichier. Je peux lire le fichier dans VLC, tous les cadres sont là, mais il est lu à plusieurs centaines de fois la fréquence d'image réelle. Actuellement, je capture des images à 2,5 FPS, mais elles sont lues comme si elles avaient été enregistrées à 250 images/seconde ou plus. J'ai essayé de changer le taux de trame sans aucune chance.La lecture de l'encodeur libx264 est trop rapide

J'ai aussi essayé de mettre

_param.b_vfr_input = 1 

puis définissez les bases de temps appropriée, mais qui cause mon programme de tomber en panne. Des idées? Mon code d'encodage est montré ci-dessous. J'ai également inclus la sortie de ffprobe -show_frames

Wrapper Classe:

x264wrapper::x264wrapper(int width, int height, int fps, int timeBaseNum, int timeBaseDen, int vfr) 
{ 
    x264_param_default_preset(&_param, "veryfast", "zerolatency"); 
    _param.i_threads = 1; 
    _param.i_width = width; 
    _param.i_height = height; 
    _param.i_fps_num = fps; 
    _param.i_fps_den = 1; 
    // Intra refres: 
    _param.i_keyint_max = fps; 
    _param.b_intra_refresh = 1; 
    //Rate control: 
    _param.rc.i_rc_method = X264_RC_CRF; 
    //_param.rc.i_rc_method = X264_RC_CQP; 
    _param.rc.f_rf_constant = 25; 
    _param.rc.f_rf_constant_max = 35; 
    //For streaming: 
    _param.b_repeat_headers = 1; 
    _param.b_annexb = 1;  
    // misc 
    _param.b_vfr_input = vfr; 
    _param.i_timebase_num = timeBaseNum; 
    _param.i_timebase_den = timeBaseDen; 

    _param.i_log_level = X264_LOG_DEBUG; 

    _encoder = x264_encoder_open(&_param); 

    cout << "Timebase " << _param.i_timebase_num << "/" << _param.i_timebase_den << endl; 
    cout << "fps " << _param.i_fps_num << "/" << _param.i_fps_den << endl; 
    _ticks_per_frame = (int64_t)_param.i_timebase_den * _param.i_fps_den/_param.i_timebase_num/_param.i_fps_num; 
    cout << "ticks_per_frame " << _ticks_per_frame << endl; 
    int result = x264_picture_alloc(&_pic_in, X264_CSP_I420, width, height); 
    if (result != 0) 
    { 
     cout << "Failed to allocate picture" << endl; 
     throw(1); 
    } 

    _ofs = new ofstream("output.h264", ofstream::out | ofstream::binary); 
    _pts = 0; 
} 


x264wrapper::~x264wrapper(void) 
{ 
    _ofs->close(); 
} 



void x264wrapper::encode(uint8_t * buf) 
{ 
    x264_nal_t* nals; 
    int i_nals; 
    convertFromBalserToX264(buf); 
    _pts += _ticks_per_frame; 
    _pic_in.i_pts = _pts; 
    x264_picture_t pic_out; 
    int frame_size = x264_encoder_encode(_encoder, &nals, &i_nals, &_pic_in, &pic_out); 
    if (frame_size >= 0) 
    { 
     _ofs->write((char*)nals[0].p_payload, frame_size); 
    } 
    else 
    { 
     cout << "error: x264_encoder_encode failed" << endl; 
    } 
} 

Sortie de ffprobe -show_frames:

[FRAME] 
media_type=video 
key_frame=1 
pkt_pts=N/A 
pkt_pts_time=N/A 
pkt_dts=N/A 
pkt_dts_time=N/A 
pkt_duration=48000 
pkt_duration_time=0.040000 
pkt_pos=0 
width=1920 
height=1080 
pix_fmt=yuv420p 
sample_aspect_ratio=N/A 
pict_type=I 
coded_picture_number=0 
display_picture_number=0 
interlaced_frame=0 
top_field_first=0 
repeat_pict=0 
reference=0 
[/FRAME] 
[FRAME] 
media_type=video 
key_frame=0 
pkt_pts=N/A 
pkt_pts_time=N/A 
pkt_dts=N/A 
pkt_dts_time=N/A 
pkt_duration=N/A 
pkt_duration_time=N/A 
pkt_pos=54947 
width=1920 
height=1080 
pix_fmt=yuv420p 
sample_aspect_ratio=N/A 
pict_type=P 
coded_picture_number=1 
display_picture_number=0 
interlaced_frame=0 
top_field_first=0 
repeat_pict=0 
reference=0 
[/FRAME] 
[FRAME] 
media_type=video 
key_frame=0 
pkt_pts=N/A 
pkt_pts_time=N/A 
pkt_dts=N/A 
pkt_dts_time=N/A 
pkt_duration=N/A 
pkt_duration_time=N/A 
pkt_pos=57899 
width=1920 
height=1080 
pix_fmt=yuv420p 
sample_aspect_ratio=N/A 
pict_type=P 
coded_picture_number=2 
display_picture_number=0 
interlaced_frame=0 
top_field_first=0 
repeat_pict=0 
reference=0 
[/FRAME] 

Répondre

1

Comme je vous comprends flux de l'annexe B brute sortie c.-à-vous don 't mux dans un conteneur comme mkv/mp4. Comme je l'ai déjà répondu here les flux bruts de l'annexe B n'ont pas d'informations de synchronisation à l'intérieur d'autres valeurs dans l'en-tête (VUI) qui peut être utilisé pour déterminer la fréquence d'images constante mais ne fonctionnerait pas en jouant à la vitesse de la base de temps et pas de vrais fps). Si vous avez des problèmes avec le taux de trame constant (param.b_vfr_input = 0), assurez-vous également que vous utilisez un bon décodeur/lecteur parce que VLC passé a des problèmes avec les flux bruts de l'annexe B (doubler la fréquence mais pas accélérer cent fois). Vous pouvez également essayer de fusionner votre flux avec MKVToolnix et regarder quel fps il détectera.

Questions connexes