2009-08-06 8 views
29

क्यूटी विजेट में छवियों को प्रदर्शित करने का सबसे तेज़ तरीका क्या है? मैंने libavformat और libavcodec का उपयोग कर वीडियो को डीकोड किया है, इसलिए मेरे पास पहले से ही कच्चे आरजीबी या वाईसीबीसीआर 4: 2: 0 फ्रेम हैं। मैं वर्तमान में एक QGraphicsScene ऑब्जेक्ट के साथ एक QGraphicsSix वस्तु का उपयोग कर रहा हूं जिसमें QGraphicsPixmapItem शामिल है। मैं वर्तमान में एक मेमरी बफर से QImage कन्स्ट्रक्टर का उपयोग करके और QPixmap :: Image() से QPixmap में परिवर्तित करके क्यूपीक्समैप में फ्रेम डेटा प्राप्त कर रहा हूं।क्यूटी में डीकोडेड वीडियो फ्रेम प्रदर्शित करने का सबसे प्रभावी तरीका क्या है?

मुझे इसके परिणाम पसंद हैं और यह अपेक्षाकृत तेज़ लगता है, लेकिन मैं मदद नहीं कर सकता लेकिन सोचता हूं कि एक और अधिक प्रभावी तरीका होना चाहिए। मैंने यह भी सुना है कि QImage QPixmap रूपांतरण के लिए महंगा है। मैंने एक समाधान लागू किया है जो एक विजेट पर एक एसडीएल ओवरले का उपयोग करता है, लेकिन मैं सिर्फ क्यूटी के साथ रहना चाहता हूं क्योंकि मैं QGraphicsView का उपयोग करके वीडियो डिस्प्ले के साथ आसानी से क्लिक और अन्य उपयोगकर्ता इंटरैक्शन को कैप्चर करने में सक्षम हूं।

मैं libswscale के साथ कोई आवश्यक वीडियो स्केलिंग या रंगस्थान रूपांतरण कर रहा हूं, इसलिए मैं यह जानना चाहूंगा कि सभी प्रोसेसिंग के बाद छवि डेटा प्रदर्शित करने का कोई अधिक प्रभावी तरीका है या नहीं।

धन्यवाद।

उत्तर

26

उत्तर के लिए धन्यवाद, लेकिन अंत में मैंने इस समस्या का पुनरीक्षण किया और एक आसान समाधान के साथ आया जो अच्छा प्रदर्शन देता है। इसमें QGLWidget से प्राप्त करना और paintEvent() फ़ंक्शन को ओवरराइड करना शामिल है। paintEvent() फ़ंक्शन के अंदर, आप QPainter::drawImage(...) पर कॉल कर सकते हैं और यह उपलब्ध होने पर हार्डवेयर का उपयोग करके आपके लिए निर्दिष्ट आयताकार को स्केलिंग करेगा। तो यह इस तरह दिखता है:

class QGLCanvas : public QGLWidget 
{ 
public: 
    QGLCanvas(QWidget* parent = NULL); 
    void setImage(const QImage& image); 
protected: 
    void paintEvent(QPaintEvent*); 
private: 
    QImage img; 
}; 

QGLCanvas::QGLCanvas(QWidget* parent) 
    : QGLWidget(parent) 
{ 
} 

void QGLCanvas::setImage(const QImage& image) 
{ 
    img = image; 
} 

void QGLCanvas::paintEvent(QPaintEvent*) 
{ 
    QPainter p(this); 

    //Set the painter to use a smooth scaling algorithm. 
    p.setRenderHint(QPainter::SmoothPixmapTransform, 1); 

    p.drawImage(this->rect(), img); 
} 
इस के साथ

, मैं अभी भी RGB32 को YUV 420P कन्वर्ट करने के लिए है, लेकिन ffmpeg libswscale में है कि रूपांतरण का एक बहुत तेजी से क्रियान्वयन है। प्रमुख लाभ दो चीजों से आते हैं:

  • सॉफ़्टवेयर स्केलिंग की कोई आवश्यकता नहीं है। वीडियो कार्ड (यदि उपलब्ध हो) पर स्केलिंग किया जाता है
  • QImage से QPixmap में रूपांतरण, QPainter::drawImage() फ़ंक्शन में हो रहा है, मूल छवि रिज़ॉल्यूशन पर अपस्केल पूर्णस्क्रीन रिज़ॉल्यूशन के विपरीत किया जाता है।

मैं अपनी पिछली विधि के साथ केवल प्रदर्शन (डीकोडिंग अन्य थ्रेड में किया जा रहा था) पर अपने प्रोसेसर को घुमा रहा था। अब मेरा डिस्प्ले थ्रेड पूर्णस्क्रीन 1920x1200 30fps प्लेबैक के लिए कोर के लगभग 8-9% का उपयोग करता है। मुझे यकीन है कि अगर मैं वाईयूवी डेटा सीधे वीडियो कार्ड पर भेज सकता हूं तो यह शायद बेहतर हो सकता है, लेकिन यह अभी काफी अच्छा है।

+0

मैंने अपने डिकोडर थ्रेड में swscale के साथ yg पैकेट को आरजीबी में परिवर्तित कर दिया और अपनी विधि का उपयोग किया। बेकार चल रहा है। – baci

+0

'पी.सेटरेंडरहिंट (QPainter :: SmoothPixmapTransform, 1);' - setRenderHint लोअरकेस के साथ होना चाहिए। – ottoshmidt

+0

धन्यवाद, @ottoshmidt। फिक्स्ड। –

3

मुझे gtkmm (gtk + C++ wrapping) के साथ एक ही समस्या है। एसडीएल ओवरले का उपयोग करने के अलावा सबसे अच्छा समाधान विजेट के छवि बफर को सीधे अद्यतन करना था, फिर एक रेड्रा के लिए पूछना था। लेकिन मैं अगर यह क्यूटी साथ संभव है पता नहीं है ...

मेरी 2 सेंट

3

अपने ओपन/छायांकन कौशल पर निर्भर करता है आप एक बनावट के लिए वीडियो फ्रेम कॉपी करने के लिए कोशिश कर सकते एक करने के लिए बनावट नक्शा आयताकार (या कुछ और..फन!) और इसे ओपनजीएल दृश्य में प्रदर्शित करें। सबसे सीधा दृष्टिकोण नहीं है, लेकिन तेज़, क्योंकि आप सीधे ग्राफिक्स मेमोरी (जैसे एसडीएल) में लिख रहे हैं। मैं इस प्रारूप को संपीड़ित करने के बाद ही वाईसीबीसीआर का उपयोग करने के लिए पुनः प्राप्त करूंगा (रंग, वाई = पूर्ण सीबी, सीआर फ्रेम के 1/4 हैं) इसलिए फ्रेम कम करने के लिए कम स्मृति + कम प्रतिलिपि की आवश्यकता होती है। मैं क्यूटी जीएल का उपयोग नहीं कर रहा हूं लेकिन अप्रत्यक्ष रूप से क्यूटी (ओएसजी) में जीएल का उपयोग कर रहा हूं और रीयलटाइम में लगभग 7-11 पूर्ण एचडी (1440 x 1080) वीडियो प्रदर्शित कर सकता हूं।

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

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