2012-04-13 17 views
10

के साथ स्ट्रीमिंग एच 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 उपरोक्त कुछ भी नहीं करता है; मैंने इसे सत्यापित करने के लिए वायरशर्क का उपयोग किया है। संदर्भ के लिए, मैं encEncoder ऑब्जेक्ट का संदर्भ होने के साथ पहले 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

मैं के रूप में खुद को स्ट्रीम करने के लिए जीस्ट्रीमर का उपयोग नहीं करते, मुझे पूरा यकीन नहीं है कि आरटीपी कैप्स के साथ इसका क्या अर्थ है। लेकिन, यह मुझे आश्चर्यचकित करता है कि क्या मैं स्ट्रीम का वर्णन करने के लिए आरटीपी पर पर्याप्त जानकारी नहीं भेज रहा हूं। मैं वीडियो के लिए काफी नया हूं और मुझे लगता है कि यहां कुछ महत्वपूर्ण चीज है जो मैं यहां लापता हूं। कोई संकेत?

उत्तर

4

एच 264 एक एन्कोडिंग मानक है। यह निर्दिष्ट करता है कि कैसे वीडियो डेटा संकुचित और प्रारूप में संग्रहीत किया जाता है जिसे बाद में बिंदु पर वीडियो स्ट्रीम में डिकंप्रेस किया जा सकता है।

आरटीपी एक संचरण प्रोटोकॉल है। यह पैकेट के प्रारूप और क्रम को निर्दिष्ट करता है जो द्वारा मनमाने ढंग से एन्कोडर द्वारा एन्कोड किए गए ऑडियो-वीडियो डेटा को ले जा सकता है।

जीस्ट्रीमर डेटा प्राप्त करने की अपेक्षा करता है जो आरटीपी प्रोकोटोल के अनुरूप है। क्या आपकी उम्मीद है कि libaformat जीटी स्ट्रीमर द्वारा तुरंत पढ़ने योग्य आरटीपी पैकेट का उत्पादन करेगा? हो सकता है कि जीस्ट्रीमर्स एक अतिरिक्त स्ट्रीम विवरण की अपेक्षा करें जो उचित डिकोडर का उपयोग करके स्ट्रीम किए गए पैकेट को स्वीकार और डीकोड कर सके? शायद इसके लिए एक अतिरिक्त आरटीएसपी एक्सचेंज या एसडीपी स्ट्रीम डिस्क्रिप्टर फ़ाइल की आवश्यकता है?

त्रुटि संदेश स्पष्ट रूप से बताता है कि एक आरटीपी प्रारूप पर बातचीत नहीं की गई है। caps क्षमताओं के लिए कम हाथ हैं। रिसीवर को रिसीवर/डिकोडिंग मशीनरी को सही तरीके से स्थापित करने के लिए ट्रांसमीटर की क्षमताओं को जानना आवश्यक है।

मैं दृढ़ता से सुझाव देता हूं कि कम से कम अपने आरटीपी स्ट्रीम के लिए एक एसडीपी फ़ाइल बनाने का प्रयास करें। libavformat should be able to do it for you

+0

यह बात है - मुझे नहीं पता, और मुझे जो जानकारी चाहिए उसे ढूंढने में मुझे परेशानी हो रही है। जो मैं बता सकता हूं, libavformat चीजों को आपके लिए आरटीपी स्ट्रीम में पैक करेगा (और अमान्य पैकेट नहीं भेजेगा - मैंने कोशिश की है)। यह कोई आरटीएसपी वार्ता नहीं करता है; आखिरकार ग्राहकों को आरटीएसपी स्ट्रीमिंग को संभालने के लिए फेंग या कुछ अन्य बाहरी अनुप्रयोगों पर ध्यान दिया जाएगा। हालांकि, यह स्पष्ट नहीं करता है कि क्यों कुछ भी आरटीपी धारा के सिर या पूंछ नहीं बना सकता है जो libavformat उत्पन्न कर रहा है। –

+0

आपको इसे किसी भी तरह से बातचीत करने की आवश्यकता है। अपनी स्ट्रीम के लिए एसडीपी फ़ाइल बनाने का प्रयास क्यों न करें? –

+0

मैंने इसे जाने दिया और मैं एक हरे रंग की स्क्रीन प्रदर्शित करने के लिए वीएलसी प्राप्त कर सकता हूं - चाहे वह सही है या नहीं, मुझे नहीं पता, लेकिन यह एक शुरुआत है। आज इस पर काम कर रहे होंगे, इसलिए हम देखेंगे कि यह वास्तव में मुद्दा था या नहीं। –

संबंधित मुद्दे