示例#1
0
static int decode_to_timestamp(AVFormatContext* fc,
                               int video_stream_index,
                               double wanted_timestamp, double fps,
                               AVPacket* pkt, AVFrame* frame,
                               double* timestamp)
{
  double frame_duration = 1.0 / fps;
  double current_timestamp = wanted_timestamp - 2*frame_duration;

  int counter = 0;

  AVStream* video_stream = fc->streams[video_stream_index];
  double time_base = av_q2d(video_stream->time_base);

  while (fabs(current_timestamp - wanted_timestamp) >= 0.98*frame_duration)
    {
      int ret = next_video_frame(pkt, fc, video_stream_index);
      
      if (ret < 0)
          return -1;

      int got_frame = 0;
      ret = decode(fc, video_stream_index, frame, pkt, &got_frame);

      if (got_frame)
        current_timestamp = ((double) pkt->pts) * time_base;
      av_free_packet(pkt);

      if (ret < 0)
        return -1;

      if (pkt->pts == AV_NOPTS_VALUE)
        {
          std::cerr << "Invalid pts in packet\n";
          return -1;
        }

      ++counter;
    }

#if defined FFMPEGDRIVER_PRINT_DEBUG    
  std::cout << "decoded " << counter << " frames\n";
#endif

  *timestamp = current_timestamp;
  return 1;
}
示例#2
0
void *display_thread(void *arg)
{
	PlayerCtx *ctx = arg;
	int i;

	OLRenderParams params;
	memset(&params, 0, sizeof params);
	params.rate = 48000;
	params.on_speed = 2.0/100.0;
	params.off_speed = 2.0/15.0;
	params.start_wait = 8;
	params.end_wait = 3;
	params.snap = 1/120.0;
	params.render_flags = RENDER_GRAYSCALE;
	params.min_length = 20;
	params.start_dwell = 2;
	params.end_dwell = 2;
	params.max_framelen = 48000/20.0;

	if(olInit(OL_FRAMES_BUF, 300000) < 0) {
		printf("OpenLase init failed\n");
		return NULL;
	}

	float aspect = ctx->width / (float)ctx->height;
	float sample_aspect = av_q2d(ctx->v_stream->sample_aspect_ratio);
	if (sample_aspect != 0)
		aspect *= sample_aspect;
	printf("Aspect: %f\n", aspect);

	float iaspect = 1/aspect;

	int maxd = ctx->width > ctx->height ? ctx->width : ctx->height;
	int mind = ctx->width < ctx->height ? ctx->width : ctx->height;

	g_ctx = ctx;
	olSetAudioCallback(get_audio);
	olSetRenderParams(&params);

	OLTraceCtx *trace_ctx;
	OLTraceParams tparams;
	OLTraceResult result;
	memset(&result, 0, sizeof(result));
	ctx->settings_changed = 1;

	tparams.sigma = ctx->settings.blur / 100.0;
	if (ctx->settings.canny)
		tparams.mode = OL_TRACE_CANNY;
	else
		tparams.mode = OL_TRACE_THRESHOLD;
	tparams.width = ctx->width;
	tparams.height = ctx->height;

	printf("Resolution: %dx%d\n", ctx->width, ctx->height);
	olTraceInit(&trace_ctx, &tparams);

	VideoFrame *last = NULL;

	pthread_mutex_lock(&ctx->display_mode_mutex);
	DisplayMode display_mode = ctx->display_mode;
	pthread_mutex_unlock(&ctx->display_mode_mutex);

	int inf = 0;
	int bg_white = -1;
	float time = 0;
	int frames = 0;
	while (display_mode != STOP) {
		pthread_mutex_lock(&ctx->settings_mutex);
		PlayerSettings settings = ctx->settings;
		int settings_changed = ctx->settings_changed;
		ctx->settings_changed = 0;
		pthread_mutex_unlock(&ctx->settings_mutex);

		if (ctx->audio_idx == -1) {
			drop_all_video(ctx);
			next_video_frame(ctx);
		}

		params.min_length = settings.minsize;
		params.end_dwell = params.start_dwell = settings.dwell;
		params.off_speed = settings.offspeed * 0.002;
		params.snap = (settings.snap*2.0)/(float)maxd;
		params.start_wait = settings.startwait;
		params.end_wait = settings.endwait;
		if (settings.minrate == 0)
			params.max_framelen = 0;
		else
			params.max_framelen = params.rate / settings.minrate;

		olSetRenderParams(&params);

		olLoadIdentity();
		if (aspect > 1) {
			olSetScissor(-1, -iaspect, 1, iaspect);
			olScale(1, iaspect);
		} else {
			olSetScissor(-aspect, -1, aspect, 1);
			olScale(aspect, 1);
		}

		olScale(1 + settings.overscan/100.0, 1 + settings.overscan/100.0);
		olTranslate(-1.0f, 1.0f);
		olScale(2.0f/ctx->width, -2.0f/ctx->height);

		if (!ctx->cur_frame || ctx->cur_frame->seekid < 0) {
			printf("Dummy frame\n");
			float ftime = olRenderFrame(80);
			pthread_mutex_lock(&ctx->display_mode_mutex);
			display_mode = ctx->display_mode;
			pthread_mutex_unlock(&ctx->display_mode_mutex);
			if (ctx->cur_frame && ctx->cur_frame->seekid < 0)
				deliver_event(ctx, time, ftime, frames, 1);
			else
				deliver_event(ctx, time, ftime, frames, 0);
			continue;
		}

		if (last != ctx->cur_frame || settings_changed) {
			tparams.sigma = settings.blur / 100.0;
			if (settings.canny) {
				tparams.mode = OL_TRACE_CANNY;
				tparams.threshold = settings.threshold;
				tparams.threshold2 = settings.threshold2;
				bg_white = -1;
			} else {
				tparams.mode = OL_TRACE_THRESHOLD;
				if (settings.splitthreshold) {
					int edge_off = mind * settings.offset / 100;
					int bsum = 0;
					int cnt = 0;
					int c;
					for (c = edge_off; c < (ctx->width-edge_off); c++) {
						bsum += ctx->cur_frame->data[c+edge_off*ctx->cur_frame->stride];
						bsum += ctx->cur_frame->data[c+(ctx->height-edge_off-1)*ctx->cur_frame->stride];
						cnt += 2;
					}
					for (c = edge_off; c < (ctx->height-edge_off); c++) {
						bsum += ctx->cur_frame->data[edge_off+ctx->cur_frame->stride];
						bsum += ctx->cur_frame->data[(c+1)*ctx->cur_frame->stride-1-edge_off];
						cnt += 2;
					}
					bsum /= cnt;
					if (bg_white == -1)
						bg_white = bsum > ((settings.darkval + settings.lightval)/2);
					if (bg_white && bsum < settings.darkval)
						bg_white = 0;
					if (!bg_white && bsum > settings.lightval)
						bg_white = 1;
					if (bg_white)
						tparams.threshold = settings.threshold2;
					else
						tparams.threshold = settings.threshold;
				} else {
					tparams.threshold = settings.threshold;
				}
			}
			olTraceReInit(trace_ctx, &tparams);
			olTraceFree(&result);
			printf("Trace\n");
			olTrace(trace_ctx, ctx->cur_frame->data, ctx->cur_frame->stride, &result);
			printf("Trace done\n");
			inf++;
			last = ctx->cur_frame;
		}

		int i, j;
		for (i = 0; i < result.count; i++) {
			OLTraceObject *o = &result.objects[i];
			olBegin(OL_POINTS);
			OLTracePoint *p = o->points;
			for (j = 0; j < o->count; j++) {
				if (j % settings.decimation == 0)
					olVertex(p->x, p->y, C_WHITE);
				p++;
			}
			olEnd();
		}

		float ftime = olRenderFrame(80);
		OLFrameInfo info;
		olGetFrameInfo(&info);
		frames++;
		time += ftime;
		printf("Frame time: %.04f, Cur FPS:%6.02f, Avg FPS:%6.02f, Drift: %7.4f, "
				"In %4d, Out %4d Thr %3d/%3d Bg %3d Pts %4d",
				ftime, 1/ftime, frames/time, 0.0, inf, frames,
				tparams.threshold, tparams.threshold2, 0, info.points);
		if (info.resampled_points)
			printf(" Rp %4d Bp %4d", info.resampled_points, info.resampled_blacks);
		if (info.padding_points)
			printf(" Pad %4d", info.padding_points);
		printf("\n");
		deliver_event(ctx, time, ftime, frames, 0);

		pthread_mutex_lock(&ctx->display_mode_mutex);
		display_mode = ctx->display_mode;
		pthread_mutex_unlock(&ctx->display_mode_mutex);
	}

	olTraceDeinit(trace_ctx);

	for(i = 0; i < OL_FRAMES_BUF; i++)
		olRenderFrame(80);

	olShutdown();
	return NULL;
}
示例#3
0
void get_audio(float *lb, float *rb, int samples)
{
	PlayerCtx *ctx = g_ctx;

	if (ctx->audio_idx == -1) {
		memset(lb, 0, samples * sizeof(*lb));
		memset(rb, 0, samples * sizeof(*rb));
		return;
	}

	pthread_mutex_lock(&ctx->display_mode_mutex);
	DisplayMode display_mode = ctx->display_mode;
	pthread_mutex_unlock(&ctx->display_mode_mutex);

	if (display_mode != PLAY)
	{
		if (display_mode == PAUSE) {
			printf("get_audio: paused\n");
			if (!ctx->cur_frame) {
				next_video_frame(ctx);
			}
			while (ctx->cur_frame->seekid != ctx->cur_seekid &&
				   ctx->cur_frame->seekid != -ctx->cur_seekid) {
				printf("Drop audio due to seek\n");
				drop_audio(ctx, 1);
				next_video_frame(ctx);
				drop_audio(ctx, 1);
			}
			if (ctx->skip_frame) {
				ctx->skip_frame = 0;
				drop_audio(ctx, 1);
				next_video_frame(ctx);
				drop_audio(ctx, 1);
			}
			printf("get_audio: pause complete\n");
		}
		memset(lb, 0, samples * sizeof(*lb));
		memset(rb, 0, samples * sizeof(*rb));
		return;
	}
	pthread_mutex_lock(&ctx->settings_mutex);
	double volume = ctx->settings.volume / 100.0;
	pthread_mutex_unlock(&ctx->settings_mutex);

	while (samples) {
		double pts = -1;

		pthread_mutex_lock(&ctx->a_buf_mutex);
		int have_samples = ctx->a_buf_put - ctx->a_buf_get;
		if (!have_samples) {
			printf("Wait for audio\n");
			pthread_cond_wait(&ctx->a_buf_not_empty, &ctx->a_buf_mutex);
			pthread_mutex_unlock(&ctx->a_buf_mutex);
			continue;
		}
		if (have_samples < 0)
			have_samples += ctx->a_buf_len;
		pthread_mutex_unlock(&ctx->a_buf_mutex);

		int get = ctx->a_buf_get;
		int played = 0;
		while (samples && have_samples--) {
			if (ctx->a_buf[get].seekid == -ctx->cur_seekid) {
				memset(lb, 0, sizeof(*lb) * samples);
				memset(rb, 0, sizeof(*rb) * samples);
				samples = 0;
				break;
			}
			if (ctx->a_buf[get].seekid == ctx->cur_seekid) {
				pts = ctx->a_buf[get].pts;
				*lb++ = ctx->a_buf[get].l / 32768.0 * volume;
				*rb++ = ctx->a_buf[get].r / 32768.0 * volume;
				samples--;
				played++;
			}
			if (++get >= ctx->a_buf_len)
				get = 0;
		}

		pthread_mutex_lock(&ctx->a_buf_mutex);
		ctx->a_buf_get = get;
		pthread_cond_signal(&ctx->a_buf_not_full);
		pthread_mutex_unlock(&ctx->a_buf_mutex);

		printf("Played %d samples, next pts %f\n", played, pts);

		while (1) {
			if (!ctx->cur_frame) {
				next_video_frame(ctx);
				continue;
			}
			if (ctx->cur_frame->seekid == -ctx->cur_seekid)
				break;
			double next_pts = ctx->cur_frame->pts;
			if (ctx->last_frame_pts != -1)
				next_pts = 2 * ctx->cur_frame->pts - ctx->last_frame_pts;
			if (pts > next_pts || ctx->cur_frame->seekid != ctx->cur_seekid) {
				if (next_video_frame(ctx))
					continue;
			}
			break;
		}
	}
}