Ejemplo n.º 1
0
	bool readNextFrame()
	{
		TRACE_FN;
		std::lock_guard<std::recursive_mutex> l(this->frame_queue_lock);
		if (this->stopped)
			return false;

		char ret;
		if (this->current_frame_read == 0)
			ret = smk_first(this->smk_ctx);
		else
			ret = smk_next(this->smk_ctx);

		if (ret == SMK_ERROR)
		{
			LogWarning("Error decoding frame %u", this->current_frame_read);
			return false;
		}

		if (ret == SMK_LAST)
		{
			LogInfo("Last frame %u", this->current_frame_read);
			this->stopped = true;
		}

		const unsigned char *palette_data = smk_get_palette(this->smk_ctx);
		if (!palette_data)
		{
			LogWarning("Failed to get palette data for frame %u", this->current_frame_read);
			return false;
		}
		const unsigned char *image_data = smk_get_video(this->smk_ctx);
		if (!image_data)
		{
			LogWarning("Failed to get image data for frame %u", this->current_frame_read);
			return false;
		}

		auto frame = mksp<FrameImage>();
		frame->frame = this->current_frame_read;

		auto img = mksp<PaletteImage>(this->frame_size);
		frame->image = img;
		frame->palette = mksp<Palette>(256);

		PaletteImageLock img_lock(img);
		memcpy(img_lock.getData(), image_data, this->frame_size.x * this->frame_size.y);

		for (unsigned int i = 0; i < 256; i++)
		{
			auto red = *palette_data++;
			auto green = *palette_data++;
			auto blue = *palette_data++;
			frame->palette->setColour(i, {red, green, blue});
		}

		auto audio_frame = mksp<FrameAudio>();
		audio_frame->frame = current_frame_read;
		audio_frame->format = this->audio_format;
		unsigned long audio_bytes = smk_get_audio_size(this->smk_ctx, 0);
		if (audio_bytes == 0)
		{
			LogWarning("Error reading audio size for frame %u", this->current_frame_read);
			return false;
		}

		auto sample_count =
		    audio_bytes / (this->audio_bytes_per_sample * this->audio_format.channels);
		audio_frame->samples.reset(new char[audio_bytes]);
		audio_frame->sample_count = sample_count;
		auto sample_pointer = smk_get_audio(this->smk_ctx, 0);
		if (!sample_pointer)
		{
			LogWarning("Error reading audio data for frame %u", this->current_frame_read);
			return false;
		}
		memcpy(audio_frame->samples.get(), sample_pointer, audio_bytes);

		LogInfo("Read %lu samples bytes, %u samples", audio_bytes, audio_frame->sample_count);

		this->image_queue.push(frame);
		this->audio_queue.push(audio_frame);

		LogInfo("read frame %u", this->current_frame_read);
		this->current_frame_read++;
		return true;
	}
Ejemplo n.º 2
0
void process(const char *fn)
{
	FILE *fp;
	smk s;
	char outfile[256];
	unsigned char b[4];

	int		i,j,k;
	unsigned long temp_u;

	/* all and video info */
	unsigned long	w, h, f;
	double usf;
	unsigned long total_frame_size;

	/* audio info */
	unsigned char	a_t, a_c[7], a_d[7];
	unsigned long	a_r[7];

	unsigned char num_tracks = 0;
	unsigned char **audio_data[7];
	unsigned long *audio_size[7];
	unsigned long total_audio_size[7] = {0};
	unsigned long total_total_audio_size = 0;

	unsigned char *pal,*frame;

	unsigned long cur_frame;

	printf("--------\nsmk2avi processing %s...\n",fn);

	/* open the smk file */
	s = smk_open_file(fn,SMK_MODE_MEMORY);
	if (s == NULL) goto error;

	/* get some info about the file */
	smk_info_all(s, NULL, &f, &usf);
	smk_info_video(s, &w, &h, NULL);
	smk_info_audio(s, &a_t, a_c, a_d, a_r);

	printf("\t\t\twidth: %u, height: %u, usec/frame: %lf, frames: %u\n",w,h,usf,f);

	total_frame_size = w * h * 3;

	/* make 2 passes through the file.
		first one is to pull all the audio tracks only. */
	smk_enable_all(s,a_t);
	for (i = 0; i < 7; i ++)
	{
		if (a_t & (1 << i))
		{
			audio_size[i] = malloc(f * sizeof(unsigned long));
			audio_data[i] = malloc(f * sizeof(unsigned char*));
			num_tracks ++;
		} else {
			audio_size[i] = NULL;
			audio_data[i] = NULL;
		}
	}

	printf("\tAudio processing frame: ");
	smk_first(s);
	for (cur_frame = 0; cur_frame < f; cur_frame ++)
	{
		printf("%u... ",cur_frame);
			fflush(stdout);
		for (i = 0; i < 7; i ++)
		{
			if (audio_size[i] != NULL)
			{
				audio_size[i][cur_frame] = smk_get_audio_size(s,i);
				total_audio_size[i] += smk_get_audio_size(s,i);
				total_total_audio_size += smk_get_audio_size(s,i);
				audio_data[i][cur_frame] = malloc(audio_size[i][cur_frame]);
				memcpy(audio_data[i][cur_frame],smk_get_audio(s,i),audio_size[i][cur_frame]);
			}
		}
		smk_next(s);
	}
	printf("done!\n");

	smk_enable_all(s,SMK_VIDEO_TRACK);

	sprintf(outfile,"%s.avi",fn);

	fp = fopen(outfile,"wb");

	printf("Writing AVI file...\n");

	// riff header
	w("RIFF",4);
	temp_u = 4 + 4 + (8 + 64 + 124 + (num_tracks * 102)) + 
			8 + (4 + ((total_frame_size + 8) * f) + ( (num_tracks * 8) + total_total_audio_size));
	lu(temp_u);
	w("AVI ",4);

	{
		// avi header list
		LIST;
		temp_u = 8 + 64 + 124 + (num_tracks * 102);
		lu(temp_u);
		w("hdrl",4);

		{
			// avi header
			w("avih",4);
			lu(56);
			{
				lu( (unsigned long)usf ); // microsec per frame
				temp_u = total_frame_size + total_total_audio_size;
				lu( temp_u ); // max bytes per sec
				lu( 1 ); // padding granularity
				lu( 0 ); // flags
				lu( f ); // total frames
				lu( 0 ); // initial frames
				temp_u = num_tracks + 1;
				lu( temp_u ); // streams
				temp_u = total_frame_size + total_total_audio_size;
				lu( temp_u ); // suggested buf size
				lu( w ); // width
				lu( h ); // height
				lu( 0 ); // reserved (0-3)
				lu( 0 );
				lu( 0 );
				lu( 0 );
			}

			// stream list: video stream
puts("Video stream header list");
			LIST
			lu(116);
			w("strl",4);
	
			{
				w("strh",4);
				lu(56);
				{
					w("vids",4); // fourcc type
					w("DIB ",4); // fourcc handler
					lu(0); // flags
					lu(0); // priority + language
					lu(0); // init frames
					lu ((unsigned long)usf); // scale
					lu( 1000000 ); // rate
					lu(0); // start
					temp_u = (unsigned long) ((double)f * 100000.0 / usf);
				lu( temp_u ); // length (time in seconds ?)
					lu(total_frame_size); // suggested bufsize
					lu(-1); // quality
					lu(total_frame_size); // samplesize
					lu(0); // rcFrame
					su(w); su(h); //  rcFrame: right, bottom
				}
	
				w("strf",4);
				lu(40);
				{
					lu(40);	// size
					lu(w);	// width
					lu(h);	// height
					su(1); // planes
					su(24); // bpp
					lu(0); // compression
					lu(total_frame_size); // total image frame size
					lu(0); // xpels/meter
					lu(0); // ypels/meter
					lu(0); // colors used
					lu(0); // colors important
				}
			}
	
			// stream list: audio stream(s)
			for (i = 0; i < 7; i++)
			{
				if (audio_size[i] != NULL)
				{
printf("-> Audio header %d, %dhz, %d bits, %d channels\n",i,a_r[i],a_d[i],a_c[i]);
					LIST
					lu(94);
					w("strl",4);
	
					w("strh",4);
					lu(56);
					{
						w("auds",4); // fourcc
						lu(0); // handler (pcm)
						lu(0); // flags
						lu(0); // priority + language
						lu(0); // initial frames
						lu( a_c[i]); // scale
					temp_u = a_r[i] * a_c[i];
					lu( temp_u ); // framerate
						lu(0); // start
					temp_u = (unsigned long) ((double)f * 100000.0 / usf);
					lu( temp_u ); // time in seconds
						temp_u = total_audio_size[i] / a_c[i]; 
					lu( temp_u ); // sugg. buf size
						lu(-1); // quality
						temp_u = total_audio_size[i];
						lu(temp_u); // sample size
						lu(0); // rect ??
						lu(0); // rect ??
					}
		
					w("strf",4);
					lu(18);
					{
						su(1);	// format
						su(a_c[i]); // channels
						lu(a_r[i]); // samples/sec
						temp_u = a_c[i] * a_r[i] * (a_d[i] / 8); // avg bytes/sec
						lu(temp_u);
						temp_u = a_c[i] * (a_d[i] / 8); // avg bytes/sec
						su(temp_u);
						su(a_d[i]);
						su(0);
					}
				}
			}
		}

		smk_first(s);
		printf("\tVideo processing frame:\n");

		// movie data
		LIST
		temp_u = 4 + ((total_frame_size + 8) * f) + ( (num_tracks * 8) + total_total_audio_size);
		lu(temp_u);
		w("movi",4);
	
		for (i = 0; i < f; i ++)
		{
			w("00db",4);
			lu(total_frame_size);

			frame = smk_get_video(s);
			pal = smk_get_palette(s);

			if (frame == NULL || pal == NULL) goto error;
	
			for (j = h - 1; j >= 0; j--)
			{
				for (k = 0; k < w; k++)
				{
					w(&pal[frame[(j * w) + k] * 3 + 2],1);
					w(&pal[frame[(j * w) + k] * 3 + 1],1);
					w(&pal[frame[(j * w) + k] * 3],1);
				}
			}
			printf("%u...",i);
			fflush(stdout);

			smk_next(s);
		}
		printf("done!\n");

		k = 0;
		for (i = 0; i < 7; i++)
		{
			if (audio_size[i] != NULL)
			{
				k ++;
				sprintf(b,"%02uwb",k);
				w(b,4);
				temp_u = total_audio_size[i];
				lu(temp_u);

				for (j = 0; j < f; j++)
				{
					w(audio_data[i][j],audio_size[i][j]);
				}
			}
		}
	}
	
	fclose(fp);	

	smk_close(s);

	printf("done.\n--------\n");
	return;

error:
	fclose(fp);	

	smk_close(s);
	printf("!!HAD ERRORS!!\n--------\n");
	return;
	
}