Skip to content

Commit

Permalink
Fixed #18 : Encoder and player now supports silent flims
Browse files Browse the repository at this point in the history
  • Loading branch information
fstark committed Nov 16, 2021
1 parent 517e389 commit 79b6761
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 21 deletions.
Binary file modified MacFlim Source Code.dsk
Binary file not shown.
8 changes: 7 additions & 1 deletion README.md
Expand Up @@ -188,6 +188,10 @@ When specifiying a set of pgm files as input, the audio must be provided using a
sox -V2 audio.wav -r 22200 -e unsigned-integer -b 8 audio.raw remix 1 norm


### --silent **boolean**

If true, the generated flim will not contain any audio, and will be smaller by 22KB/s. This is useful for encoding silent movies, or if you don't need sound and want to get the best image possible for a background display.

## Moar options!

Digging into the dirty details, here are the options that control the encoding itself (ie: the options driven by the profile).
Expand All @@ -198,7 +202,7 @@ You need to specify those options *after* the ``--profile``

This is an advanced section for fine-tuning the encodings. You are not expected to understand it, and the details may change without warning.

### --byterate byterate
### --byterate **byterate**

The byterate is the number of bytes per ticks (a tick is 1/60th of a second) that are available to encode the video stream. 370 additional bytes are used for the sound, plus a handful of bytes overhead. When encoding the changes between two frames, flimmaker will use up to byterate bytes (not strictly true, but a good enough approximation of the process), and, if there are not enough bandwidth, will let part the previous frame leak into the next one.

Expand All @@ -208,6 +212,8 @@ The Mac Plus is able to read and decode around 1500 bytes per tick, the Mac SE a

You can play with this parameter if your mac has a faster/slower drive (example: SE/30 from ram disk). If the byterate is too high, you will suffer sound and video skips at playback, as your Mac will not able to fetch and decompress the data fast enough.

NOTE: as of today, the byterate is only the *video* byterate. 376 extra bytes are added for audio. This WILL PROBABLY change in the future.

### --fps-ratio **integer**

``--fps-ratio 2`` will effectively halve the framerate of the input, resulting in a worse looking, but smaller flim. If Mac Flim has troubles displaying your flim, using ``--fps-ratio 2`` or higher can vastly improve the visual result.
Expand Down
8 changes: 6 additions & 2 deletions flimcompressor.hpp
Expand Up @@ -37,7 +37,8 @@ class flimcompressor

framebuffer result;

size_t get_size() { return audio.size()+video.size()*4; }
// #### passing silent is inelegant: we should not generate audio data when silenced
size_t get_size( bool silent ) { return video.size()+silent*audio.size(); }
};

private:
Expand All @@ -55,6 +56,8 @@ class flimcompressor

const std::vector<frame> &get_frames() const { return frames_; }

bool progress_ = true;

struct codec_spec
{
uint8_t signature;
Expand Down Expand Up @@ -312,7 +315,8 @@ class flimcompressor
f.result = current_fb;

frames_.push_back( f );
std::clog << "Encoded " << frames_.size() << " output frames\r" << std::flush;
if (progress_)
std::clog << "Encoded " << frames_.size() << " output frames\r" << std::flush;
}

auto q = frames_.back().result.proximity( fb );
Expand Down
44 changes: 27 additions & 17 deletions flimencoder.hpp
Expand Up @@ -194,6 +194,7 @@ class encoding_profile
std::ostringstream cmd;

cmd << "--byterate " << byterate_;
cmd << " --buffer-size " << buffer_size_;
cmd << " --fps-ratio " << fps_ratio_;
cmd << " --group " << (group_?"true":"false");
cmd << " --bars " << (bars_?"true":"false");
Expand Down Expand Up @@ -235,6 +236,8 @@ class flimencoder
size_t cover_begin_; /// Begin index of cover image
size_t cover_end_; /// End index of cover image

bool silent_ = false; /// If true, film has no sound (maybe should be handled at the reader level)

size_t frame_from_image( size_t n ) const
{
return ticks_from_frame( n-1, fps_/profile_.fps_ratio() );
Expand Down Expand Up @@ -333,15 +336,12 @@ class flimencoder
void set_diff_pattern( const std::string pattern ) { diff_pattern_ = pattern; }
void set_change_pattern( const std::string pattern ) { change_pattern_ = pattern; }
void set_target_pattern( const std::string pattern ) { target_pattern_ = pattern; }
void set_silent( bool silent ) { silent_ = silent; }

// Encode all the blocks
void make_flim( const std::string flim_pathname, input_reader *reader, const std::vector<std::unique_ptr<output_writer>> &writers )
{
assert( reader );
/*
read_images( from, to, profile_.half_rate() );
read_audio( from, images_.size() );
*/

int i = 0;
while (auto next = reader->next())
Expand All @@ -351,10 +351,11 @@ class flimencoder
i++;
}

while (auto next = reader->next_sound())
{
audio_samples_.push_back( *next );
}
if (!silent_)
while (auto next = reader->next_sound())
{
audio_samples_.push_back( *next );
}

// audio_samples_ = normalize_sound( reader->raw_sound(), images_.size()/fps_*60*370 );

Expand Down Expand Up @@ -387,9 +388,9 @@ class flimencoder
{
std::vector<u_int8_t> block_content;
auto block_ptr = std::back_inserter( block_content );
size_t current_block_size = 0;
// size_t current_block_size = 0;

while (current_frame!=std::end(frames) && current_block_size+current_frame->get_size()<profile_.buffer_size())
while (current_frame!=std::end(frames) && block_content.size()+current_frame->get_size( silent_ )<profile_.buffer_size())
{
// logs current image
{
Expand Down Expand Up @@ -423,16 +424,23 @@ class flimencoder
img++;
}

write2( block_ptr, current_frame->ticks*370+8 ); // size of sound + header + size itself
write2( block_ptr, 0 ); // ffMode
write4( block_ptr, 65536 ); // rate
write( block_ptr, current_frame->audio );
if (!silent_)
{
write2( block_ptr, current_frame->ticks*370+8 ); // size of sound + header + size itself
write2( block_ptr, 0 ); // ffMode
write4( block_ptr, 65536 ); // rate
write( block_ptr, current_frame->audio );
}
else
{
write2( block_ptr, 2 ); // No sound
}
write2( block_ptr, current_frame->video.size()+2 );
write( block_ptr, current_frame->video );

current_block_size += current_frame->get_size();
current_frame++;
}

write4( out_movie, block_content.size()+4 /* size */+4 /* 'FLIM' */+2/* frames */ );
write4( out_movie, 0x464C494D );
write2( out_movie, current_frame-block_first_frame );
Expand Down Expand Up @@ -493,8 +501,10 @@ class flimencoder
index++;
std::clog << "Wrote " << index << " frames\r" << std::flush;
sound_frame_t snd;
if (sound<std::end(audio_samples_))
snd = *sound++;

if (!silent_)
if (sound<std::end(audio_samples_))
snd = *sound++;

writer->write_frame( frame.result.as_image(), snd );
}
Expand Down
18 changes: 17 additions & 1 deletion flimmaker.cpp
Expand Up @@ -163,7 +163,9 @@ void usage( const std::string name )
std::cerr << "\n Encoding options:\n";

std::cerr << " --profile PROFILE : presents the specific encoding profile, which sets a suitable default for all encoding options\n";
std::cerr << " Defdaul is 'se30'. See below for description of profiles.\n";
std::cerr << " Default is 'se30'. See below for description of profiles.\n";

std::cerr << " --silent BOOLEAN : set to true for silent flims\n";

std::cerr << " --byterate BYTERATE : bytes per ticks available for video compression\n";
std::cerr << " --fps-ratio BOOLEAN : ratio of images from the source to drop.\n";
Expand Down Expand Up @@ -246,6 +248,7 @@ try
std::string cache_file = std::tmpnam( nullptr );
bool generated_cache = true;
bool downloaded_file = false;
bool silent_arg = false;

const std::string cmd_name{ argv[0] };

Expand Down Expand Up @@ -417,6 +420,12 @@ try
argv++;
audio_arg = *argv;
}
else if (!strcmp(*argv,"--silent"))
{
argc--;
argv++;
silent_arg = bool_from(*argv);
}
else if (!strcmp(*argv,"--flim"))
{
argc--;
Expand Down Expand Up @@ -517,6 +526,12 @@ try
argv++;
custom_profile.set_error_bidi( bool_from(*argv) );
}
else if (!strcmp(*argv,"--buffer-size"))
{
argc--;
argv++;
custom_profile.set_buffer_size( atoi(*argv) );
}
else
{
std::cerr << "Unknown argument " << *argv << "\n";
Expand Down Expand Up @@ -611,6 +626,7 @@ try
encoder.set_diff_pattern( diff_pattern );
encoder.set_change_pattern( change_pattern );
encoder.set_target_pattern( target_pattern );
encoder.set_silent( silent_arg );

// encoder.set_input_single_random();

Expand Down

0 comments on commit 79b6761

Please sign in to comment.