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 + -
显示快捷键?