EAGLContexts共享EAGLSharegroup在子类化GLKView时给出错误

时间:2015-08-27 11:16:54

标签: ios objective-c multithreading ffmpeg opengl-es-2.0

我正在尝试使用FFMPEG创建一个可以使用OpenGl显示帧的播放器。 player类有三个线程:一个用于渲染(运行runloop并处理每N ms触发的渲染事件。) - 它获取存储在pictureQueue中的GLKTextureInfo并渲染。  一个用于从VideoStream读取数据包并将它们放入videoQueue中,第三个从videoQueue获取数据包并对其进行解码并创建GLKTextureInfo并将其存储在pictureQueue中。

案例1: player类子类GLKView并创建EAGLContext将其设置为其上下文,并将其设置为呈现线程中的currentContext(它是第一个启动的线程)。

EAGLContext *mycontext = [self createBestEaglContext];
if (!self.mycontext || ![EAGLContext setCurrentContext:mycontext]) {
    NSLog(@"Could not create Base EAGLContext");
    return;
}
[self setContext:mycontext];

然后启动stream decoding thread,如果找到视频流,则Video Packet Decoding Thread会启动// set's the params for the GLKBaseEffect // set's up VBO's // run's runloop 。然后

Video Packet Decoding Thread

EAGLContext还会创建EAGLSharegroup,共享先前创建的上下文self.videoPacketDecodeThreadContext = [self createEaglContextForOtherThread]; if (!self.videoPacketDecodeThreadContext || ![EAGLContext setCurrentContext:self.videoPacketDecodeThreadContext]) { NSLog(@"Could not create video packet decode thread context"); }

UIImage* image = [self ImageFromAVPicture:*(AVPicture*)pFrameRGB width:self.is.video_stream->codec->width height:self.is.video_stream->codec->height];

NSError *error = nil;
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:image.CGImage
                                                               options:nil
                                                                 error:&error];
if (error)
{
   NSLog(@"Texture loading Error: %@\n", error.description);
   //return -1;
}
else
{
   [self.is.pictQueue_lock lock];
   [self.is.pictQueue enqueue:textureInfo];
   [self.is.pictQueue_lock unlock];
}

纹理部分

Failed to bind EAGLDrawable: <CAEAGLLayer: 0x156f7e50> to GL_RENDERBUFFER 1

我收到错误Failed to make complete framebuffer object 8cd6glerror 1280以及Player

案例2 GLKView不是子类GLKView,而是将其设置为故事板中创建的-(void)initPlayerWithView:(GLKView*)v { self.view = v; } 的委托。

self.view

并将everyThing设置为上述(将mycontext上下文设置为-(void)drawRect:(CGRect)rect)一切正常。

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect而且Rendering Thread都在 { [self.is.pictQueue_lock lock]; GLKTextureInfo *textureInfo = (GLKTextureInfo*)[self.is.pictQueue dequeue]; [self.is.pictQueue_lock unlock]; // delete the previous texture GLuint index = self.baseEffect.texture2d0.name; glDeleteTextures(1, &index); self.baseEffect.texture2d0.name = textureInfo.name; self.baseEffect.texture2d0.target = textureInfo.target; [self.baseEffect prepareToDraw]; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Enable vertex buffer glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); glEnableVertexAttribArray(GLKVertexAttribPosition); //Enable texture buffer glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, textureCoords)); glEnableVertexAttribArray(GLKVertexAttribTexCoord0); glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0); } 上被调用。渲染代码:

 request.Method = "POST /sample.xml";

如何解决案例1中的错误?此外,如果他们是我可以以不同的方式做的其他事情,请建议如:

  1. 我使用过很多线程吗?
  2. 我正在将解码后的帧转换为UIImage,然后从中创建纹理。可以这样做吗?

1 个答案:

答案 0 :(得分:0)

我不是关于GLKView,我在OSX中编写了一个使用NSOpenGLView的播放器,子类化在那里工作得很好,但我让它为我创建了上下文。

  

我使用过很多线程吗?

默认情况下,对于大多数编解码器,ffmpeg使用frame multithreading,这意味着主解码线程不执行任何操作,它会创建子线程并等待它们完成解码帧。 (对于实时通信,你也可以使用切片多线程,这可以减少延迟,但缩放得不太好,并且需要比特流支持。)如果你没有做任何具体的事情来告诉它,ffmpeg使用帧多线程,你的帧解码线程什么也没做。所以你不需要它。播放器线程可以直接解码视频。

  

我正在将解码后的帧转换为   UIImage,然后从中创建纹理。它能做到吗?   不同吗?

UIImage是RGB格式,大多数视频解码器输出YUV,因此这表明其他一些代码正在进行软件YUV-RGB转换。这种RGB转换速度很慢,非常慢。

相反,请考虑openGL可以直接绘制YUV。所以我不会使用UIImage,而是使用着色器直接绘制YUV平面,在硬件内部进行YUV-RGB转换。