lqtplay.c
来自「这个库实现了录象功能」· C语言 代码 · 共 1,866 行 · 第 1/4 页
C
1,866 行
fprintf(stderr, _("height :%i\n"), lqt_qtvr_get_height(qt)); fprintf(stderr, _("depth :%i\n"), lqt_qtvr_get_depth(qt)); if (qt_isqtvr == QTVR_PAN) { oh_width = lqt_qtvr_get_height(qt) * qtvr_dwidth / (float)qtvr_dheight; if (lqt_qtvr_get_panotype(qt) == QTVR_PANO_VERT) { oh_width = floor(oh_width / (float)quicktime_video_height(qt, 0) + 1) * quicktime_video_height(qt, 0); } else if (lqt_qtvr_get_panotype(qt) == QTVR_PANO_HORZ) { oh_width = floor(oh_width / (float)quicktime_video_width(qt, 0) + 1) * quicktime_video_width(qt, 0); } fprintf(stderr, _("oh_width verz :%i\n"),oh_width); } } /* sanity checks */ if (!quicktime_has_video(qt)) { fprintf(stderr,_("WARNING: no video stream\n")); } else if (!quicktime_supported_video(qt,0)) { fprintf(stderr,_("WARNING: unsupported video codec\n")); } else { qt_hasvideo = 1; qt_width = quicktime_video_width(qt,0); qt_height = quicktime_video_height(qt,0); qt_timescale = lqt_video_time_scale(qt,0);#ifdef DUMP_TIMECODES has_timecodes = lqt_has_timecode_track(qt, 0, &timecode_flags, &timecode_rate);#endif fprintf(stderr, _("Timescale: %d\n"), qt_timescale); } if (!quicktime_has_audio(qt)) { fprintf(stderr,_("WARNING: no audio stream\n")); } else if (!quicktime_supported_audio(qt,0)) { fprintf(stderr,_("WARNING: unsupported audio codec\n")); } else { qt_hasaudio = 1; qt_channels = quicktime_track_channels(qt,0); qt_sample_rate = quicktime_sample_rate(qt,0); if (use_alsa == 1) { if (-1 == alsa_init(adev_name, qt_channels, qt_sample_rate)) { qt_hasaudio = 0;} } else { if (-1 == oss_init("/dev/dsp", qt_channels, qt_sample_rate)) qt_hasaudio = 0; } } if (0 == qt_hasvideo && 0 == qt_hasaudio) { fprintf(stderr,_("ERROR: no playable stream found\n")); exit(1); }}static void qt_cleanup() { if(qt) quicktime_close(qt); }static int qt_init_video(void){ int i; /* init */ qt_rows = malloc(qt_height * sizeof(char*)); if (qt_isqtvr == QTVR_PAN) { qt_frame_row = malloc(qtvr_dwidth * 3); qt_frame = malloc(qtvr_dwidth * qtvr_dheight * 3); if (lqt_qtvr_get_panotype(qt) == QTVR_PANO_VERT) { qt_frame_tmp[0] = malloc(sizeof(int) * qtvr_dwidth * qt_width); qt_frame_tmp[1] = malloc(sizeof(int) * qtvr_dwidth * qt_width); } else { qt_frame_tmp[0] = malloc(sizeof(int) * qtvr_dwidth * qt_height); qt_frame_tmp[1] = malloc(sizeof(int) * qtvr_dwidth * qt_height); } qt_panorama_buffer = malloc((lqt_qtvr_get_width(qt)+oh_width)* lqt_qtvr_get_height(qt)* 3); } else qt_frame = malloc(qt_width * qt_height * 4); qt_gc = XCreateGC(dpy,XtWindow(simple),0,NULL); switch (qt_cmodel) { case BC_RGB888:#ifdef HAVE_GL fprintf(stderr,_("INFO: using BC_RGB888 + %s\n"), use_gl ? _("OpenGL") : _("plain X11"));#else fprintf(stderr,_("INFO: using BC_RGB888 + %s\n"), _("plain X11"));#endif if (qt_isqtvr == QTVR_PAN) { qt_ximage = x11_create_ximage(dpy,qtvr_dwidth,qtvr_dheight); } else qt_ximage = x11_create_ximage(dpy,qt_width,qt_height); for (i = 0; i < qt_height; i++) qt_rows[i] = qt_frame + qt_width * 3 * i; break; case BC_YUV422: fprintf(stderr,_("INFO: using BC_YUV422 + Xvideo extention\n")); qt_xvimage = xv_create_ximage(dpy,qt_width,qt_height, xv_port,FOURCC_YUV2); for (i = 0; i < qt_height; i++) qt_rows[i] = (uint8_t*)(qt_xvimage->data + qt_width * 2 * i); lqt_set_row_span(qt,0,qt_xvimage->pitches[0]); break; case BC_YUV420P: if(xv_have_YV12) { fprintf(stderr, _("INFO: using BC_YUV420P + Xvideo extention (YV12)\n")); qt_xvimage = xv_create_ximage(dpy,qt_width,qt_height, xv_port,FOURCC_YV12); qt_rows[0] = (uint8_t*)(qt_xvimage->data + qt_xvimage->offsets[0]); qt_rows[1] = (uint8_t*)(qt_xvimage->data + qt_xvimage->offsets[2]); qt_rows[2] = (uint8_t*)(qt_xvimage->data + qt_xvimage->offsets[1]); } else if(xv_have_I420) { fprintf(stderr, _("INFO: using BC_YUV420P + Xvideo extention (I420)\n")); qt_xvimage = xv_create_ximage(dpy,qt_width,qt_height, xv_port,FOURCC_I420); qt_rows[0] = (uint8_t*)(qt_xvimage->data + qt_xvimage->offsets[0]); qt_rows[1] = (uint8_t*)(qt_xvimage->data + qt_xvimage->offsets[1]); qt_rows[2] = (uint8_t*)(qt_xvimage->data + qt_xvimage->offsets[2]); } lqt_set_row_span(qt,0,qt_xvimage->pitches[0]); lqt_set_row_span_uv(qt,0,qt_xvimage->pitches[1]); break; default: fprintf(stderr,_("ERROR: internal error at %s:%d\n"), __FILE__,__LINE__); exit(1); } if (qt_isqtvr) { /* has to be done here to set initial pov */ // look into this quicktime_set_video_position(qt, lqt_qtvr_get_initial_position(qt),0); /*XSetInputFocus(dpy, XtWindow(simple), RevertToPointerRoot, CurrentTime); */ if (qt_isqtvr == QTVR_PAN) { float dist; int oh_frames; int i, i2, l, j, j2, k; float x, y; int pano_width = lqt_qtvr_get_width(qt); int pano_height = lqt_qtvr_get_height(qt); oh_frames = oh_width/((lqt_qtvr_get_panotype(qt) == QTVR_PANO_HORZ)?qt_width:qt_height); for (i = 0; i < lqt_qtvr_get_columns(qt) + oh_frames; i++) { /* set position in video file */ /* if position larger than panorama, start from the beginning (overhead)*/ quicktime_set_video_position(qt, (i>=lqt_qtvr_get_columns(qt))?i-lqt_qtvr_get_columns(qt):i, 0); /* decode a frame */ lqt_decode_video(qt, qt_rows, 0); if (lqt_qtvr_get_panotype(qt) == QTVR_PANO_VERT) { long buffer_size; buffer_size = (pano_width + oh_width) * qt_width * 3; /* set position in the output buffer */ /* to the upper left corner of the desired frame */ j = i * qt_height * 3; /* put frame, rotated into buffer */ /* TODO: do this slightly less ass backwards */ for (k = 0; k < qt_width; k++) { for (l = qt_height - 1; l >= 0; l--) { qt_panorama_buffer[buffer_size - j + 0] = qt_frame[((qt_height - l) * qt_width - k) * 3 + 0]; qt_panorama_buffer[buffer_size - j + 1] = qt_frame[((qt_height - l) * qt_width - k) * 3 + 1]; qt_panorama_buffer[buffer_size - j + 2] = qt_frame[((qt_height - l) * qt_width - k) * 3 + 2]; j+=3; } j += (pano_width + oh_width - qt_height) * 3; } } else if (lqt_qtvr_get_panotype(qt) == QTVR_PANO_HORZ) { int row_offset; /* put frame into buffer at offset j */ j = i * qt_width; for (k = 0; k < qt_height; k++) { row_offset = k * (pano_width + oh_width) + j; for (l = 0; l < qt_width; l++) { qt_panorama_buffer[(row_offset + l) * 3 ] = qt_frame[(k * qt_width + l) * 3 ]; qt_panorama_buffer[(row_offset + l) * 3 + 1] = qt_frame[(k * qt_width + l) * 3 + 1]; qt_panorama_buffer[(row_offset + l) * 3 + 2] = qt_frame[(k * qt_width + l) * 3 + 2]; } } } } // "precalc" // default "zoom" dist = lqt_qtvr_get_width(qt)/(2*M_PI); for (j = 0; j < pano_height; j++) { for (i=0; i < qtvr_dwidth; i++) { x = i - (qtvr_dwidth/2); y = j - (pano_height/2); i2 = (qtvr_dwidth / 2) + dist * atan(x / dist); j2 = (pano_height / 2) + (dist * y) / sqrt(dist * dist + x * x); //j2 = j; i2 = i; if (i2 < 0 || i2 > qtvr_dwidth || j2 < 0 || j2 > pano_height) { continue; } k = (j * qtvr_dwidth + i); qt_frame_tmp[0][k] = i2; //x qt_frame_tmp[1][k] = j2; //y } } } } return 0;}static int qt_frame_decode(void) { int i, j, k1, k2, x2, x, y, i2; int pano_width = lqt_qtvr_get_width(qt); int pano_height = lqt_qtvr_get_height(qt);#ifdef DUMP_TIMECODES uint32_t timecode;#endif if (qt_isqtvr == QTVR_OBJ) { /* sanity check and decode */ if (quicktime_video_position(qt, 0) >= 0 && quicktime_video_position(qt, 0) < quicktime_video_length(qt,0)) lqt_decode_video(qt, qt_rows, 0); // quicktime_decode_scaled(qt,0,0,qt_width,qt_height,qt_width,qt_height, // qt_cmodel,qt_rows,0); } else if (qt_isqtvr == QTVR_PAN) { float qdist = pow(pano_width / (2 * M_PI), 2); int tilt = ypos + qtvr_dheight / 2 - pano_height / 2; int tmp_row_offset; float hofac, hofac2; hofac = qtvr_dheight * (qtvr_dheight - pano_height) / (-12 * qdist); for (j = 0; j < qtvr_dheight; j++) { tmp_row_offset = (ypos + j) * qtvr_dwidth; for (i = 0; i < qtvr_dwidth; i++) { k2 = i * 3; k1 = (qt_frame_tmp[1][tmp_row_offset + i] * (pano_width + oh_width) + qt_frame_tmp[0][tmp_row_offset + i] + xpos) * 3; qt_frame_row[k2] = qt_panorama_buffer[k1]; qt_frame_row[k2 + 1] = qt_panorama_buffer[k1 + 1]; qt_frame_row[k2 + 2] = qt_panorama_buffer[k1 + 2]; } // Perspective Correction // probably wrong y = j - (qtvr_dheight/2); hofac2 = (((y * tilt) / (qdist * 3)) + 1 - hofac); for (i=0; i < qtvr_dwidth; i++) { x = i - (qtvr_dwidth / 2); x2 = x * hofac2; i2 = (qtvr_dwidth / 2) + x2; k2 = (j * qtvr_dwidth + i) * 3; k1 = i2 * 3; qt_frame[k2] = qt_frame_row[k1]; qt_frame[k2 + 1] = qt_frame_row[k1 + 1]; qt_frame[k2 + 2] = qt_frame_row[k1 + 2]; } } } else { if (quicktime_video_position(qt,0) >= quicktime_video_length(qt,0)) return -1; if (qt_drop) { qt_droptotal += qt_drop; fprintf(stderr,_("dropped %d frame(s)\r"),qt_droptotal); for (i = 0; i < qt_drop; i++) quicktime_read_frame(qt,qt_frame,0); qt_drop = 0; } qt_frame_time = lqt_frame_time(qt, 0);#ifdef DUMP_TIMECODES if(lqt_read_timecode(qt, 0, &timecode)) dump_timecode(qt, 0, timecode);#endif lqt_decode_video(qt, qt_rows, 0); } return 0; }static int qt_frame_blit(void){ switch (qt_cmodel) { case BC_RGB888:#ifdef HAVE_GL if (use_gl) { if (qt_isqtvr == QTVR_PAN) { gl_blit(simple,qt_frame,qtvr_dwidth,qtvr_dheight,swidth,sheight); } else gl_blit(simple,qt_frame,qt_width,qt_height,swidth,sheight); } else#endif // HAVE_GL { switch (pixmap_bytes) { case 2: if (qt_isqtvr == QTVR_PAN) { rgb_to_lut2((uint8_t*)(qt_ximage->data),qt_frame,qtvr_dwidth*qtvr_dheight); } else rgb_to_lut2((uint8_t*)(qt_ximage->data),qt_frame,qt_width*qt_height); break; case 4: if (qt_isqtvr == QTVR_PAN) { rgb_to_lut4((uint8_t*)(qt_ximage->data),qt_frame,qtvr_dwidth*qtvr_dheight); } else rgb_to_lut4((uint8_t*)(qt_ximage->data),qt_frame,qt_width*qt_height); break; } if (qt_isqtvr == QTVR_PAN) { x11_blit(XtWindow(simple),qt_gc,qt_ximage,qtvr_dwidth,qtvr_dheight); } else x11_blit(XtWindow(simple),qt_gc,qt_ximage,qt_width,qt_height); } break; case BC_YUV422: case BC_YUV420P: xv_blit(XtWindow(simple),qt_gc,qt_xvimage, qt_width,qt_height,swidth,sheight); break; default: fprintf(stderr,_("ERROR: internal error at %s:%d\n"), __FILE__,__LINE__); exit(1); } return 0;}static void qt_frame_delay(struct timeval *start, struct timeval *wait){ struct timeval now; long msec; gettimeofday(&now,NULL); /* Get the now - start (->negative value) */ msec = (start->tv_sec - now.tv_sec) * 1000; msec += (start->tv_usec - now.tv_usec) / 1000; if (qt_hasaudio && oss_sr && oss_hr) { /* cheap trick to make a/v sync ... */ msec = (long long)msec * oss_hr / oss_sr; } msec += (qt_frame_time * 1000) / qt_timescale; if (msec < 0) { qt_drop = -msec * quicktime_frame_rate(qt,0) / 1000; wait->tv_sec = 0; wait->tv_usec = 0; } else { wait->tv_sec = msec / 1000; wait->tv_usec = (msec % 1000) * 1000; }}/* Decode at most AUDIO_BLOCK_SIZE samples and interleave them into the qt_audio array. Return the real number of decoded samples */static int decode_audio() { int i, j; int samples_decoded; long last_pos = lqt_last_audio_position(qt, 0); if(!qt_audio) { /* Initialize */ if(qt_channels > 1) { qt_audion = malloc(qt_channels * sizeof(*qt_audion)); for(i = 0; i < qt_channels; i++) { qt_audion[i] = calloc(AUDIO_BLOCK_SIZE, sizeof(*(qt_audion[i]))); } } qt_audio = calloc(AUDIO_BLOCK_SIZE*qt_channels, sizeof(*qt_audio)); } if(qt_channels > 1) { lqt_decode_audio_track(qt, qt_audion, (float**)0, AUDIO_BLOCK_SIZE, 0); samples_decoded = lqt_last_audio_position(qt, 0) - last_pos; /* Interleave */ for (i = 0; i < samples_decoded; i++) { for(j = 0; j < qt_channels; j++) { qt_audio[qt_channels*i+j] = qt_audion[j][i]; } } } else { lqt_decode_audio_track(qt, &qt_audio, (float**)0, AUDIO_BLOCK_SIZE, 0); samples_decoded = lqt_last_audio_position(qt, 0) - last_pos; } total_samples_decoded += samples_decoded; qt_audio_samples_in_buffer = samples_decoded; qt_audio_ptr = qt_audio; if(samples_decoded < AUDIO_BLOCK_SIZE) { fprintf(stderr, _("Audio track finished (got %d samples, wanted %d)\n"), samples_decoded, AUDIO_BLOCK_SIZE); qt_audio_eof = 1; } return samples_decoded; }//static int runcount;static int qt_alsa_audio_write(){#ifdef HAVE_ALSA int done = 0; int ret = 0; while(!done) { /* Decode new audio samples */ if(!qt_audio_samples_in_buffer) decode_audio(AUDIO_BLOCK_SIZE); ret = snd_pcm_writei(pcm_handle, (void *)(qt_audio_ptr), qt_audio_samples_in_buffer); if (ret == -EAGAIN) { ret = 0; done = 1; // snd_pcm_wait(pcm_handle, 1000); } else if (ret == -EPIPE) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?