lsnes/include/video/avi/codec.hpp
Ilari Liusvaara a0663b5450 Add the needed support for internal buffering by audio codec
Some audio codecs may want to internally buffer to send the audio in
larger blocks. Add method avi_audio_codec::flush() that signals to the
codec that incomplete block should be flushed in preparation to close
the AVI file (after calling that, audio packet queue is flushed).
2012-02-12 21:39:06 +02:00

283 lines
6.3 KiB
C++

#ifndef _avi__avi_codec__hpp__included__
#define _avi__avi_codec__hpp__included__
#include <cstdint>
#include <vector>
#include <cstdlib>
#include "video/avi/structure.hpp"
#include "video/avi/samplequeue.hpp"
#include "video/avi/timer.hpp"
/**
* AVI packet.
*/
struct avi_packet
{
/**
* Packet type code. The usual values are:
* - 0x6264: Uncompressed bitmap
* - 0x6364: compressed bitmap
* - 0x6277: Sound data
*/
uint16_t typecode;
/**
* Hide from index flag.
*/
bool hidden;
/**
* Index flags. Ignored if hidden flag is set.
*/
uint32_t indexflags;
/**
* The actual packet payload.
*/
std::vector<char> payload;
};
/**
* AVI video codec (compressor).
*/
struct avi_video_codec
{
/**
* Strf info
*/
struct format
{
format(uint32_t compression, uint16_t bitcount);
uint32_t suggested_buffer_size;
uint32_t max_bytes_per_sec;
uint16_t planes;
uint16_t bit_count;
uint32_t compression;
uint32_t resolution_x;
uint32_t resolution_y;
uint32_t quality;
uint32_t clr_used;
uint32_t clr_important;
std::vector<uint8_t> extra;
};
virtual ~avi_video_codec();
/**
* Reset the codec, giving new state.
*
* Parameter width: The width of image.
* Parameter height: The height of image.
* Parameter fps_n: fps numerator.
* Parameter fps_d: fps denominator.
* Returns: Stream format.
*/
virtual format reset(uint32_t width, uint32_t height, uint32_t fps_n, uint32_t fps_d) = 0;
/**
* Send in frame of data. ready() must return true.
*
* - The buffer can be reused after this call returns.
* - rshift = 0, gshift = 8, bshift = 16.
*
* Parameter data: Video frame data, left to right, top to bottom order.
*/
virtual void frame(uint32_t* data) = 0;
/**
* Is the codec ready to receive a new frame?
*
* Returns: True if new frame can be passed. False if packets have to be extracted.
*/
virtual bool ready() = 0;
/**
* Read packet. Before calling, ready() must return false.
*
* Returns: The packet.
*/
virtual avi_packet getpacket() = 0;
};
/**
* AVI common codec type.
*/
template<typename T>
struct avi_codec_type
{
avi_codec_type(const char* iname, const char* hname, T* (*instance)());
/**
* Unregister instance.
*/
~avi_codec_type();
/**
* Find instance.
*
* Parameter iname: Iname of instance to find.
*/
static avi_codec_type<T>* find(const std::string& iname);
/**
* Find next codec type.
*
* Parameter type: Type to find. If NULL, find the first one.
* Returns: The next codec, or NULL if none.
*/
static avi_codec_type<T>* find_next(avi_codec_type<T>* type);
/**
* Get iname field of codec.
*/
std::string get_iname();
/**
* Get hname field of codec.
*/
std::string get_hname();
/**
* Get instance of codec.
*/
T* get_instance();
private:
std::string iname;
std::string hname;
T* (*instance)();
static std::map<std::string, avi_codec_type<T>*>& codecs();
};
/**
* AVI audio codec (compressor).
*/
struct avi_audio_codec
{
/**
* Strf info.
*/
struct format
{
format(uint16_t tag);
uint32_t max_bytes_per_sec;
uint32_t suggested_buffer_size;
uint16_t format_tag;
uint32_t average_rate;
uint16_t alignment;
uint16_t bitdepth;
uint32_t quality;
std::vector<uint8_t> extra;;
};
virtual ~avi_audio_codec();
/**
* Reset the codec, giving new state.
*
* Parameter samplerate: The new sampling rate.
* Parameter channels: Channel count.
* Returns: Stream format.
*/
virtual format reset(uint32_t samplerate, uint16_t channels) = 0;
/**
* Send in samples of data. ready() must return true.
*
* - The buffer can be reused after this call returns.
*
* Parameter data: Interleaved samples.
* Parameter samples: Number of samples offered.
*/
virtual void samples(int16_t* data, size_t samples) = 0;
/**
* Flush the audio state. Default implementation does nothing.
*/
virtual void flush();
/**
* Is the codec ready to receive a new frame?
*
* Returns: True if new frame can be passed. False if packets have to be extracted.
*/
virtual bool ready() = 0;
/**
* Read packet. Before calling, ready() must return false.
*
* Returns: The packet.
*/
virtual avi_packet getpacket() = 0;
};
typedef avi_codec_type<avi_video_codec> avi_video_codec_type;
typedef avi_codec_type<avi_audio_codec> avi_audio_codec_type;
/**
* Combine trackid and packet typecode into full type.
*/
uint32_t get_actual_packet_type(uint8_t trackid, uint16_t typecode);
/**
* AVI output stream.
*/
struct avi_output_stream
{
/**
* Create new output stream.
*/
avi_output_stream();
/**
* Destructor.
*/
~avi_output_stream();
/**
* Start new segment. If there is existing segment, it is closed.
*
* Parameter out: Output file.
* Parameter vcodec: The video codec to use.
* Parameter acodec: The audio codec to use.
* Parameter width: Width of video.
* Parameter height: Height of video.
* Parameter fps_n: Framerate numerator.
* Parameter fps_d: Framerate denomerator.
* Parameter samplerate: Audio sampling rate.
* Parameter channels: Number of audio channels.
*/
void start(std::ostream& out, avi_video_codec& vcodec, avi_audio_codec& acodec, uint32_t width,
uint32_t height, uint32_t fps_n, uint32_t fps_d, uint32_t samplerate, uint16_t channels);
/**
* Write stuff to video codec.
*
* Parameter frame: The frame to write. See avi_video_codec::frame() for format.
*/
void frame(uint32_t* frame);
/**
* Write stuff to audio codec.
*
* Parameter samples: The samples to write.
* Parameter samplecount: Count of samples.
*/
void samples(int16_t* samples, size_t samplecount);
/**
* Flush audio codec state in preparation to close the AVI.
*/
void flushaudio();
/**
* Get number of samples for the next frame.
*
* Returns: The number of samples.
*/
size_t framesamples();
/**
* Get size estimate.
*
* Returns: The estimated size.
*/
uint64_t get_size_estimate();
/**
* Flush frame and associtated samples from queue.
*
* Parameter frame: The frame to write. Deleted if written.
* Parameter aqueue: The audio queue.
* Parameter force: Read the frame even if there aren't enough sound samples.
* Returns: True if frame was read, false otherwise.
*/
bool readqueue(uint32_t* frame, sample_queue& aqueue, bool force);
/**
* End a segment.
*/
void end();
private:
bool in_segment;
avi_file_structure avifile;
avi_video_codec* vcodec;
avi_audio_codec* acodec;
uint16_t achans;
timer video_timer;
timer audio_timer;
};
#endif