static rfbBool InitializeTLS(void) { int i; if (rfbTLSInitialized) return TRUE; mutex_buf = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); if (mutex_buf == NULL) { rfbClientLog("Failed to initialized OpenSSL: memory.\n"); return (-1); } for (i = 0; i < CRYPTO_num_locks(); i++) pthread_mutex_init(&mutex_buf[i], NULL); CRYPTO_set_locking_callback(locking_function); CRYPTO_set_id_callback(id_function); CRYPTO_set_dynlock_create_callback(dyn_create_function); CRYPTO_set_dynlock_lock_callback(dyn_lock_function); CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); RAND_load_file("/dev/urandom", 1024); rfbClientLog("OpenSSL initialized.\n"); rfbTLSInitialized = TRUE; return TRUE; }
static rfbBool InitializeTLSSession(rfbClient* client, rfbBool anonTLS) { int ret; const char *p; if (client->tlsSession) return TRUE; if ((ret = gnutls_init((gnutls_session_t*)&client->tlsSession, GNUTLS_CLIENT)) < 0) { rfbClientLog("Failed to initialized TLS session: %s.\n", gnutls_strerror(ret)); return FALSE; } if ((ret = gnutls_priority_set_direct((gnutls_session_t)client->tlsSession, anonTLS ? rfbAnonTLSPriority : rfbTLSPriority, &p)) < 0) { rfbClientLog("Warning: Failed to set TLS priority: %s (%s).\n", gnutls_strerror(ret), p); } gnutls_transport_set_ptr((gnutls_session_t)client->tlsSession, (gnutls_transport_ptr_t)client); gnutls_transport_set_push_function((gnutls_session_t)client->tlsSession, PushTLS); gnutls_transport_set_pull_function((gnutls_session_t)client->tlsSession, PullTLS); rfbClientLog("TLS session initialized.\n"); return TRUE; }
static rfbBool HandshakeTLS(rfbClient* client) { int timeout = 15; int ret; while (timeout > 0 && (ret = gnutls_handshake((gnutls_session_t)client->tlsSession)) < 0) { if (!gnutls_error_is_fatal(ret)) { rfbClientLog("TLS handshake blocking.\n"); sleep(1); timeout--; continue; } rfbClientLog("TLS handshake failed: %s.\n", gnutls_strerror(ret)); FreeTLS(client); return FALSE; } if (timeout <= 0) { rfbClientLog("TLS handshake timeout.\n"); FreeTLS(client); return FALSE; } rfbClientLog("TLS handshake done.\n"); return TRUE; }
static rfbBool HandshakeTLS(rfbClient* client) { int timeout = 15; int ret; return TRUE; while (timeout > 0 && (ret = SSL_do_handshake(client->tlsSession)) < 0) { if (ret != -1) { rfbClientLog("TLS handshake blocking.\n"); sleep(1); timeout--; continue; } rfbClientLog("TLS handshake failed: -.\n"); FreeTLS(client); return FALSE; } if (timeout <= 0) { rfbClientLog("TLS handshake timeout.\n"); FreeTLS(client); return FALSE; } rfbClientLog("TLS handshake done.\n"); return TRUE; }
static void update(rfbClient* client,int x,int y,int w,int h) { clientData* cd=(clientData*)client->clientData; int maxDelta=0; #ifndef VERY_VERBOSE static const char* progress="|/-\\"; static int counter=0; if(++counter>sizeof(progress)) counter=0; fprintf(stderr,"%c\r",progress[counter]); #else rfbClientLog("Got update (encoding=%s): (%d,%d)-(%d,%d)\n", testEncodings[cd->encodingIndex].str, x,y,x+w,y+h); #endif /* only check if this was the last update */ if(x+w!=lastUpdateRect.x2 || y+h!=lastUpdateRect.y2) { #ifdef VERY_VERBOSE rfbClientLog("Waiting (%d!=%d or %d!=%d)\n", x+w,lastUpdateRect.x2,y+h,lastUpdateRect.y2); #endif return; } #ifdef LIBVNCSERVER_HAVE_LIBZ if(testEncodings[cd->encodingIndex].id==rfbEncodingTight) maxDelta=5; #endif updateStatistics(cd->encodingIndex, !doFramebuffersMatch(cd->server,client,maxDelta)); }
static void sc_do_screenshot(rfbClient* client, const char *filename) { screentoimage_init(); int rc = screentoimage_write(client, filename); if (rc == -1) { rfbClientLog("Failed to write screenshot\n"); } else { rfbClientLog("screenshot writed\n"); } screentoimage_finalize(); }
static rfbBool handleBackChannelMessage(rfbClient* client, rfbServerToClientMsg* message) { backChannelMsg msg; char* text; if(message->type != rfbBackChannel) return FALSE; rfbClientSetClientData(client, sendMessage, sendMessage); if(!ReadFromRFBServer(client, ((char*)&msg)+1, sizeof(msg)-1)) return TRUE; msg.size = rfbClientSwap32IfLE(msg.size); text = malloc(msg.size); if(!ReadFromRFBServer(client, text, msg.size)) { free(text); return TRUE; } rfbClientLog("got back channel message: %s\n", text); free(text); return TRUE; }
int WaitForMessage(rfbClient* client,unsigned int usecs) { fd_set fds; struct timeval timeout; int num; if (client->serverPort==-1) /* playing back vncrec file */ return 1; timeout.tv_sec=(usecs/1000000); timeout.tv_usec=(usecs%1000000); FD_ZERO(&fds); FD_SET(client->sock,&fds); num=select(client->sock+1, &fds, NULL, NULL, &timeout); if(num<0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientLog("Waiting for message failed: %d (%s)\n",errno,strerror(errno)); } return num; }
int WriteToTLS(rfbClient* client, char *buf, unsigned int n) { unsigned int offset = 0; ssize_t ret; while (offset < n) { ret = SSL_write (client->tlsSession, buf + offset, (size_t)(n-offset)); if (ret < 0) errno = ssl_errno (client->tlsSession, ret); if (ret == 0) continue; if (ret < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) continue; rfbClientLog("Error writing to TLS: -\n"); return -1; } offset += (unsigned int)ret; } return offset; }
static void* clientLoop(void* data) { rfbClient* client=(rfbClient*)data; clientData* cd=(clientData*)client->clientData; client->appData.encodingsString=strdup(testEncodings[cd->encodingIndex].str); sleep(1); rfbClientLog("Starting client (encoding %s, display %s)\n", testEncodings[cd->encodingIndex].str, cd->display); if(!rfbInitClient(client,NULL,NULL)) { rfbClientErr("Had problems starting client (encoding %s)\n", testEncodings[cd->encodingIndex].str); updateStatistics(cd->encodingIndex,TRUE); return NULL; } while(1) { if(WaitForMessage(client,50)>=0) if(!HandleRFBServerMessage(client)) break; } free(((clientData*)client->clientData)->display); free(client->clientData); if(client->frameBuffer) free(client->frameBuffer); rfbClientCleanup(client); return NULL; }
static rfbBool SetTLSAnonCredential(rfbClient* client) { gnutls_anon_client_credentials anonCred; int ret; if ((ret = gnutls_anon_allocate_client_credentials(&anonCred)) < 0 || (ret = gnutls_credentials_set((gnutls_session_t)client->tlsSession, GNUTLS_CRD_ANON, anonCred)) < 0) { FreeTLS(client); rfbClientLog("Failed to create anonymous credentials: %s", gnutls_strerror(ret)); return FALSE; } rfbClientLog("TLS anonymous credential created.\n"); return TRUE; }
static char *sc_get_password(rfbClient* client) { char *pw = getenv("VNCPASSWD"); if (!pw) { rfbClientLog("Please provide VNCPASSWD environment variable\n"); exit(1); } return strdup(pw); }
static rfbBool InitializeTLS(void) { int ret; if (rfbTLSInitialized) return TRUE; if ((ret = gnutls_global_init()) < 0 || (ret = gnutls_dh_params_init(&rfbDHParams)) < 0 || (ret = gnutls_dh_params_generate2(rfbDHParams, DH_BITS)) < 0) { rfbClientLog("Failed to initialized GnuTLS: %s.\n", gnutls_strerror(ret)); return FALSE; } rfbClientLog("GnuTLS initialized.\n"); rfbTLSInitialized = TRUE; return TRUE; }
static rfbBool HandleH264 (rfbClient* client, int rx, int ry, int rw, int rh) { rfbH264Header hdr; char *framedata; DebugLog(("Framebuffer update with H264 (x: %d, y: %d, w: %d, h: %d)\n", rx, ry, rw, rh)); /* First, read the frame size and allocate buffer to store the data */ if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbH264Header)) return FALSE; hdr.slice_type = rfbClientSwap32IfLE(hdr.slice_type); hdr.nBytes = rfbClientSwap32IfLE(hdr.nBytes); hdr.width = rfbClientSwap32IfLE(hdr.width); hdr.height = rfbClientSwap32IfLE(hdr.height); framedata = (char*) malloc(hdr.nBytes); /* Obtain frame data from the server */ DebugLog(("Reading %d bytes of frame data (type: %d)\n", hdr.nBytes, hdr.slice_type)); if (!ReadFromRFBServer(client, framedata, hdr.nBytes)) return FALSE; /* First make sure we have a large enough raw buffer to hold the * decompressed data. In practice, with a fixed BPP, fixed frame * buffer size and the first update containing the entire frame * buffer, this buffer allocation should only happen once, on the * first update. */ if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) { if ( client->raw_buffer != NULL ) { free( client->raw_buffer ); } client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 )); client->raw_buffer = (char*) malloc( client->raw_buffer_size ); rfbClientLog("Allocated raw buffer of %d bytes (%dx%dx%d BPP)\n", client->raw_buffer_size, rw, rh, BPP); } /* Decode frame if frame data was sent. Server only sends frame data for the first * framebuffer update message for a particular frame buffer contents. * If more than 1 rectangle is updated, the messages after the first one (with * the H.264 frame) have nBytes == 0. */ if (hdr.nBytes > 0) { DebugLog((" decoding %d bytes of H.264 data\n", hdr.nBytes)); h264_decode_frame(hdr.width, hdr.height, framedata, hdr.nBytes, hdr.slice_type); } DebugLog((" updating rectangle (%d, %d)-(%d, %d)\n", rx, ry, rw, rh)); put_updated_rectangle(client, rx, ry, rw, rh, hdr.width, hdr.height, hdr.nBytes != 0); free(framedata); return TRUE; }
void rfbClientCleanup(rfbClient* client) { #ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBJPEG int i; for ( i = 0; i < 4; i++ ) { if (client->zlibStreamActive[i] == TRUE ) { if (inflateEnd (&client->zlibStream[i]) != Z_OK && client->zlibStream[i].msg != NULL) rfbClientLog("inflateEnd: %s\n", client->zlibStream[i].msg); } } if ( client->decompStreamInited == TRUE ) { if (inflateEnd (&client->decompStream) != Z_OK && client->decompStream.msg != NULL) rfbClientLog("inflateEnd: %s\n", client->decompStream.msg ); } if (client->jpegSrcManager) free(client->jpegSrcManager); #endif #endif FreeTLS(client); while (client->clientData) { rfbClientData* next = client->clientData->next; free(client->clientData); client->clientData = next; } if (client->sock >= 0) close(client->sock); if (client->listenSock >= 0) close(client->listenSock); free(client->desktopName); free(client->serverHost); if (client->destHost) free(client->destHost); if (client->clientAuthSchemes) free(client->clientAuthSchemes); free(client); }
int WriteToTLS(rfbClient* client, char *buf, unsigned int n) { unsigned int offset = 0; ssize_t ret; if (client->LockWriteToTLS) { if (!client->LockWriteToTLS(client)) { rfbClientLog("Callback to get lock in WriteToTLS() failed\n"); return -1; } } while (offset < n) { ret = gnutls_record_send((gnutls_session_t)client->tlsSession, buf+offset, (size_t)(n-offset)); if (ret == 0) continue; if (ret < 0) { if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) continue; rfbClientLog("Error writing to TLS: %s.\n", gnutls_strerror(ret)); if (client->UnlockWriteToTLS) { if (!client->UnlockWriteToTLS(client)) rfbClientLog("Callback to unlock WriteToTLS() failed\n"); } return -1; } offset += (unsigned int)ret; } if (client->UnlockWriteToTLS) { if (!client->UnlockWriteToTLS(client)) { rfbClientLog("Callback to unlock WriteToTLS() failed\n"); return -1; } } return offset; }
rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n) { fd_set fds; int i = 0; int j; if (client->serverPort==-1) return TRUE; /* vncrec playing */ #ifdef LIBVNCSERVER_WITH_CLIENT_TLS if (client->tlsSession) { /* WriteToTLS() will guarantee either everything is written, or error/eof returns */ i = WriteToTLS(client, buf, n); if (i <= 0) return FALSE; return TRUE; } #endif while (i < n) { j = write(client->sock, buf + i, (n - i)); if (j <= 0) { if (j < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || #ifdef LIBVNCSERVER_ENOENT_WORKAROUND errno == ENOENT || #endif errno == EAGAIN) { FD_ZERO(&fds); FD_SET(client->sock,&fds); if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { rfbClientErr("select\n"); return FALSE; } j = 0; } else { rfbClientErr("write\n"); return FALSE; } } else { rfbClientLog("write failed\n"); return FALSE; } } i += j; } return TRUE; }
static rfbBool resize_func(rfbClient* client) { static rfbBool first=TRUE; if(!first) { rfbClientLog("I don't know yet how to change resolutions!\n"); exit(1); } signal(SIGINT,signal_handler); int width=client->width; int height=client->height; int depth=client->format.bitsPerPixel; client->updateRect.x = client->updateRect.y = 0; client->updateRect.w = width; client->updateRect.h = height; client->frameBuffer = (uint8_t*)malloc(width*height*depth); memset(client->frameBuffer, 0, width*height*depth); rfbClientLog("Allocate %d bytes: %d x %d x %d\n", width*height*depth, width,height,depth); return TRUE; }
static void sendMessage(rfbClient* client, char* text) { backChannelMsg msg; uint32_t length = strlen(text)+1; msg.type = rfbBackChannel; msg.size = rfbClientSwap32IfLE(length); if(!WriteToRFBServer(client, (char*)&msg, sizeof(msg)) || !WriteToRFBServer(client, text, length)) { rfbClientLog("enableBackChannel: write error (%d: %s)", errno, strerror(errno)); } }
void rfbClientCleanup(rfbClient* client) { #ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBJPEG struct rfbClientPrivate *priv; int i; priv = RFB_CLIENT_PRIV(client); for ( i = 0; i < 4; i++ ) { if (priv->zlibStreamActive[i] == TRUE ) { if (inflateEnd (&priv->zlibStream[i]) != Z_OK && priv->zlibStream[i].msg != NULL) rfbClientLog("inflateEnd: %s\n", priv->zlibStream[i].msg); } } if ( priv->decompStreamInited == TRUE ) { if (inflateEnd (&priv->decompStream) != Z_OK && priv->decompStream.msg != NULL) rfbClientLog("inflateEnd: %s\n", priv->decompStream.msg ); } if (priv->jpegSrcManager) free(priv->jpegSrcManager); #endif #endif FreeTLS(client); if (client->sock >= 0) close(client->sock); if (client->listenSock >= 0) close(client->listenSock); free(client->desktopName); free(client->serverHost); if (client->destHost) free(client->destHost); if (client->clientAuthSchemes) free(client->clientAuthSchemes); free(client); }
static gnutls_certificate_credentials_t CreateX509CertCredential(rfbCredential *cred) { gnutls_certificate_credentials_t x509_cred; int ret; if (!cred->x509Credential.x509CACertFile) { rfbClientLog("No CA certificate provided.\n"); return NULL; } if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) { rfbClientLog("Cannot allocate credentials: %s.\n", gnutls_strerror(ret)); return NULL; } if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, cred->x509Credential.x509CACertFile, GNUTLS_X509_FMT_PEM)) < 0) { rfbClientLog("Cannot load CA credentials: %s.\n", gnutls_strerror(ret)); gnutls_certificate_free_credentials (x509_cred); return NULL; } if (cred->x509Credential.x509ClientCertFile && cred->x509Credential.x509ClientKeyFile) { if ((ret = gnutls_certificate_set_x509_key_file(x509_cred, cred->x509Credential.x509ClientCertFile, cred->x509Credential.x509ClientKeyFile, GNUTLS_X509_FMT_PEM)) < 0) { rfbClientLog("Cannot load client certificate or key: %s.\n", gnutls_strerror(ret)); gnutls_certificate_free_credentials (x509_cred); return NULL; } } else { rfbClientLog("No client certificate or key provided.\n"); } if (cred->x509Credential.x509CACrlFile) { if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, cred->x509Credential.x509CACrlFile, GNUTLS_X509_FMT_PEM)) < 0) { rfbClientLog("Cannot load CRL: %s.\n", gnutls_strerror(ret)); gnutls_certificate_free_credentials (x509_cred); return NULL; } } else { rfbClientLog("No CRL provided.\n"); } gnutls_certificate_set_dh_params (x509_cred, rfbDHParams); return x509_cred; }
int WaitForMessage(rfbClient* client,unsigned int usecs) { fd_set fds; struct timeval timeout; int num; int maxfd; if (client->serverPort==-1) { /* playing back vncrec file */ client->serverMsg = TRUE; return 1; } client->serverMsg = client->serverMsgMulticast = FALSE; timeout.tv_sec=(usecs/1000000); timeout.tv_usec=(usecs%1000000); FD_ZERO(&fds); FD_SET(client->sock,&fds); maxfd = client->sock; if(client->multicastSock >= 0 && !client->multicastDisabled) { FD_SET(client->multicastSock,&fds); maxfd = max(client->sock, client->multicastSock); } num=select(maxfd+1, &fds, NULL, NULL, &timeout); if(num<0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientLog("Waiting for message failed: %d (%s)\n",errno,strerror(errno)); return num; } if(FD_ISSET(client->sock, &fds)) client->serverMsg = TRUE; if(client->multicastSock >= 0 && FD_ISSET(client->multicastSock, &fds)) client->serverMsgMulticast = TRUE; if(client->multicastPacketBuf && ghpringbuf_count(client->multicastPacketBuf)) { client->serverMsgMulticast = TRUE; ++num; } return num; }
static rfbBool InitializeTLSSession(rfbClient* client, rfbBool anonTLS) { int ret; if (client->tlsSession) return TRUE; client->tlsSession = open_ssl_connection (client, client->sock, anonTLS); if (!client->tlsSession) return FALSE; rfbClientLog("TLS session initialized.\n"); return TRUE; }
int ReadFromTLS(rfbClient* client, char *out, unsigned int n) { ssize_t ret; ret = gnutls_record_recv((gnutls_session_t)client->tlsSession, out, n); if (ret >= 0) return ret; if (ret == GNUTLS_E_REHANDSHAKE || ret == GNUTLS_E_AGAIN) { errno = EAGAIN; } else { rfbClientLog("Error reading from TLS: %s.\n", gnutls_strerror(ret)); errno = EINTR; } return -1; }
static void SaveFramebufferAsPPM(rfbClient* client, int x, int y, int w, int h) { static time_t t=0,t1; FILE* f; int i,j; rfbPixelFormat* pf=&client->format; int bpp=pf->bitsPerPixel/8; int row_stride=client->width*bpp; /* save one picture only if the last is older than 2 seconds */ t1=time(NULL); if(t1-t>2) t=t1; else return; /* assert bpp=4 */ if(bpp!=4 && bpp!=2) { rfbClientLog("bpp = %d (!=4)\n",bpp); return; } f=fopen("framebuffer.ppm","wb"); if(!f) { rfbClientErr("Could not open framebuffer.ppm\n"); return; } fprintf(f,"P6\n# %s\n%d %d\n255\n",client->desktopName,client->width,client->height); for(j=0;j<client->height*row_stride;j+=row_stride) for(i=0;i<client->width*bpp;i+=bpp) { unsigned char* p=client->frameBuffer+j+i; unsigned int v; if(bpp==4) v=*(unsigned int*)p; else if(bpp==2) v=*(unsigned short*)p; else v=*(unsigned char*)p; fputc((v>>pf->redShift)*256/(pf->redMax+1),f); fputc((v>>pf->greenShift)*256/(pf->greenMax+1),f); fputc((v>>pf->blueShift)*256/(pf->blueMax+1),f); } fclose(f); }
int ReadFromTLS(rfbClient* client, char *out, unsigned int n) { ssize_t ret; ret = SSL_read (client->tlsSession, out, n); if (ret >= 0) return ret; else { errno = ssl_errno (client->tlsSession, ret); if (errno != EAGAIN) { rfbClientLog("Error reading from TLS: -.\n"); } } return -1; }
int main(int argc, char **argv) { const char *filename = getenv("VNCSCREENSHOT_FILENAME"); if (!filename) { rfbClientLog("Please provide VNCSCREENSHOT_FILENAME environment variable\n", argv[0]); return 1; } rfbClient* client = rfbGetClient(8,3,4); client->GetPassword = sc_get_password; client->GotFrameBufferUpdate = sc_got_frame_buffer_update; if (!rfbInitClient(client,&argc,argv)) return 2; time_t start = time(NULL); int got_error = 0; while (time(NULL) - start < 2) { int rc = WaitForMessage(client, 1000); if (rc < 0) { got_error = 1; break; } if (rc == 0) continue; if(!HandleRFBServerMessage(client)) { got_error = 1; break; } } if (!got_error) { sc_do_screenshot(client, filename); } rfbClientCleanup(client); exit(got_error ? 3 : 0); }
void PrintInHex(char *buf, int len) { int i, j; char c, str[17]; str[16] = 0; rfbClientLog("ReadExact: "); for (i = 0; i < len; i++) { if ((i % 16 == 0) && (i != 0)) { rfbClientLog(" "); } c = buf[i]; str[i % 16] = (((c > 31) && (c < 127)) ? c : '.'); rfbClientLog("%02x ",(unsigned char)c); if ((i % 4) == 3) rfbClientLog(" "); if ((i % 16) == 15) { rfbClientLog("%s\n",str); } } if ((i % 16) != 0) { for (j = i % 16; j < 16; j++) { rfbClientLog(" "); if ((j % 4) == 3) rfbClientLog(" "); } str[i % 16] = 0; rfbClientLog("%s\n",str); } fflush(stderr); }
rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n) { fd_set fds; int i = 0; int j; if (client->serverPort==-1) return TRUE; /* vncrec playing */ while (i < n) { j = write(client->sock, buf + i, (n - i)); if (j <= 0) { if (j < 0) { if (errno == EWOULDBLOCK || #ifdef LIBVNCSERVER_ENOENT_WORKAROUND errno == ENOENT || #endif errno == EAGAIN) { FD_ZERO(&fds); FD_SET(client->sock,&fds); if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { rfbClientErr("select\n"); return FALSE; } j = 0; } else { rfbClientErr("write\n"); return FALSE; } } else { rfbClientLog("write failed\n"); return FALSE; } } i += j; } return TRUE; }
static void h264_cleanup_decoder() { VAStatus va_status; rfbClientLog("%s()\n", __FUNCTION__); if (va_surface_id[0] != VA_INVALID_ID) { va_status = vaDestroySurfaces(va_dpy, &va_surface_id[0], SURFACE_NUM); CHECK_VASTATUS(va_status, "vaDestroySurfaces"); } if (va_context_id) { va_status = vaDestroyContext(va_dpy, va_context_id); CHECK_VASTATUS(va_status, "vaDestroyContext"); va_context_id = 0; } num_frames = 0; sid = 0; frame_id = 0; field_order_count = 0; }