के साथ स्ट्रीमिंग एच 264 आरटीपी पर स्ट्रीमिंग को लागू करने के लिए पिछले सप्ताह में कोशिश कर रहा है, x264 का उपयोग एन्कोडर के रूप में और libavformat को पैक करने और स्ट्रीम भेजने के लिए कर रहा है। समस्या यह है कि, जहां तक मैं कह सकता हूं कि यह सही तरीके से काम नहीं कर रहा है।स्ट्रीमिंग एच .264 आरटीपी पर libavformat
अभी मैं यादृच्छिक डेटा (x264_picture_alloc) एन्कोड कर रहा हूं और libx264 से एनएएल फ्रेम निकालने जा रहा हूं। यह काफी सरल है:
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
सुरक्षित रूप से एक प्रकाश की किरण वर्ग जो तब फ्रेम बाहर भेज देंगे करने के लिए फ्रेम के ऊपर से गुजर के लिए प्रयोग किया जाता है। अभी यह थ्रेड नहीं है, क्योंकि मैं इसे काम करने के लिए बस कोशिश करने के लिए परीक्षण कर रहा हूं। व्यक्तिगत फ्रेम एन्कोड करने से पहले, मैंने एन्कोडर को प्रारंभ करना सुनिश्चित कर लिया है।
लेकिन मुझे विश्वास नहीं है कि x264 समस्या है, क्योंकि मैं वापस एनएएल में फ्रेम डेटा देख सकता हूं। जहां कोई बात बिगड़ जाए लगते
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);
}
यह वह जगह है: डेटा स्ट्रीमिंग libavformat, जो पहले एक प्रकाश की किरण कक्षा में आरंभ नहीं हो जाता के साथ पूरा किया है। av_write_header
उपरोक्त कुछ भी नहीं करता है; मैंने इसे सत्यापित करने के लिए वायरशर्क का उपयोग किया है। संदर्भ के लिए, मैं enc
Encoder
ऑब्जेक्ट का संदर्भ होने के साथ पहले x264 को संभालने के लिए उपयोग किए जाने वाले स्ट्रीमर इंस्टेंस को प्रारंभ करने के लिए Streamer streamer(&enc, "10.89.6.3", 49990, 800, 600, 30, 40000);
का उपयोग करता हूं।
अब जब मैं एक एनएएल बाहर स्ट्रीम करने के लिए चाहते हैं, मैं इस का उपयोग करें:
// 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);
इस बिंदु पर, मैं आरटीपी डेटा नेटवर्क पर प्रदर्शित होने के देख सकते हैं, और यह फ्रेम मैं भेज दिया गया है की तरह लग रहा , x264 से थोड़ा कॉपीराइट ब्लॉब भी शामिल है। लेकिन, मेरे द्वारा उपयोग किए जाने वाले कोई भी खिलाड़ी डेटा की कोई समझ नहीं कर पाए हैं। वीएलसी एक एसडीपी विवरण चाहते हैं, जो apparently isn't required है।
मैं तो gst-launch
के माध्यम से इसे खेलने की कोशिश की:
gst-launch udpsrc port=49990 ! rtph264depay ! decodebin ! xvimagesink
यह यूडीपी डेटा के लिए इंतज़ार कर बैठेंगे, लेकिन जब यह प्राप्त होता है, मैं:
ERROR: element /GstPipeline:pipeline0/GstRtpH264Depay:rtph264depay0: No RTP format was negotiated. Additional debug info: gstbasertpdepayload.c(372): gst_base_rtp_depayload_chain(): /GstPipeline:pipeline0/GstRtpH264Depay:rtph264depay0: Input buffers need to have RTP caps set on them. This is usually achieved by setting the 'caps' property of the upstream source element (often udpsrc or appsrc), or by putting a capsfilter element before the depayloader and setting the 'caps' property on that. Also see http://cgit.freedesktop.org/gstreamer/gst-plugins-good/tree/gst/rtp/README
मैं के रूप में खुद को स्ट्रीम करने के लिए जीस्ट्रीमर का उपयोग नहीं करते, मुझे पूरा यकीन नहीं है कि आरटीपी कैप्स के साथ इसका क्या अर्थ है। लेकिन, यह मुझे आश्चर्यचकित करता है कि क्या मैं स्ट्रीम का वर्णन करने के लिए आरटीपी पर पर्याप्त जानकारी नहीं भेज रहा हूं। मैं वीडियो के लिए काफी नया हूं और मुझे लगता है कि यहां कुछ महत्वपूर्ण चीज है जो मैं यहां लापता हूं। कोई संकेत?
यह बात है - मुझे नहीं पता, और मुझे जो जानकारी चाहिए उसे ढूंढने में मुझे परेशानी हो रही है। जो मैं बता सकता हूं, libavformat चीजों को आपके लिए आरटीपी स्ट्रीम में पैक करेगा (और अमान्य पैकेट नहीं भेजेगा - मैंने कोशिश की है)। यह कोई आरटीएसपी वार्ता नहीं करता है; आखिरकार ग्राहकों को आरटीएसपी स्ट्रीमिंग को संभालने के लिए फेंग या कुछ अन्य बाहरी अनुप्रयोगों पर ध्यान दिया जाएगा। हालांकि, यह स्पष्ट नहीं करता है कि क्यों कुछ भी आरटीपी धारा के सिर या पूंछ नहीं बना सकता है जो libavformat उत्पन्न कर रहा है। –
आपको इसे किसी भी तरह से बातचीत करने की आवश्यकता है। अपनी स्ट्रीम के लिए एसडीपी फ़ाइल बनाने का प्रयास क्यों न करें? –
मैंने इसे जाने दिया और मैं एक हरे रंग की स्क्रीन प्रदर्शित करने के लिए वीएलसी प्राप्त कर सकता हूं - चाहे वह सही है या नहीं, मुझे नहीं पता, लेकिन यह एक शुरुआत है। आज इस पर काम कर रहे होंगे, इसलिए हम देखेंगे कि यह वास्तव में मुद्दा था या नहीं। –