Je récupère des images vidéo de la caméra via v4l, et j'ai besoin de les transcoder au format mpeg4 pour les diffuser successivement via RTP. Tout fonctionne réellement mais il y a quelque chose que je ne fais pas en recodant: le flux d'entrée produit 15fps, tandis que la sortie est à 25fps, et chaque trame d'entrée est convertie en une seule séquence d'objets vidéo (je l'ai vérifié avec une vérification simple sur le flux de bits de sortie). Je suppose que le récepteur analyse correctement le flux binaire mpeg4 mais la mise en paquets RTP est en quelque sorte fausse. Comment est-ce que je suis supposé diviser le bitstream encodé dans un ou plusieurs AVPacket? Peut-être que je manque l'évidence et j'ai juste besoin de chercher des marqueurs de cadre B/P, mais je pense que je n'utilise pas l'API d'encodage correctement.libavcodec, comment transcoder la vidéo avec différentes fréquences d'images?
Voici un extrait de mon code, qui est basé sur les échantillons de ffmpeg disponibles:
// input frame
AVFrame *picture;
// input frame color-space converted
AVFrame *planar;
// input format context, video4linux2
AVFormatContext *iFmtCtx;
// output codec context, mpeg4
AVCodecContext *oCtx;
// [ init everything ]
// ...
oCtx->time_base.num = 1;
oCtx->time_base.den = 25;
oCtx->gop_size = 10;
oCtx->max_b_frames = 1;
oCtx->bit_rate = 384000;
oCtx->pix_fmt = PIX_FMT_YUV420P;
for(;;)
{
// read frame
rdRes = av_read_frame(iFmtCtx, &pkt);
if (rdRes >= 0 && pkt.size > 0)
{
// decode it
iCdcCtx->reordered_opaque = pkt.pts;
int decodeRes = avcodec_decode_video2(iCdcCtx, picture, &gotPicture, &pkt);
if (decodeRes >= 0 && gotPicture)
{
// scale/convert color space
avpicture_fill((AVPicture *)planar, planarBuf.get(), oCtx->pix_fmt, oCtx->width, oCtx->height);
sws_scale(sws, picture->data, picture->linesize, 0, iCdcCtx->height, planar->data, planar->linesize);
// encode
ByteArray encBuf(65536);
int encSize = avcodec_encode_video(oCtx, encBuf.get(), encBuf.size(), planar);
// this happens every GOP end
while(encSize == 0)
encSize = avcodec_encode_video(oCtx, encBuf.get(), encBuf.size(), 0);
// send the transcoded bitstream with the result PTS
if (encSize > 0)
enqueueFrame(oCtx->coded_frame->pts, encBuf.get(), encSize);
}
}
}