int main(int argc, char *argv[]) { AVCodecContext* video_dec_ctx = NULL; AVCodec* video_dec = NULL; AVPacket pkt; AVFrame *frame = NULL; int read_eos = 0; int decode_count = 0; int render_count = 0; int video_stream_index = -1, i; uint8_t *frame_copy = NULL; FILE *dump_yuv = NULL; // parse command line parameters process_cmdline(argc, argv); if (!input_file) { ERROR("no input file specified\n"); return -1; } // libav* init av_register_all(); // open input file AVFormatContext* pFormat = NULL; if (avformat_open_input(&pFormat, input_file, NULL, NULL) < 0) { ERROR("fail to open input file: %s by avformat\n", input_file); return -1; } if (avformat_find_stream_info(pFormat, NULL) < 0) { ERROR("fail to find out stream info\n"); return -1; } av_dump_format(pFormat,0,input_file,0); // find out video stream for (i = 0; i < pFormat->nb_streams; i++) { if (pFormat->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { video_dec_ctx = pFormat->streams[i]->codec; video_stream_index = i; break; } } ASSERT(video_dec_ctx && video_stream_index>=0); // open video codec video_dec = avcodec_find_decoder(video_dec_ctx->codec_id); video_dec_ctx->coder_type = render_mode ? render_mode -1 : render_mode; // specify output frame type if (avcodec_open2(video_dec_ctx, video_dec, NULL) < 0) { ERROR("fail to open codec\n"); return -1; } // decode frames one by one av_init_packet(&pkt); while (1) { if(read_eos == 0 && av_read_frame(pFormat, &pkt) < 0) { read_eos = 1; } if (read_eos) { pkt.data = NULL; pkt.size = 0; } if (pkt.stream_index == video_stream_index) { frame = av_frame_alloc(); int got_picture = 0,ret = 0; ret = avcodec_decode_video2(video_dec_ctx, frame, &got_picture, &pkt); if (ret < 0) { // decode fail (or decode finished) DEBUG("exit ...\n"); break; } if (read_eos && ret>=0 && !got_picture) { DEBUG("ret=%d, exit ...\n", ret); break; // eos has been processed } decode_count++; if (got_picture) { switch (render_mode) { case 0: // dump raw video frame to disk file case 1: { // draw raw frame data as texture // assumed I420 format int height[3] = {video_dec_ctx->height, video_dec_ctx->height/2, video_dec_ctx->height/2}; int width[3] = {video_dec_ctx->width, video_dec_ctx->width/2, video_dec_ctx->width/2}; int plane, row; if (render_mode == 0) { if (!dump_yuv) { char out_file[256]; sprintf(out_file, "./dump_%dx%d.I420", video_dec_ctx->width, video_dec_ctx->height); dump_yuv = fopen(out_file, "ab"); if (!dump_yuv) { ERROR("fail to create file for dumped yuv data\n"); return -1; } } for (plane=0; plane<3; plane++) { for (row = 0; row<height[plane]; row++) fwrite(frame->data[plane]+ row*frame->linesize[plane], width[plane], 1, dump_yuv); } } else { // glTexImage2D doesn't handle pitch, make a copy of video data frame_copy = malloc(video_dec_ctx->height * video_dec_ctx->width * 3 / 2); unsigned char* ptr = frame_copy; for (plane=0; plane<3; plane++) { for (row=0; row<height[plane]; row++) { memcpy(ptr, frame->data[plane]+row*frame->linesize[plane], width[plane]); ptr += width[plane]; } } drawVideo((uintptr_t)frame_copy, 0, video_dec_ctx->width, video_dec_ctx->height, 0); } } break; case 2: // draw video frame as texture with drm handle case 3: // draw video frame as texture with dma_buf handle drawVideo((uintptr_t)frame->data[0], render_mode -1, video_dec_ctx->width, video_dec_ctx->height, (uintptr_t)frame->data[1]); break; default: break; } render_count++; } } } if (frame) av_frame_free(&frame); if (frame_copy) free(frame_copy); if (dump_yuv) fclose(dump_yuv); deinit_egl(); PRINTF("decode %s ok, decode_count=%d, render_count=%d\n", input_file, decode_count, render_count); return 0; }
int egl_lock_surface(void) { fprintf(stderr, "TEST_EXTENSIONS : EGL_KHR_lock_surface & EGL_KHR_lock_surface2 \n"); int ret = 1; int i = 0; EGLImageKHR image; GLuint image_texture; int move_x = 0; int move_y = 0; int direction_x = 1; int direction_y = 1; /* CREATE CONTEXT STRUCTURE */ X11Context* x11_ctx = (X11Context*)malloc(sizeof(X11Context)); EglContext* egl_ctx = (EglContext*)malloc(sizeof(EglContext)); RenderingContext* gles_ctx = (RenderingContext*)malloc(sizeof(RenderingContext)); PFNEGLCREATEIMAGEKHRPROC p_eglCreateImageKHR; PFNEGLDESTROYIMAGEKHRPROC p_eglDestroyImageKHR; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC p_glEGLImageTargetTexture2DOES; /* Initialize native x11 */ if(!init_x11_native(x11_ctx)) goto finish; /* Initialize egl */ if(!init_egl(x11_ctx, egl_ctx)) goto finish; if(!is_supported(egl_ctx->egl_display,"EGL_KHR_lock_surface")) { /* EGL_KHR_lock_surface is not supporect */ fprintf(stderr, "EGL_KHR_lock_surface is not supported\n"); goto finish; } /* Create native pixmap */ int xDefaultScreen = DefaultScreen(x11_ctx->native_display); int xDefaultDepth = XDefaultDepth( x11_ctx->native_display, xDefaultScreen ); Pixmap pixmap = XCreatePixmap(x11_ctx->native_display,x11_ctx->native_window, TEX_W, TEX_H, xDefaultDepth); if(pixmap == None) { fprintf(stderr, "FAIL to XCreatePixmap \n"); goto finish; } PFNEGLLOCKSURFACEKHRPROC p_eglLockSurfaceKHR = (PFNEGLLOCKSURFACEKHRPROC)eglGetProcAddress( "eglLockSurfaceKHR" ); PFNEGLUNLOCKSURFACEKHRPROC p_eglUnlockSurfaceKHR = (PFNEGLUNLOCKSURFACEKHRPROC)eglGetProcAddress( "eglUnlockSurfaceKHR" ); if(!p_eglLockSurfaceKHR || !p_eglUnlockSurfaceKHR) { fprintf(stderr, "EGL_KHR_lock_surface is not supported \n"); goto finish; } /* Create eglPixmapSurface */ if(!create_lockable_pixmap_surface(egl_ctx, pixmap)) { fprintf(stderr, "FAIL to Create PixmapSurface \n"); goto finish; } /* Create eglImage and texture */ if(!create_egl_image_texture(pixmap, &image_texture, egl_ctx)) { fprintf(stderr, "FAIL to Create eglImage \n"); goto finish; } /* vertices, color, texture coordinate info */ static GLfloat vertices[] = { -1.0, 1.0, 0.0, 1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0}; static GLfloat colors[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; static GLfloat texcoord[] = {0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0}; EGLint lock_surface_attrib [] = {EGL_MAP_PRESERVE_PIXELS_KHR, EGL_FALSE, EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, EGL_NONE}; unsigned char* p_eglimg_data = NULL; if(!init_gles(vertices, colors, texcoord, gles_ctx)) { fprintf(stderr, "FAIL TO INIT GLES\n"); goto finish; } /* Query Lockable Surface infomation */ if(!eglMakeCurrent(egl_ctx->egl_display, egl_ctx->pixmap_sur, egl_ctx->pixmap_sur, egl_ctx->pixmap_ctx)) goto finish; if(!p_eglLockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur, lock_surface_attrib )) { p_eglUnlockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur ); if(!eglMakeCurrent(egl_ctx->egl_display, egl_ctx->wnd_sur, egl_ctx->wnd_sur, egl_ctx->wnd_ctx)) goto finish; if(!p_eglLockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur, lock_surface_attrib )) { fprintf(stderr, "FAIL to p_eglLockSurfaceKHR %x \n", eglGetError()); p_eglUnlockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur ); } } EGLint data[7]; eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_PITCH_KHR, &data[0]); eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_ORIGIN_KHR, &data[1]); eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_PIXEL_RED_OFFSET_KHR, &data[2]); eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR , &data[3]); eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR, &data[4]); eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR , &data[5]); fprintf(stderr, "eglSurface Infomation \n"); fprintf(stderr, " EGL_BITMAP_PITCH_KHR %d\n EGL_BITMAP_ORIGIN_KHR 0x%x\n EGL_BITMAP_PIXEL_RED_OFFSET_KHR %d\n EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR %d\n ", data[0], data[1], data[2], data[3]); fprintf(stderr, "EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR %d\n EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR %d\n", data[4], data[5]); if(is_supported(egl_ctx->egl_display, "EGL_KHR_lock_surface2")) { eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_PIXEL_SIZE_KHR , &data[6]); fprintf(stderr, " EGL_BITMAP_PIXEL_SIZE_KHR %d\n", data[6]); } if(!p_eglUnlockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur )) { fprintf(stderr, "FAIL to eglUnlockSurfaceKHR %x \n", eglGetError()); goto finish; } for(i=0; i<FRAME; i++) { /* MakeCurrent eglPixmapSurface */ if(!eglMakeCurrent(egl_ctx->egl_display, egl_ctx->pixmap_sur, egl_ctx->pixmap_sur, egl_ctx->pixmap_ctx)) goto finish; if(!p_eglLockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur, lock_surface_attrib )) { p_eglUnlockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur ); /* MakeCurrent eglWindowSurface */ if(!eglMakeCurrent(egl_ctx->egl_display, egl_ctx->wnd_sur, egl_ctx->wnd_sur, egl_ctx->wnd_ctx)) goto finish; if(!p_eglLockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur, lock_surface_attrib )) { fprintf(stderr, "FAIL to p_eglLockSurfaceKHR %x \n", eglGetError()); p_eglUnlockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur ); } } if(!eglQuerySurface(egl_ctx->egl_display, egl_ctx->pixmap_sur, EGL_BITMAP_POINTER_KHR, (EGLint *) &p_eglimg_data)) { fprintf(stderr, "FAIL to query surface %x \n", eglGetError()); p_eglUnlockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur ); goto finish; } if(p_eglimg_data == NULL) { fprintf(stderr, "eglQuerySurface return NULL for locksurface \n"); goto finish; } if(i%30 < 10) update_eglimg( p_eglimg_data, 'R', TEX_W, TEX_H, 4 ); else if(i%30 >= 10 && i%30 <20) update_eglimg( p_eglimg_data, 'G', TEX_W, TEX_H, 4 ); else update_eglimg( p_eglimg_data, 'B', TEX_W, TEX_H, 4 ); if(!p_eglUnlockSurfaceKHR( egl_ctx->egl_display, egl_ctx->pixmap_sur )) { fprintf(stderr, "FAIL to eglUnlockSurfaceKHR %x \n", eglGetError()); goto finish; } /* MakeCurrent eglWindowSurface */ if(!eglMakeCurrent(egl_ctx->egl_display, egl_ctx->wnd_sur, egl_ctx->wnd_sur, egl_ctx->wnd_ctx)) goto finish; /* Draw on to eglWindowSurface */ glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glViewport(move_x,move_y, RECT_W, RECT_H ); glBindTexture(GL_TEXTURE_2D, image_texture); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); eglSwapBuffers(egl_ctx->egl_display, egl_ctx->wnd_sur); if(direction_x == 1) move_x += SPEED; else move_x -= SPEED; if(direction_y == 1) move_y += SPEED; else move_y -= SPEED; if(move_x+RECT_W > x11_ctx->width || move_x < 0) direction_x = - direction_x; if(move_y+RECT_H > x11_ctx->height || move_y < 0) direction_y = - direction_y; if(!eglSwapBuffers(egl_ctx->egl_display, egl_ctx->wnd_sur)) goto finish; } destroy_egl_image_texture(&image_texture, egl_ctx); finish: /* Deinit gl */ deinit_gles(gles_ctx); /* Deinit egl */ deinit_egl(egl_ctx); /* Deinit native x11 */ deinit_x11_native(x11_ctx); if(x11_ctx) free(x11_ctx); if(egl_ctx) free(egl_ctx); if(gles_ctx) free(gles_ctx); return ret; }