Exemplo n.º 1
0
ssize_t
load_audio_file(const char *name, char **data, size_t *size)
{
    mm_file mf;
    unsigned channels, rate;
    const size_t def_size = 16 * 1024;
    size_t offset = 0;
    ssize_t read = 0;
    double start = get_time();

    /* make compiler happy */
    start *= 1.0;

    assert(name);
    assert(data);
    assert(size);

    if (mm_open_fp(&mf, sOpen(name, "rb", FT_AUDIO)) < 0) {
        return -1;
    }

    if (mm_audio_info(&mf, &channels, &rate) < 0) {
        CWARNING3(audio, "no audio data in file `%s'", name);
        mm_close(&mf);
        return -1;
    }

    if (channels != 1 || rate != 11025) {
        CERROR3(audio, "file `%s' should be mono, 11025Hz", name);
        mm_close(&mf);
        return -1;
    }

    if (!*data) {
        *data = (char *)xmalloc(*size = def_size);
    }

    while (0 < (read = mm_decode_audio(&mf,
                                       *data + offset, *size - offset))) {
        offset += read;

        if (*size <= offset) {
            *data = (char *)xrealloc(*data, *size *= 2);
        }
    }

    mm_close(&mf);

    CDEBUG4(audio, "loading file `%s' took %5.4f seconds",
            name, get_time() - start);

    return offset;
}
int
main(int argc, char **argv)
{
	char *file = NULL;
	int have_video = 0, have_audio = 0;
	unsigned h = 0, w = 0;
	float fps = 0.0;
	unsigned ch = 0, hz = 0;
	struct audiobuf abuf;
	int end = 0;
	SDL_Surface *display = NULL;
	SDL_Overlay *ovl = NULL;
	SDL_Event event;
	mm_file media;

	if (argc > 1)
		file = argv[1];
	else
		usage(argv[0]);

	if (mm_open(&media, file) <= 0)
		eprintf("No audio or video in `%s'\n", file);

	if (mm_video_info(&media, &w, &h, &fps) >= 0)
	{
		printf("Video data: %dx%d, %gfps\n", w, h, fps);
		have_video = 1;
	}

	if (mm_audio_info(&media, &ch, &hz) >= 0)
	{
		printf("Audio data: %s, %dHz\n", (ch == 1) ? "mono" : "stereo", hz);
		have_audio = 1;
	}

	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0)
		eprintf("Sdl init failed: %s\n", SDL_GetError());

	if (have_video)
	{
		if ((display = SDL_SetVideoMode(w, h, 24,
					SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
			eprintf("SDL_SetVideoMode: %s\n", SDL_GetError());

		if ((ovl = SDL_CreateYUVOverlay(w, h,
					SDL_YV12_OVERLAY, display)) == NULL)
			eprintf("SDL_CreateYUVOverlay: %s\n", SDL_GetError());
	}

	if (have_audio)
	{
		int bytes;
		int bps;
		double tdiff;
		SDL_AudioSpec desired;

		desired.channels = ch;
		desired.freq = hz;
		desired.format = AUDIO_U8;
		bps = ch * 1;
		desired.samples = 4096;
		desired.callback = audio_cb;
		desired.userdata = &abuf;
		if (SDL_OpenAudio(&desired, NULL) < 0)
			eprintf("SDL_OpenAudio: %s\n", SDL_GetError());

		abuf.size = 4 * 4096;
		abuf.off = 0;
		abuf.bytes = 0;
		abuf.buf = xmalloc(abuf.size);

		tdiff = get_time();
		while ((bytes = mm_decode_audio(&media,
					abuf.buf + abuf.bytes, abuf.size - abuf.bytes)) > 0)
		{
			abuf.bytes += bytes;
			if (abuf.size - abuf.bytes <= 4096)
				abuf.buf = xrealloc(abuf.buf, abuf.size *= 2);
		};
		if (bytes < 0)
			eperror("convert_audio");

		printf("Decoding: %.3f seconds\n", get_time() - tdiff);
		printf("Audio: %d samples, %.2f seconds\n", abuf.bytes / bps,
			(double) (abuf.bytes) / bps / desired.freq);

		SDL_PauseAudio(0);
	}

	while (!end)
	{
		while (SDL_PollEvent(&event))
			switch (event.type)
			{
				case SDL_QUIT:
					end = 1;
					break;
				case SDL_KEYDOWN:
					if (event.key.keysym.sym == SDLK_q
						|| event.key.keysym.sym == SDLK_ESCAPE)
						end = 1;
					break;
				default:
					break;
			}

		if (have_video && !end)
		{
			static double oldt, newt;

			if (mm_decode_video(&media, ovl) > 0)
			{
				SDL_Rect r = { 0, 0, w, h };
				newt = 1 / fps + oldt - get_time();
				if (newt > 0)
					SDL_Delay(newt * 1000);
				SDL_DisplayYUVOverlay(ovl, &r);
				oldt = get_time();
			}
			else
				end = 1;
		}

		if (have_audio && abuf.bytes <= 0)
			end = 1;

		if (!have_video)
			SDL_Delay(100);
	}

	if (have_audio)
	{
		SDL_PauseAudio(1);
		free(abuf.buf);
	}

	if (have_video)
	{
		SDL_FreeYUVOverlay(ovl);
	}

	SDL_Quit();
	mm_close(&media);

	return EXIT_SUCCESS;
}