View JPEG

Hello!
I try view JPEG from IP-camera, I have used Qt 4.7.
My code:
initializeGL()

glClearColor(0.0, 0.0, 0.0, 0.0);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_CUBE_MAP);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

resizeGL(int width, int height)

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//convert QByteArray
image = QGLWidget::convertToGLFormat(QImage::fromData(jpg));
if (1 == frame_number)
        glTexImage2D(GL_TEXTURE_2D, 0, 4, image.width(), image.height(),
		0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
else
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width(),
			image.height(),	GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
glDisable(GL_TEXTURE_2D);
glPixelZoom(1.0, 1.0);

paintGL()

glClear(GL_COLOR_BUFFER_BIT);
glTranslatef(-image.width()/2, -image.height()/2, 0.0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 1.0);
glVertex3f(0.0, image.height(), 0.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f(image.width(), 0.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(image.width(), image.height(), 0.0);
glEnd();
glDisable(GL_TEXTURE_2D);
//glDrawPixels(image.width(), image.height(), GL_RGBA,
//		 GL_UNSIGNED_BYTE, image.bits());

I run resizeGL and paintGL after each frame.
I successfully get JPEG, but I have two problems:

  • if I comment glDrawPixels I view only white rectangle
  • if I use glDrawPixels I view static image
    How can I solve this problem?
    Thank you and excuse me for my bad english.

Simply by updating your image every frame (or almost if you want to achieve a constant framerate from your camera).

The easiest and a fast solution is to use glCopyTexSubImage. I think you can achieve this with glDrawPixels but it will be slower.

Hello and thank you for your reply!
Where I need use glCopyTexSubImage? I try use it in resize and paint, but I don’t get any changes.

Also I view strange:

GLFormat glformat;
qDebug() << "OpenGL version" << glformat.majorVersion()
	 << glformat.minorVersion()
	 << glformat.openGLVersionFlags()
	 << "
pbuffer" << QGLPixelBuffer::hasOpenGLPbuffers();

I get this OpenGL version 1 0 QFlags(0x1|0x2|0x4|0x8|0x10|0x20|0x40)
pbuffer true

But glxinfo have another info:

name of display: :0.0
display: :0  screen: 0
direct rendering: Yes
server glx vendor string: NVIDIA Corporation
server glx version string: 1.4
server glx extensions:
    GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_SGIX_fbconfig, 
    GLX_SGIX_pbuffer, GLX_SGI_video_sync, GLX_SGI_swap_control, 
    GLX_EXT_texture_from_pixmap, GLX_ARB_multisample, GLX_NV_float_buffer
client glx vendor string: NVIDIA Corporation
client glx version string: 1.4
client glx extensions:
    GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_visual_info, 
    GLX_EXT_visual_rating, GLX_EXT_import_context, GLX_SGI_video_sync, 
    GLX_NV_swap_group, GLX_NV_video_out, GLX_SGIX_fbconfig, GLX_SGIX_pbuffer, 
    GLX_SGI_swap_control, GLX_NV_float_buffer, GLX_ARB_fbconfig_float, 
    GLX_EXT_fbconfig_packed_float, GLX_EXT_texture_from_pixmap, 
    GLX_EXT_framebuffer_sRGB, GLX_NV_present_video
GLX version: 1.3
GLX extensions:
    GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_SGIX_fbconfig, 
    GLX_SGIX_pbuffer, GLX_SGI_video_sync, GLX_SGI_swap_control, 
    GLX_EXT_texture_from_pixmap, GLX_ARB_multisample, GLX_NV_float_buffer, 
    GLX_ARB_get_proc_address
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce FX 5500/AGP/SSE2
OpenGL version string: 2.1.2 NVIDIA 173.14.27
OpenGL shading language version string: 1.20 NVIDIA via Cg compiler
OpenGL extensions:
    GL_ARB_depth_texture, GL_ARB_fragment_program, 
    GL_ARB_fragment_program_shadow, GL_ARB_fragment_shader, 
    GL_ARB_half_float_pixel, GL_ARB_imaging, GL_ARB_multisample, 
    GL_ARB_multitexture, GL_ARB_occlusion_query, GL_ARB_pixel_buffer_object, 
    GL_ARB_point_parameters, GL_ARB_point_sprite, GL_ARB_shadow, 
    GL_ARB_shader_objects, GL_ARB_shading_language_100, 
    GL_ARB_texture_border_clamp, GL_ARB_texture_compression, 
    GL_ARB_texture_cube_map, GL_ARB_texture_env_add, 
    GL_ARB_texture_env_combine, GL_ARB_texture_env_dot3, 
    GL_ARB_texture_mirrored_repeat, GL_ARB_texture_rectangle, 
    GL_ARB_transpose_matrix, GL_ARB_vertex_buffer_object, 
    GL_ARB_vertex_program, GL_ARB_vertex_shader, GL_ARB_window_pos, 
    GL_S3_s3tc, GL_EXT_texture_env_add, GL_EXT_abgr, GL_EXT_bgra, 
    GL_EXT_blend_color, GL_EXT_blend_func_separate, GL_EXT_blend_minmax, 
    GL_EXT_blend_subtract, GL_EXT_compiled_vertex_array, GL_EXT_Cg_shader, 
    GL_EXT_draw_range_elements, GL_EXT_fog_coord, GL_EXT_framebuffer_blit, 
    GL_EXT_framebuffer_multisample, GL_EXT_framebuffer_object, 
    GL_EXT_gpu_program_parameters, GL_EXT_multi_draw_arrays, 
    GL_EXT_packed_depth_stencil, GL_EXT_packed_pixels, 
    GL_EXT_paletted_texture, GL_EXT_pixel_buffer_object, 
    GL_EXT_point_parameters, GL_EXT_rescale_normal, GL_EXT_secondary_color, 
    GL_EXT_separate_specular_color, GL_EXT_shadow_funcs, 
    GL_EXT_shared_texture_palette, GL_EXT_stencil_two_side, 
    GL_EXT_stencil_wrap, GL_EXT_texture3D, GL_EXT_texture_compression_s3tc, 
    GL_EXT_texture_cube_map, GL_EXT_texture_edge_clamp, 
    GL_EXT_texture_env_combine, GL_EXT_texture_env_dot3, 
    GL_EXT_texture_filter_anisotropic, GL_EXT_texture_lod, 
    GL_EXT_texture_lod_bias, GL_EXT_texture_object, GL_EXT_texture_sRGB, 
    GL_EXT_timer_query, GL_EXT_vertex_array, GL_IBM_rasterpos_clip, 
    GL_IBM_texture_mirrored_repeat, GL_KTX_buffer_region, GL_NV_blend_square, 
    GL_NV_copy_depth_to_color, GL_NV_depth_clamp, GL_NV_fence, 
    GL_NV_float_buffer, GL_NV_fog_distance, GL_NV_fragment_program, 
    GL_NV_fragment_program_option, GL_NV_framebuffer_multisample_coverage, 
    GL_NV_half_float, GL_NV_light_max_exponent, GL_NV_multisample_filter_hint, 
    GL_NV_occlusion_query, GL_NV_packed_depth_stencil, GL_NV_pixel_data_range, 
    GL_NV_point_sprite, GL_NV_primitive_restart, GL_NV_register_combiners, 
    GL_NV_register_combiners2, GL_NV_texgen_reflection, 
    GL_NV_texture_compression_vtc, GL_NV_texture_env_combine4, 
    GL_NV_texture_expand_normal, GL_NV_texture_rectangle, 
    GL_NV_texture_shader, GL_NV_texture_shader2, GL_NV_texture_shader3, 
    GL_NV_vertex_array_range, GL_NV_vertex_array_range2, GL_NV_vertex_program, 
    GL_NV_vertex_program1_1, GL_NV_vertex_program2, 
    GL_NV_vertex_program2_option, GL_SGIS_generate_mipmap, 
    GL_SGIS_texture_lod, GL_SGIX_depth_texture, GL_SGIX_shadow, 
    GL_SUN_slice_accum

Why Qt return 1.0 as version OpenGL?

I reread your first post.
Can you ensure paintGL is not called only once ? I mean if you try to do a little animation in this function, do you see any animation or do you have a static image ? If you have a static image, try to see how QT works to make animations work (basically paintGL should be called in a callback function).

glCopyTexSubImage should be called wherever you need to update the content of your texture data.

Try this: “glGetString(GL_VERSION)” and tell what result do you have.

Yes, I insert in paintGL debug output qDebug(“paintGL: texture id %d”, texture);
I see next output while I don’t close programm:

paintGL: texture id 1
paintGL: texture id 1
paintGL: texture id 1
.........

I insert in constructor next code:

QGLFormat glformat;
glformat.setVersion(1, 4);
qDebug() << "OpenGL version" << glformat.majorVersion()
	 << glformat.minorVersion()
	 << glformat.openGLVersionFlags()
	 << "
pbuffer" << QGLPixelBuffer::hasOpenGLPbuffers();
makeCurrent();
qDebug() << "OpenGL version" << (char *)glGetString(GL_VERSION);

And get this output:

OpenGL version 1 4 QFlags(0x1|0x2|0x4|0x8|0x10|0x20|0x40) 
pbuffer true 
OpenGL version 2.1.2 NVIDIA 173.14.27

Why do you “set” the version with glformat.setVersion(1, 4) ? I think you can forget it.

Where do you update your “image.bits()” ? From me, image.bits always have the same content.

Ok, I don’t use setVersion and get this output:

OpenGL version 1 0 QFlags(0x1|0x2|0x4|0x8|0x10|0x20|0x40) 
pbuffer true 
OpenGL version 2.1.2 NVIDIA 173.14.27

This is very simple:

QByteArray jpg; //array for image
quint32 frame_size; //image size
quint16 frame_part; //number packets for send frame

jpg.truncate(0);
jpg.reserve(frame_size + 1);

void Image::fill_data(const quint16 num, const quint16 size,
					  const char *data)
{
        jpg.append(data, size);

	cur_size += size;
	cur_packet = num;

	if (cur_size == frame_size && cur_packet == frame_part)
		emit view_image();
}

void Image::view_image()
{
	resizeGL(frame_resolution.width(), frame_resolution.height());
	paintGL();
}

When I get frame, check frame size, I run view_image.
In resizeGL I convert jpg to OpenGL format and use it data in glTexImage2D.
After paintGL I get new frame.

OK. I know very very few about QT. But:

jpg.append(data, size);

Since jpg is a file variable, won’t this call append, and append… the data to jpg (so the first n bytes will always be the same, and could result in memory swap) ? Wouldn’t it better to replace the data ?

Can you try to do this ?


void Image::fill_data(const quint16 num, const quint16 size,
					  const char *data)
{
   glBindTexture (GL_TEXTURE_2D, texture_id);
   glTexSubImage2D (GL_TEXTURE_2D, 0, 0,0, image_width, image_height, GL_RGB, GL_UNSIGNED_BYTE, data);
}

with texture_id the texture_id returned when creating the texture, and image_width and image_height the image size.
And of course, avoid TexSubImage in your rendering function.

No, jpg isn’t file, it is buffer, I get it via network and network packets have maximum size 1400 byte.

That will change if I generate texture in fill_data?

I try, but this is not solve problem.

Sincerly, I don’t know. Updating your image data with glTexImage2D or glTexSubImage2D is enough to make the image change each frame, and so see an animated texture.
Ensure the format of your data are the same than GL expects them. Ensure you bind to the same texture id.

Hello again!
Information about my videocard:

$ glxinfo 
name of display: :0.0
display: :0  screen: 0
direct rendering: Yes
server glx vendor string: NVIDIA Corporation
server glx version string: 1.4
server glx extensions:
    GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_SGIX_fbconfig, 
    GLX_SGIX_pbuffer, GLX_SGI_video_sync, GLX_SGI_swap_control, 
    GLX_EXT_texture_from_pixmap, GLX_ARB_multisample, GLX_NV_float_buffer
client glx vendor string: NVIDIA Corporation
client glx version string: 1.4
client glx extensions:
    GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_visual_info, 
    GLX_EXT_visual_rating, GLX_EXT_import_context, GLX_SGI_video_sync, 
    GLX_NV_swap_group, GLX_NV_video_out, GLX_SGIX_fbconfig, GLX_SGIX_pbuffer, 
    GLX_SGI_swap_control, GLX_NV_float_buffer, GLX_ARB_fbconfig_float, 
    GLX_EXT_fbconfig_packed_float, GLX_EXT_texture_from_pixmap, 
    GLX_EXT_framebuffer_sRGB, GLX_NV_present_video
GLX version: 1.3
GLX extensions:
    GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_SGIX_fbconfig, 
    GLX_SGIX_pbuffer, GLX_SGI_video_sync, GLX_SGI_swap_control, 
    GLX_EXT_texture_from_pixmap, GLX_ARB_multisample, GLX_NV_float_buffer, 
    GLX_ARB_get_proc_address
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce FX 5500/AGP/SSE2
OpenGL version string: 2.1.2 NVIDIA 173.14.27
OpenGL shading language version string: 1.20 NVIDIA via Cg compiler
OpenGL extensions:
GL_ARB_depth_texture, GL_ARB_fragment_program, 
    GL_ARB_fragment_program_shadow, GL_ARB_fragment_shader, 
    GL_ARB_half_float_pixel, GL_ARB_imaging, GL_ARB_multisample, 
    GL_ARB_multitexture, GL_ARB_occlusion_query, GL_ARB_pixel_buffer_object, 
    GL_ARB_point_parameters, GL_ARB_point_sprite, GL_ARB_shadow, 
    GL_ARB_shader_objects, GL_ARB_shading_language_100, 
    GL_ARB_texture_border_clamp, GL_ARB_texture_compression, 
    GL_ARB_texture_cube_map, GL_ARB_texture_env_add, 
    GL_ARB_texture_env_combine, GL_ARB_texture_env_dot3, 
    GL_ARB_texture_mirrored_repeat, GL_ARB_texture_rectangle, 
    GL_ARB_transpose_matrix, GL_ARB_vertex_buffer_object, 
    GL_ARB_vertex_program, GL_ARB_vertex_shader, GL_ARB_window_pos, 
    GL_S3_s3tc, GL_EXT_texture_env_add, GL_EXT_abgr, GL_EXT_bgra, 
    GL_EXT_blend_color, GL_EXT_blend_func_separate, GL_EXT_blend_minmax, 
    GL_EXT_blend_subtract, GL_EXT_compiled_vertex_array, GL_EXT_Cg_shader, 
    GL_EXT_draw_range_elements, GL_EXT_fog_coord, GL_EXT_framebuffer_blit, 
    GL_EXT_framebuffer_multisample, GL_EXT_framebuffer_object, 
    GL_EXT_gpu_program_parameters, GL_EXT_multi_draw_arrays, 
    GL_EXT_packed_depth_stencil, GL_EXT_packed_pixels, 
    GL_EXT_paletted_texture, GL_EXT_pixel_buffer_object, 
    GL_EXT_point_parameters, GL_EXT_rescale_normal, GL_EXT_secondary_color, 
    GL_EXT_separate_specular_color, GL_EXT_shadow_funcs, 
    GL_EXT_shared_texture_palette, GL_EXT_stencil_two_side, 
    GL_EXT_stencil_wrap, GL_EXT_texture3D, GL_EXT_texture_compression_s3tc, 
    GL_EXT_texture_cube_map, GL_EXT_texture_edge_clamp, 
    GL_EXT_texture_env_combine, GL_EXT_texture_env_dot3, 
    GL_EXT_texture_filter_anisotropic, GL_EXT_texture_lod, 
    GL_EXT_texture_lod_bias, GL_EXT_texture_object, GL_EXT_texture_sRGB, 
    GL_EXT_timer_query, GL_EXT_vertex_array, GL_IBM_rasterpos_clip, 
    GL_IBM_texture_mirrored_repeat, GL_KTX_buffer_region, GL_NV_blend_square, 
    GL_NV_copy_depth_to_color, GL_NV_depth_clamp, GL_NV_fence, 
    GL_NV_float_buffer, GL_NV_fog_distance, GL_NV_fragment_program, 
    GL_NV_fragment_program_option, GL_NV_framebuffer_multisample_coverage, 
    GL_NV_half_float, GL_NV_light_max_exponent, GL_NV_multisample_filter_hint, 
    GL_NV_occlusion_query, GL_NV_packed_depth_stencil, GL_NV_pixel_data_range, 
    GL_NV_point_sprite, GL_NV_primitive_restart, GL_NV_register_combiners, 
    GL_NV_register_combiners2, GL_NV_texgen_reflection, 
    GL_NV_texture_compression_vtc, GL_NV_texture_env_combine4, 
    GL_NV_texture_expand_normal, GL_NV_texture_rectangle, 
    GL_NV_texture_shader, GL_NV_texture_shader2, GL_NV_texture_shader3, 
    GL_NV_vertex_array_range, GL_NV_vertex_array_range2, GL_NV_vertex_program, 
    GL_NV_vertex_program1_1, GL_NV_vertex_program2, 
    GL_NV_vertex_program2_option, GL_SGIS_generate_mipmap, 
    GL_SGIS_texture_lod, GL_SGIX_depth_texture, GL_SGIX_shadow, 
    GL_SUN_slice_accum

And I get information what my card don’t support NPOT textures, but I can use GL_ARB_texture_rectangle extension.
I read http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt and try it, but I get error invalid operation in glEnable(GL_TEXTURE_RECTANGLE_ARB) and glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, …) operations.

QString Image::glerror_to_text(GLenum err)
{
	return QString("GLError [%1] %2").
			arg(err, 0, 10).
			arg((char *)gluErrorString(err));
}

I get this output:

initializeGL: after glEnable "GLError [1282] invalid operation"
resizeGL: after glTex*Image2D "GLError [1282] invalid operation"

How can I solve this problem?
Thank you.

P.S. When I read http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml and http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml I don’t see GL_TEXTURE_RECTANGLE_ARB target, why?

Because GL_TEXTURE_RECTANGLE_ARB is an extension. You need to read the extension pages

http://www.opengl.org/registry/

http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt

V-man, he said he read the specs. And AFAIK, GL_TEXTURE_RECTANGLE_ARB need no function loading process.

I think Qt has something to do with this. Try to set a higher QT GL version (2.0 or so). If it still does not work, I think you should check about a QT GL forum.

His question was

P.S. When I read http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml and http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml I don’t see GL_TEXTURE_RECTANGLE_ARB target, why?

and that’s why I answered.

People don’t understand the difference between OpenGL and a OpenGL extension. The http://www.opengl.org/sdk/docs don’t cover extensions.

Ok, I is only start use OpenGL and don’t understand all yet.
But my main question - why I can’t see JPEG, where I have error?

This pseudo-code should do the work:


// init
GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex_id);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, image_width, image_height, 0, GL_RED, GL_UNSIGNED_BYTE, data);

// draw loop
data = get_data_compatible_with_gl_from_camera();
glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex_id);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0,0, image_width, image_height, GL_RGB, GL_UNSIGNED_BYTE, data);
glBegin (GL_QUADS);
glTexCoord2f (0,0);
glVertex2f (0,0);
glTexCoord2f (image_width, 0);
glVertex2f (quad_width, 0);
glTexCoord2f (image_width, image_height);
glVertex2f (quad_width, quad_height);
glTexCoord2f (0, image_height);
glVertex2f (0, quad_height);
glEnd();
glDisable (GL_TEXTURE_RECTANGLE_ARB);

If you can’t get GL_TEXTURE_RECTANGLE_ARB to be recognized, you have several solutions: the best, check a QT forum to know how to do it. The easiest: use squared POT textures.

I really think your issue is a QT issue since you can have different GL versions if you check it directly by GL or threw a Qt function. Unfortunately I never did OpenGL with Qt, so I can’t help you more.

And when you’ll find why, it will be nice to let us know :slight_smile: