streaming H.264 sur RTP avec libavformat

J'ai essayé au cours de la dernière semaine pour mettre en œuvre H. 264 streaming sur RTP, à l'aide de x264 comme un encodeur et démultiplexeur d'emballer et d'envoyer le flux de données. Problème est, autant que je peux dire c'est ne fonctionne pas correctement.

Droit maintenant, je suis juste l'encodage des données aléatoires (x264_picture_alloc) et l'extraction NALE des images à partir de libx264. C'est assez simple:

x264_picture_t pic_out;
x264_nal_t* nals;
int num_nals;
int frame_size = x264_encoder_encode(this->encoder, &nals, &num_nals, this->pic_in, &pic_out);

if (frame_size <= 0)
{
    return frame_size;
}

//push NALs into the queue
for (int i = 0; i < num_nals; i++)
{
    //create a NAL storage unit
    NAL nal;
    nal.size = nals[i].i_payload;
    nal.payload = new uint8_t[nal.size];
    memcpy(nal.payload, nals[i].p_payload, nal.size);

    //push the storage into the NAL queue
    {
        //lock and push the NAL to the queue
        boost::mutex::scoped_lock lock(this->nal_lock);
        this->nal_queue.push(nal);
    }
}

nal_queue est utilisé pour transporter en toute sécurité en passant images sur le Serpentin de la classe qui sera ensuite envoyer les images. Pour l'instant il n'est pas fileté, que je suis juste tester pour essayer d'obtenir que cela fonctionne. Avant l'encodage des images individuelles, j'ai fait en sorte d'initialiser le codeur.

Mais je ne crois pas que le x264 est la question, que je puisse voir les données d'image dans les Nales il retourne.
Streaming les données est réalisé avec démultiplexeur, qui est d'abord initialisé dans un Streamer de la classe:

Streamer::Streamer(Encoder* encoder, string rtp_address, int rtp_port, int width, int height, int fps, int bitrate)
{
    this->encoder = encoder;

    //initalize the AV context
    this->ctx = avformat_alloc_context();
    if (!this->ctx)
    {
        throw runtime_error("Couldn't initalize AVFormat output context");
    }

    //get the output format
    this->fmt = av_guess_format("rtp", NULL, NULL);
    if (!this->fmt)
    {
        throw runtime_error("Unsuitable output format");
    }
    this->ctx->oformat = this->fmt;

    //try to open the RTP stream
    snprintf(this->ctx->filename, sizeof(this->ctx->filename), "rtp://%s:%d", rtp_address.c_str(), rtp_port);
    if (url_fopen(&(this->ctx->pb), this->ctx->filename, URL_WRONLY) < 0)
    {
        throw runtime_error("Couldn't open RTP output stream");
    }

    //add an H.264 stream
    this->stream = av_new_stream(this->ctx, 1);
    if (!this->stream)
    {
        throw runtime_error("Couldn't allocate H.264 stream");
    }

    //initalize codec
    AVCodecContext* c = this->stream->codec;
    c->codec_id = CODEC_ID_H264;
    c->codec_type = AVMEDIA_TYPE_VIDEO;
    c->bit_rate = bitrate;
    c->width = width;
    c->height = height;
    c->time_base.den = fps;
    c->time_base.num = 1;

    //write the header
    av_write_header(this->ctx);
}

C'est là que les choses semblent aller de mal. av_write_header ci-dessus ne semble faire rien-absolument rien; j'ai utilisé wireshark pour vérifier cela. Pour référence, j'utilise Streamer streamer(&enc, "10.89.6.3", 49990, 800, 600, 30, 40000); pour initialiser le Streamer exemple, avec enc être une référence à un Encoder objet utilisé pour traiter x264 précédemment.

Maintenant, quand je veux écouter une NALE, j'utilise ceci:

//grab a NAL
NAL nal = this->encoder->nal_pop();
cout << "NAL popped with size " << nal.size << endl;

//initalize a packet
AVPacket p;
av_init_packet(&p);
p.data = nal.payload;
p.size = nal.size;
p.stream_index = this->stream->index;

//send it out
av_write_frame(this->ctx, &p);

À ce point, je peux voir RTP de données figurant sur le réseau, et il semble que les images que j'ai envoyé, il y a même peu de droit d'auteur blob de x264. Maispas de joueur que j'ai utilisé a été en mesure de donner un sens aux données. VLC quitte à vouloir un SDP description, qui apparemment, il n'est pas nécessaire.

J'ai ensuite essayé de le lire à gst-launch:

gst-launch udpsrc port=49990 ! rtph264depay ! decodebin ! xvimagesink

Ce sera assis en attente de données UDP, mais quand il est reçu, j'obtiens:

ERREUR: élément /GstPipeline:pipeline0/GstRtpH264Depay:rtph264depay0: Pas de RTP
le format a été négocié. Supplémentaire les informations de débogage:
gstbasertpdepayload.c(372): gst_base_rtp_depayload_chain ():
/GstPipeline:pipeline0/GstRtpH264Depay:rtph264depay0: tampons d'Entrée
besoin d'avoir RTP casquettes. C'est en général atteint par la mise en
les "bouchons" la propriété de la source amont de l'élément (souvent udpsrc ou
appsrc), ou en mettant un capsfilter élément avant de le depayloader et
réglage de la 'caps' bien sur que. Voir aussi
http://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/gst/rtp/README

Que je ne suis pas en utilisant GStreamer pour diffuser lui-même, je ne suis pas tout à fait sûr de ce que cela signifie avec RTP casquettes. Mais, il me fait me demander si je ne suis pas envoyer assez d'informations sur RTP pour décrire le flux de données. Je suis assez nouveau à la vidéo et je me sens comme il ya quelque chose qui me manque ici. Un indice?

source d'informationauteur Jacob Peddicord