Beispiel #1
0
static int
granulepos_test_encode (int frequency, int auto_p)
{
  theora_info ti;
  theora_state th;
  int result;
  int frame, tframe, keyframe, keydist;
  int shift;
  double rate, ttime;
  yuv_buffer yuv;
  unsigned char *framedata;
  ogg_packet op;
  long long int last_granule = -1;

/*  INFO ("+ Initializing theora_info struct"); */
  theora_info_init (&ti);

  ti.width = 32;
  ti.height = 32;
  ti.frame_width = ti.width;
  ti.frame_height = ti.frame_height;
  ti.offset_x = 0;
  ti.offset_y = 0;
  ti.fps_numerator = 16;
  ti.fps_denominator = 1;
  ti.aspect_numerator = 1;
  ti.aspect_denominator = 1;
  ti.colorspace = OC_CS_UNSPECIFIED;
  ti.pixelformat = OC_PF_420;
  ti.target_bitrate = 0;
  ti.quality = 16;

  ti.dropframes_p = 0;
  ti.quick_p = 1;

  /* check variations of automatic or forced keyframe choice */
  ti.keyframe_auto_p = auto_p;
  /* check with variations of the maximum gap */
  ti.keyframe_frequency = frequency;
  ti.keyframe_frequency_force = frequency;

  ti.keyframe_data_target_bitrate = ti.target_bitrate * 1.5;
  ti.keyframe_auto_threshold = 80;
  ti.keyframe_mindistance = MIN(8, frequency);
  ti.noise_sensitivity = 1;

/*  INFO ("+ Initializing theora_state for encoding"); */
  result = theora_encode_init (&th, &ti);
  if (result == OC_DISABLED) {
    INFO ("+ Clearing theora_state");
    theora_clear (&th);
  } else if (result < 0) {
    FAIL ("negative return code initializing encoder");
  }

/*  INFO ("+ Setting up dummy 4:2:0 frame data"); */
  framedata = calloc(ti.height, ti.width);
  yuv.y_width = ti.width;
  yuv.y_height = ti.height;
  yuv.y_stride = ti.width;
  yuv.y = framedata;
  yuv.uv_width = ti.width / 2;
  yuv.uv_height = ti.width / 2;
  yuv.uv_stride = ti.width;
  yuv.u = framedata;
  yuv.v = framedata;

  INFO ("+ Checking granulepos generation");
  shift = theora_granule_shift(&ti);
  rate = (double)ti.fps_denominator/ti.fps_numerator;
  for (frame = 0; frame < frequency * 2 + 1; frame++) {
    result = theora_encode_YUVin (&th, &yuv);
    if (result < 0) {
      printf("theora_encode_YUVin() returned %d\n", result);
      FAIL ("negative error code submitting frame for compression");
    }
    theora_encode_packetout (&th, frame >= frequency * 2, &op);
    if ((long long int)op.granulepos < last_granule)
      FAIL ("encoder returned a decreasing granulepos value");
    last_granule = op.granulepos;
    keyframe = op.granulepos >> shift;
    keydist = op.granulepos - (keyframe << shift);
    tframe = theora_granule_frame (&th, op.granulepos);
    ttime = theora_granule_time(&th, op.granulepos);
#if DEBUG
    printf("++ frame %d granulepos %lld %d:%d %d %.3lfs\n", 
	frame, (long long int)op.granulepos, keyframe, keydist,
	tframe, theora_granule_time (&th, op.granulepos));
#endif
    if ((keyframe + keydist) != frame + 1)
      FAIL ("encoder granulepos does not map to the correct frame number");
    if (tframe != frame)
      FAIL ("theora_granule_frame returned incorrect results");
    if (fabs(rate*(frame+1) - ttime) > 1.0e-6)
      FAIL ("theora_granule_time returned incorrect results");
  }

  /* clean up */
/*  INFO ("+ Freeing dummy frame data"); */
  free (framedata);

/*  INFO ("+ Clearing theora_info struct"); */
  theora_info_clear (&ti);

/*  INFO ("+ Clearing theora_state"); */
  theora_clear (&th);

  return 0;
}
Beispiel #2
0
static int OGV_LoadVideoFrame(cinematic_t *cin)
{
	int        r = 0;
	ogg_packet op;

	memset(&op, 0, sizeof(op));

	while (!r && (ogg_stream_packetout(&g_ogm->os_video, &op)))
	{
		ogg_int64_t th_frame;

		theora_decode_packetin(&g_ogm->th_state, &op);

		th_frame = theora_granule_frame(&g_ogm->th_state, g_ogm->th_state.granulepos);

		if ((g_ogm->VFrameCount < th_frame && th_frame >= OGV_NextNeededVFrame(cin)) || !cin->frameBuffer[0])
		{
			if (theora_decode_YUVout(&g_ogm->th_state, &g_ogm->th_yuvbuffer))
			{
				continue;
			}

			if (cin->frameWidth != g_ogm->th_info.width || cin->frameHeight != g_ogm->th_info.height)
			{
				cin->frameWidth  = g_ogm->th_info.width;
				cin->frameHeight = g_ogm->th_info.height;
				Com_DPrintf("Theora new resolution %dx%d\n", cin->frameWidth, cin->frameHeight);
			}

			if (cin->frameBufferSize < g_ogm->th_info.width * g_ogm->th_info.height)
			{

				cin->frameBufferSize = g_ogm->th_info.width * g_ogm->th_info.height;

				/* Free old output buffer */
				if (cin->frameBuffer[0])
				{
					Com_Dealloc(cin->frameBuffer[0]);
					cin->frameBuffer[0] = NULL;
				}

				/* Allocate the new buffer */
				cin->frameBuffer[0] = (unsigned char *)Com_Allocate(cin->frameBufferSize * 4);
				if (cin->frameBuffer[0] == NULL)
				{
					cin->frameBufferSize = 0;
					r                    = -2;
					break;
				}
			}

			if (OGV_yuv_to_rgb24(&g_ogm->th_yuvbuffer, &g_ogm->th_info, (unsigned int *) cin->frameBuffer[0]))
			{
				r                  = 1;
				g_ogm->VFrameCount = th_frame;
			}
			else
			{
				r = -1;
			}
		}
	}

	return r;
}
static int loadVideoFrameTheora(void) {
	int r = 0;
	ogg_packet	op;

	memset(&op,0,sizeof(op));

	while( !r && (ogg_stream_packetout(&g_ogm.os_video,&op)) ) {
		ogg_int64_t th_frame;
		theora_decode_packetin(&g_ogm.th_state, &op);

		th_frame = theora_granule_frame(&g_ogm.th_state,g_ogm.th_state.granulepos);

		if((g_ogm.VFrameCount<th_frame && th_frame>=nextNeededVFrame()) || !g_ogm.outputBuffer) {
//			int i,j;
			int yWShift, uvWShift;
			int yHShift, uvHShift;

			if( theora_decode_YUVout(&g_ogm.th_state, &g_ogm.th_yuvbuffer) )
				continue;

			if(g_ogm.outputWidht != g_ogm.th_info.width || g_ogm.outputHeight != g_ogm.th_info.height) {
				g_ogm.outputWidht = g_ogm.th_info.width;
				g_ogm.outputHeight = g_ogm.th_info.height;
				Com_DPrintf("[Theora(ogg)]new resolution %dx%d\n",g_ogm.outputWidht,g_ogm.outputHeight);
			}

			if(g_ogm.outputBufferSize < g_ogm.th_info.width*g_ogm.th_info.height) {

				g_ogm.outputBufferSize = g_ogm.th_info.width*g_ogm.th_info.height;

				/* Free old output buffer*/
				if(g_ogm.outputBuffer) free(g_ogm.outputBuffer);

				/* Allocate the new buffer */
				g_ogm.outputBuffer = (unsigned char*)malloc(g_ogm.outputBufferSize*4);
				if(g_ogm.outputBuffer == NULL) {
					g_ogm.outputBufferSize = 0;
					r = -2;
					break;
				}
			}

			yWShift  = findSizeShift(g_ogm.th_yuvbuffer.y_width,  g_ogm.th_info.width);
			uvWShift = findSizeShift(g_ogm.th_yuvbuffer.uv_width, g_ogm.th_info.width);
			yHShift  = findSizeShift(g_ogm.th_yuvbuffer.y_height, g_ogm.th_info.height);
			uvHShift = findSizeShift(g_ogm.th_yuvbuffer.uv_height,g_ogm.th_info.height);

			if(yWShift<0 || uvWShift<0 || yHShift<0 || uvHShift<0) {
				Com_Printf("[Theora] unexpected resolution in a yuv-Frame\n");
				r = -1;
			}
			else {

				Frame_yuv_to_rgb24(g_ogm.th_yuvbuffer.y,g_ogm.th_yuvbuffer.u,g_ogm.th_yuvbuffer.v,
						g_ogm.th_info.width, g_ogm.th_info.height, g_ogm.th_yuvbuffer.y_stride, g_ogm.th_yuvbuffer.uv_stride,
						yWShift, uvWShift, yHShift, uvHShift, (unsigned int*)g_ogm.outputBuffer );

/*				unsigned char*	pixelPtr = g_ogm.outputBuffer;
				unsigned int*	pixPtr;
				pixPtr = (unsigned int*)g_ogm.outputBuffer;

				//TODO: use one yuv->rgb funktion for the hole frame (the big amout of stack movement(yuv->rgb calls) couldn't be good ;) )
				for(j=0;j<g_ogm.th_info.height;++j) {
					for(i=0;i<g_ogm.th_info.width;++i) {
#if 1
						// simple grayscale-output ^^
						pixelPtr[0] =
							pixelPtr[1] =
							pixelPtr[2] = g_ogm.th_yuvbuffer.y[i+j*g_ogm.th_yuvbuffer.y_stride];
						pixelPtr+=4;

#else
						// using RoQ yuv->rgb code
						*pixPtr++ = yuv_to_rgb24( g_ogm.th_yuvbuffer.y[(i>>yWShift)+(j>>yHShift)*g_ogm.th_yuvbuffer.y_stride],
												g_ogm.th_yuvbuffer.u[(i>>uvWShift)+(j>>uvHShift)*g_ogm.th_yuvbuffer.uv_stride],
												g_ogm.th_yuvbuffer.v[(i>>uvWShift)+(j>>uvHShift)*g_ogm.th_yuvbuffer.uv_stride]);
#endif
					}
				}
*/

				r = 1;
				g_ogm.VFrameCount=th_frame;
			}
		}


	}

	return r;
}