2009-07-09 16 views
11

में वाईयूवी डिस्प्ले के साथ मदद की ज़रूरत है मुझे कच्ची वाईयूवी फ़ाइल प्रदर्शित करने में परेशानी हो रही है जो कि यह एनवी 12 प्रारूप में है।ओपनजीएल

मैं एक चयनित फ्रेम प्रदर्शित कर सकता हूं, हालांकि, यह अभी भी गुलाबी और हरे रंग के कुछ रंगों के साथ मुख्य रूप से काले और सफेद रंग में है।

यहाँ कैसे मेरी उत्पादन की तरह alt text http://i32.tinypic.com/hv0vih.png

फिर भी दिखता है, यहाँ कैसे मेरे कार्यक्रम काम करता है। (यह कोको/उद्देश्य-सी में किया जाता है, लेकिन मुझे प्रोग्राम एल्गोरिदम पर आपकी विशेषज्ञ सलाह की आवश्यकता है, सिंटैक्स पर नहीं।)

प्रोग्राम निष्पादन से पहले, वाईयूवी फ़ाइल को "test.yuv" नामक एक बाइनरी फ़ाइल में संग्रहीत किया जाता है। । फ़ाइल एनवी 12 प्रारूप में है, जिसका अर्थ है कि वाई योजना पहले संग्रहित की जाती है, फिर यूवी योजना अंतःस्थापित होती है। मेरी फ़ाइल निष्कर्षण में कोई समस्या नहीं है क्योंकि मैंने इसके बारे में बहुत से परीक्षण किए हैं।

दीक्षा के दौरान, मैं एक लुकअप तालिका कि सम्मान वाई, यू, वी नाव को महत्व देता

इस Y विमान के लिए में द्विआधारी/8 के काटने/एक बाइट/वर्ण में परिवर्तित कर देंगे बनाने मेरी कोड है

-(void)createLookupTableY //creates a lookup table for converting a single byte into a float between 0 and 1 
{ 
    NSLog(@"YUVFrame: createLookupTableY"); 
    lookupTableY = new float [256]; 

    for (int i = 0; i < 256; i++) 
    { 
     lookupTableY[i] = (float) i /255; 
     //NSLog(@"lookupTableY[%d]: %f",i,lookupTableY[i]);//prints out the value of each float 
    } 
} 

यू विमान लुकअप तालिका

-(void)createLookupTableU //creates a lookup table for converting a single byte into a float between 0 and 1 
{ 
    NSLog(@"YUVFrame: createLookupTableU"); 
    lookupTableU = new float [256]; 

    for (int i = 0; i < 256; i++) 
    { 
     lookupTableU[i] = -0.436 + (float) i/255* (0.436*2); 
     NSLog(@"lookupTableU[%d]: %f",i,lookupTableU[i]);//prints out the value of each float 
    } 
} 

और वी लुकअप तालिका

-(void)createLookupTableV //creates a lookup table for converting a single byte into a float between 0 and 1 
{ 
    NSLog(@"YUVFrame: createLookupTableV"); 
    lookupTableV = new float [256]; 

    for (int i = 0; i < 256; i++) 
    { 
     lookupTableV[i] = -0.615 + (float) i /255 * (0.615*2); 
     NSLog(@"lookupTableV[%d]: %f",i,lookupTableV[i]);//prints out the value of each float 
    } 
} 

इस बिंदु के बाद, मैं वाई & यूवी योजना निकालें और उन्हें, yBuffer & uvBuffer

इस बिंदु पर दो बफ़र्स में स्टोर, मैं YUV डेटा रूपांतरित करने का प्रयास है और यह एक आरजीबी बफर सरणी कहा जाता है में संग्रहीत " frameImage "

-(void)sortAndConvert//sort the extracted frame data into an array of float 
{ 
    NSLog(@"YUVFrame: sortAndConvert"); 
    int frameImageCounter = 0; 
    int pixelCounter = 0; 
    for (int y = 0; y < YUV_HEIGHT; y++)//traverse through the frame's height 
    { 
     for (int x = 0; x < YUV_WIDTH; x++)//traverse through the frame's width 
     { 

      float Y = lookupTableY [yBuffer [y*YUV_WIDTH + x] ]; 
      float U = lookupTableU [uvBuffer [ ((y/2) * (YUV_WIDTH/2) + (x/2)) * 2 ] ]; 
      float V = lookupTableV [uvBuffer [ ((y/2) * (YUV_WIDTH/2) + (x/2)) * 2 + 1] ]; 

      float RFormula = Y + 1.13983f * V; 
      float GFormula = Y - 0.39465f * U - 0.58060f * V; 
      float BFormula = Y + 2.03211f * U; 

      frameImage [frameImageCounter++] = [self clampValue:RFormula]; 
      frameImage [frameImageCounter++] = [self clampValue:GFormula]; 
      frameImage [frameImageCounter++] = [self clampValue:BFormula]; 

     } 
    } 

} 

तो मैं ओपन

-(void)drawFrame:(int)x 
{ 

    GLuint texture; 

    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, YUV_WIDTH, YUV_HEIGHT, 0, GL_RGB, GL_FLOAT, frameImage); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

    glEnable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glRotatef(180.0f, 1.0f, 0.0f, 0.0f); 

    glBegin(GL_QUADS); 
    glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0); 
    glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0); 
    glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0); 
    glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0); 
    glEnd(); 

    glFlush(); 
} 

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

यह वह जगह है जहां मुझे लगता है कि त्रुटि हो सकती है: वाई लुकअप टेबल में मैं वाई विमान में [0,1] को मानकीकृत करता हूं, यू विमान में मैंने [-0.435,0.436] के बीच मानों को मानकीकृत किया है, और वी विमान मैंने इसे चौदह मानकीकृत [-0.615,0.615]। मैंने ऐसा इसलिए किया क्योंकि वे विकिपीडिया के अनुसार वाईयूवी मूल्य सीमाएं हैं।

और आरजीबी फॉर्मूला में वाईयूवी विकिपीडिया से एक ही सूत्र है। मैंने कई अन्य सूत्रों की भी कोशिश की है, और यह एकमात्र सूत्र है जो फ्रेम के किसी न किसी दृष्टिकोण को देता है। कोई भी यह अनुमान लगाने का अनुमान लगा सकता है कि मेरा प्रोग्राम वाईयूवी फ्रेम डेटा को सही ढंग से क्यों प्रदर्शित नहीं कर रहा है। मुझे लगता है कि यह मेरी मानकीकरण तकनीक के साथ कुछ करना है, लेकिन यह मेरे लिए ठीक लगता है।

मैंने बहुत सारी परीक्षाएं की हैं, और मैं 100% निश्चित हूं कि त्रुटि तालिका को देखकर होती है। मुझे नहीं लगता कि मेरे सेटिंग सूत्र सही हैं।

जो इस पढ़ रहा है हर किसी के लिए एक नोट।सबसे लंबे समय तक, मेरा फ्रेम ठीक से प्रदर्शित नहीं हो रहा था क्योंकि मैं फ्रेम डेटा सही तरीके से निकालने में सक्षम नहीं था।

जब मैं पहली बार कार्यक्रम शुरू कर दिया, मैं यह धारणा था की एक क्लिप में 30 फ्रेम, सभी 30 वाई प्लानर datas पहले डेटा फ़ाइल में लिखा जाता है का कहना है कि, यूवी विमान datas से तो पीछा किया।

क्या मैं परीक्षण के माध्यम से पता चला और त्रुटि है कि एक YUV डेटा फ़ाइल के लिए, विशेष रूप से NV12, डेटा फ़ाइल निम्नलिखित फैशन में जमा हो जाती है था

वाई (1) यूवी (1) वाई (2) यूवी (2) ... ...

@nschmidt

मैं तुम्हें क्या सुझाव दिया

float U = lookupTableU [uvBuffer [ (y * (YUV_WIDTH/4) + (x/4)) * 2 ] ] 
float V = lookupTableU [uvBuffer [ (y * (YUV_WIDTH/4) + (x/4)) * 2 + 1] ] 
करने के लिए अपने कोड बदल

और यह परिणाम है कि मैं पाने के alt text http://i26.tinypic.com/kdtilg.png

यहाँ कंसोल से प्रिंट लाइन है। मैं प्रिंट आउट वाई, यू, वी और आरजीबी मूल्य के लिए मानों अनुवाद किया जा रहा है और frameImage सरणी में पर संग्रहीत कर रहा हूँ

YUV: [.६,५८,८२४, -0.०,२२,२२७, -0.०,४५,८२४] RGBFinal: [0.606593,0.694201,0.613655 ]

YUV: [.६,४३,१३७, -0.०,२२,२२७, -0.०,४५,८२४] RGBFinal: [0.590906,0.678514,0.597969]

YUV: [.६,०७,८४३, -0.०,२२,२२७, -0.०,४५,८२४] RGBFinal: [0.555612,0.643220,0.562675]

वाईयूवी: [0.5 9 2157, -0.022227, -0.045824] आरजीबीफ़ाइनल: [0.539 926,0.627534,0.546988]

YUV: [0.643137,0.025647,0.151941] RGBFinal: [0.816324,0.544799,0.695255]

YUV: [0.662745,0.025647,0.151941] RGBFinal: [0.835932,0.564406,0.714863]

YUV: [.६,९०,१९६ , 0.025647,0.151941] RGBFinal: [0.863383,0.591857,0.742314]

अद्यतन 13 जुलाई, 2009

समस्या अंत में nschmidt से सिफारिश करने के लिए धन्यवाद हल किया गया था। यह पता चला है कि मेरी वाईयूवी फ़ाइल वास्तव में वाईयूवी 4: 1: 1 प्रारूप में थी। मुझे मूल रूप से बताया गया था कि यह वाईयूवी एनवी 12 प्रारूप में था। वैसे भी, मैं अपने परिणामों को आपके साथ साझा करना चाहता हूं।

यहाँ उत्पादन

alt text http://i32.tinypic.com/35b9xf8.png

है और डिकोड के लिए मेरे कोड के रूप में इस प्रकार है

 float Y = (float) yBuffer [y*YUV_WIDTH + x] ; 
     float U = (float) uvBuffer [ ((y/2) * (YUV_WIDTH/2) + (x/2)) ] ; 
     float V = (float) uvBuffer [ ((y/2) * (YUV_WIDTH/2) + (x/2)) + UOffset] ; 

     float RFormula = (1.164*(Y-16) + (1.596* (V - 128))); 
     float GFormula = ((1.164 * (Y - 16)) - (0.813 * ((V) - 128)) - (0.391 * ((U) - 128))); 
     float BFormula = ((1.164 * (Y - 16)) + (2.018 * ((U) - 128))); 


     frameImage [frameImageCounter] = (unsigned char)((int)[self clampValue:RFormula]); 
     frameImageCounter ++; 
     frameImage [frameImageCounter] = (unsigned char)((int)[self clampValue:GFormula]); 
     frameImageCounter++; 
     frameImage [frameImageCounter] = (unsigned char)((int) [self clampValue:BFormula]); 
     frameImageCounter++; 



GLuint texture; 

glGenTextures(1, &texture); 
glEnable(GL_TEXTURE_2D); 

glBindTexture(GL_TEXTURE_2D, texture); 
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, YUV_WIDTH, YUV_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, frameImage); 

//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE_SGIS); 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE_SGIS); 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); 

glRotatef(180.0f, 1.0f, 0.0f, 0.0f); 

glBegin(GL_QUADS); 
glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0); 
glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0); 
glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0); 
glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0); 
glEnd(); 

NSLog(@"YUVFrameView: drawRect complete"); 
glFlush(); 

अनिवार्य रूप से, मैं कच्चे फ़ाइल निकासी के लिए NSData प्रयोग किया जाता है। एक चार सरणी बफर में संग्रहीत। वाईयूवी के लिए आरजीबी रूपांतरण के लिए, मैंने उपर्युक्त सूत्र का उपयोग किया, बाद में, मैंने मूल्यों को [0: 255] पर क्लैंप किया। तो मैंने प्रदर्शन के लिए ओपनजीएल में 2 डीटेक्चर का इस्तेमाल किया।

तो यदि आप भविष्य में वाईयूवी को आरजीबी में परिवर्तित कर रहे हैं, तो ऊपर से सूत्र का उपयोग करें। यदि पहले पोस्ट से आरजीबी रूपांतरण फॉर्मूला में वाईयूवी का उपयोग कर रहे हैं, तो आपको आरजीबी के मानों से जीएल_फ्लैट में बनावट प्रदर्शित करने की आवश्यकता है [0: 1]

उत्तर

8

अगला प्रयास करें :) मुझे लगता है कि आप यूवी बफर इंटरलीव नहीं हैं। ऐसा लगता है कि यू मान पहले आते हैं और फिर वी मानों की सरणी होती है। लाइनों को

unsigned int voffset = YUV_HEIGHT * YUV_WIDTH/2; 
float U = lookupTableU [uvBuffer [ y * (YUV_WIDTH/2) + x/2] ]; 
float V = lookupTableV [uvBuffer [ voffset + y * (YUV_WIDTH/2) + x/2] ]; 

इंगित कर सकता है कि यह वास्तव में मामला है या नहीं।

+0

वाह जैसा दिखता है, मैंने आपके प्रोग्राम को आपके समायोजन के साथ परीक्षण किया और अंत में काम किया। बहुत बहुत धन्यवाद। यह पता चला है कि आप सही थे, यू एंड वी विमान को अंतःस्थापित नहीं किया गया था क्योंकि मुझे मूल रूप से बताया गया था। आपको बहुत धन्यवाद nschmidt। मैं आपको रेटिंग कर रहा हूं – ReachConnection

+0

कोई समस्या नहीं :)। रिकॉर्ड के लिए 4: 1: 1 प्रारूप के बारे में पहला अनुमान वास्तव में गलत था। आपके पास 4: 2: 2 प्रारूप है। वास्तविक समस्या केवल आपका डेटा था जिसे इंटरलीव नहीं किया जा रहा था। – nschmidt

+0

@ रीचकनेक्शन: क्या आप मुझे बता सकते हैं कि [स्वयं क्लैंपवैल्यू: आरएफर्मुला] यह फ़ंक्शन क्या कर रहा है? मैं यूआईवी 422 से यूआईएममेज प्राप्त करने के लिए अपने कोड का उपयोग करने की योजना बना रहा हूं। –

3

मुझे लगता है कि आप यू और वी मानों को संबोधित कर रहे हैं गलत तरीके से। के बजाय: 1:: 1 प्रारूप

float U = lookupTableU [uvBuffer [ ((y/2) * (x/2) + (x/2)) * 2 ] ]; 
float V = lookupTableV [uvBuffer [ ((y/2) * (x/2) + (x/2)) * 2 + 1] ]; 

यह

float U = lookupTableU [uvBuffer [ ((y/2) * (YUV_WIDTH/2) + (x/2)) * 2 ] ]; 
float V = lookupTableV [uvBuffer [ ((y/2) * (YUV_WIDTH/2) + (x/2)) * 2 + 1] ]; 
+0

धन्यवाद, मुझे यह गलती याद आई। हालांकि, मैंने परिवर्तन किए और प्रदर्शित फ्रेम अभी भी काले और सफेद रंग में है, यहां गुलाबी और हरे रंग के रंग हैं। – ReachConnection

+0

मैंने अभी यह दिखाने के लिए एक छवि जोड़ा है कि मेरा आउटपुट – ReachConnection

0

की तर्ज पर कुछ चित्र लगता है कि आप 4 होना चाहिए। आप शायद तुम परिणाम पोस्ट देखने के लिए कर सकते हैं

float U = lookupTableU [uvBuffer [ (y * (YUV_WIDTH/4) + (x/4)) * 2 ] ] 
float V = lookupTableU [uvBuffer [ (y * (YUV_WIDTH/4) + (x/4)) * 2 + 1] ] 

करने के लिए अपने लाइनों बदलना चाहिए, और क्या गलत है। मुझे इसके बारे में सोचना हमेशा मुश्किल लगता है। इसे इस दृष्टिकोण से संपर्क करना बहुत आसान है।