AVI dumping fixups
- Write video dimensions correctly if codec pads the video - Uncompressed: Pad video right - CSCD: Pad video right - Print message when starting a new segment - Delete some unused code
This commit is contained in:
parent
37761ac6f5
commit
298ead2f6c
5 changed files with 23 additions and 66 deletions
|
@ -44,7 +44,9 @@ struct avi_video_codec
|
||||||
*/
|
*/
|
||||||
struct format
|
struct format
|
||||||
{
|
{
|
||||||
format(uint32_t compression, uint16_t bitcount);
|
format(uint32_t _width, uint32_t _height, uint32_t compression, uint16_t bitcount);
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
uint32_t suggested_buffer_size;
|
uint32_t suggested_buffer_size;
|
||||||
uint32_t max_bytes_per_sec;
|
uint32_t max_bytes_per_sec;
|
||||||
uint16_t planes;
|
uint16_t planes;
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
avi_video_codec::~avi_video_codec() {};
|
avi_video_codec::~avi_video_codec() {};
|
||||||
avi_audio_codec::~avi_audio_codec() {};
|
avi_audio_codec::~avi_audio_codec() {};
|
||||||
|
|
||||||
avi_video_codec::format::format(uint32_t _compression, uint16_t bitcount)
|
avi_video_codec::format::format(uint32_t _width, uint32_t _height, uint32_t _compression, uint16_t bitcount)
|
||||||
{
|
{
|
||||||
|
width = _width;
|
||||||
|
height = _height;
|
||||||
suggested_buffer_size = 1000000;
|
suggested_buffer_size = 1000000;
|
||||||
max_bytes_per_sec = 10000000;
|
max_bytes_per_sec = 10000000;
|
||||||
planes = 1;
|
planes = 1;
|
||||||
|
@ -39,55 +41,6 @@ uint32_t get_actual_packet_type(uint8_t trackid, uint16_t typecode)
|
||||||
return t1 | t2 << 8 | static_cast<uint32_t>(typecode) << 16;
|
return t1 | t2 << 8 | static_cast<uint32_t>(typecode) << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_avi_structure(header_list& avih, 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)
|
|
||||||
{
|
|
||||||
avi_audio_codec::format afmt = acodec.reset(samplerate, channels);
|
|
||||||
avi_video_codec::format vfmt = vcodec.reset(width, height, fps_n, fps_d);
|
|
||||||
|
|
||||||
avih.avih.microsec_per_frame = (uint64_t)1000000 * fps_d / fps_n;
|
|
||||||
avih.avih.max_bytes_per_sec = afmt.max_bytes_per_sec + vfmt.max_bytes_per_sec;
|
|
||||||
avih.avih.padding_granularity = 0;
|
|
||||||
avih.avih.flags = 2064; //Trust chunk types, has index.
|
|
||||||
avih.avih.initial_frames = 0;
|
|
||||||
avih.avih.suggested_buffer_size = 1048576; //Just some value.
|
|
||||||
avih.videotrack.strh.handler = 0;
|
|
||||||
avih.videotrack.strh.flags = 0;
|
|
||||||
avih.videotrack.strh.priority = 0;
|
|
||||||
avih.videotrack.strh.language = 0;
|
|
||||||
avih.videotrack.strh.initial_frames = 0;
|
|
||||||
avih.videotrack.strh.start = 0;
|
|
||||||
avih.videotrack.strh.suggested_buffer_size = vfmt.suggested_buffer_size;
|
|
||||||
avih.videotrack.strh.quality = vfmt.quality;
|
|
||||||
avih.videotrack.strf.width = width;
|
|
||||||
avih.videotrack.strf.height = height;
|
|
||||||
avih.videotrack.strf.planes = vfmt.planes;
|
|
||||||
avih.videotrack.strf.bit_count = vfmt.bit_count;
|
|
||||||
avih.videotrack.strf.compression = vfmt.compression;
|
|
||||||
avih.videotrack.strf.size_image = (vfmt.bit_count + 7) / 8 * width * height;
|
|
||||||
avih.videotrack.strf.resolution_x = vfmt.resolution_x;
|
|
||||||
avih.videotrack.strf.resolution_y = vfmt.resolution_y;
|
|
||||||
avih.videotrack.strf.clr_used = vfmt.clr_used;
|
|
||||||
avih.videotrack.strf.clr_important = vfmt.clr_important;
|
|
||||||
avih.videotrack.strf.fps_n = fps_n;
|
|
||||||
avih.videotrack.strf.fps_d = fps_d;
|
|
||||||
avih.audiotrack.strh.handler = 0;
|
|
||||||
avih.audiotrack.strh.flags = 0;
|
|
||||||
avih.audiotrack.strh.priority = 0;
|
|
||||||
avih.audiotrack.strh.language = 0;
|
|
||||||
avih.audiotrack.strh.initial_frames = 0;
|
|
||||||
avih.audiotrack.strh.start = 0;
|
|
||||||
avih.audiotrack.strh.suggested_buffer_size = afmt.suggested_buffer_size;
|
|
||||||
avih.audiotrack.strh.quality = afmt.quality;
|
|
||||||
avih.audiotrack.strf.format_tag = afmt.format_tag;
|
|
||||||
avih.audiotrack.strf.channels = channels;
|
|
||||||
avih.audiotrack.strf.samples_per_second = samplerate;
|
|
||||||
avih.audiotrack.strf.average_bytes_per_second = afmt.average_rate;
|
|
||||||
avih.audiotrack.strf.block_align = afmt.alignment;
|
|
||||||
avih.audiotrack.strf.bits_per_sample = afmt.bitdepth;
|
|
||||||
avih.audiotrack.strf.blocksize = channels * (afmt.bitdepth + 7) / 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PADGRANULARITY 2
|
#define PADGRANULARITY 2
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,8 +106,8 @@ void avi_output_stream::start(std::ostream& out, avi_video_codec& _vcodec, avi_a
|
||||||
avih.videotrack.strh.start = 0;
|
avih.videotrack.strh.start = 0;
|
||||||
avih.videotrack.strh.suggested_buffer_size = vfmt.suggested_buffer_size;
|
avih.videotrack.strh.suggested_buffer_size = vfmt.suggested_buffer_size;
|
||||||
avih.videotrack.strh.quality = vfmt.quality;
|
avih.videotrack.strh.quality = vfmt.quality;
|
||||||
avih.videotrack.strf.width = width;
|
avih.videotrack.strf.width = vfmt.width;
|
||||||
avih.videotrack.strf.height = height;
|
avih.videotrack.strf.height = vfmt.height;
|
||||||
avih.videotrack.strf.planes = vfmt.planes;
|
avih.videotrack.strf.planes = vfmt.planes;
|
||||||
avih.videotrack.strf.bit_count = vfmt.bit_count;
|
avih.videotrack.strf.bit_count = vfmt.bit_count;
|
||||||
avih.videotrack.strf.compression = vfmt.compression;
|
avih.videotrack.strf.compression = vfmt.compression;
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace
|
||||||
prevframe.resize(3 * ewidth * eheight);
|
prevframe.resize(3 * ewidth * eheight);
|
||||||
memset(&row[0], 0, 3 * ewidth);
|
memset(&row[0], 0, 3 * ewidth);
|
||||||
memset(&prevframe[0], 0, 3 * ewidth * eheight);
|
memset(&prevframe[0], 0, 3 * ewidth * eheight);
|
||||||
avi_video_codec::format fmt(0x44435343, 24);
|
avi_video_codec::format fmt(ewidth, eheight, 0x44435343, 24);
|
||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,26 +102,25 @@ namespace
|
||||||
out.payload[0] = (keyframe ? 0x3 : 0x2) | (level << 4);
|
out.payload[0] = (keyframe ? 0x3 : 0x2) | (level << 4);
|
||||||
out.payload[1] = 8; //RGB24.
|
out.payload[1] = 8; //RGB24.
|
||||||
|
|
||||||
uint32_t iy = 0;
|
for(uint32_t y = 0; y < eheight; y++) {
|
||||||
for(uint32_t y = eheight - 1; y < eheight; y--, iy++) {
|
|
||||||
bool done = true;
|
bool done = true;
|
||||||
if(y >= iheight)
|
if(y < eheight - iheight)
|
||||||
readrow(NULL);
|
readrow(NULL);
|
||||||
else
|
else
|
||||||
readrow(data + y * iwidth);
|
readrow(data + (eheight - y - 1) * iwidth);
|
||||||
if(keyframe) {
|
if(keyframe) {
|
||||||
memcpy(&prevframe[3 * iy * ewidth], &row[0], 3 * ewidth);
|
memcpy(&prevframe[3 * y * ewidth], &row[0], 3 * ewidth);
|
||||||
} else {
|
} else {
|
||||||
//Ew, we need to have prevframe = row, row = row - prevframe at the same time.
|
//Ew, we need to have prevframe = row, row = row - prevframe at the same time.
|
||||||
for(unsigned i = 0; i < 3 * ewidth; i++) {
|
for(unsigned i = 0; i < 3 * ewidth; i++) {
|
||||||
uint8_t tmp = row[i];
|
uint8_t tmp = row[i];
|
||||||
row[i] -= prevframe[3 * iy * ewidth + i];
|
row[i] -= prevframe[3 * y * ewidth + i];
|
||||||
prevframe[3 * iy * ewidth + i] = tmp;
|
prevframe[3 * y * ewidth + i] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zlib.next_in = &row[0];
|
zlib.next_in = &row[0];
|
||||||
zlib.avail_in = row.size();
|
zlib.avail_in = row.size();
|
||||||
if(y == 0)
|
if(y == eheight - 1)
|
||||||
done = false;
|
done = false;
|
||||||
while(zlib.avail_in || !done) {
|
while(zlib.avail_in || !done) {
|
||||||
//Make space in output buffer.
|
//Make space in output buffer.
|
||||||
|
@ -135,7 +134,7 @@ namespace
|
||||||
zlib.avail_out = ctmp.size();
|
zlib.avail_out = ctmp.size();
|
||||||
buffer_loaded = true;
|
buffer_loaded = true;
|
||||||
}
|
}
|
||||||
r = deflate(&zlib, (y == 0) ? Z_FINISH : 0);
|
r = deflate(&zlib, (y == eheight - 1) ? Z_FINISH : 0);
|
||||||
if(r == Z_STREAM_END)
|
if(r == Z_STREAM_END)
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace
|
||||||
ready_flag = true;
|
ready_flag = true;
|
||||||
row.resize(3 * ewidth);
|
row.resize(3 * ewidth);
|
||||||
memset(&row[0], 0, 3 * ewidth);
|
memset(&row[0], 0, 3 * ewidth);
|
||||||
avi_video_codec::format fmt(0, 24); //Is 0 correct value for compression?
|
avi_video_codec::format fmt(ewidth, eheight, 0, 24); //Is 0 correct value for compression?
|
||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +53,10 @@ namespace
|
||||||
uint32_t s = 0;
|
uint32_t s = 0;
|
||||||
for(uint32_t y = 0; y < eheight; y++) {
|
for(uint32_t y = 0; y < eheight; y++) {
|
||||||
bool done = true;
|
bool done = true;
|
||||||
if(y >= iheight)
|
if(y < eheight - iheight)
|
||||||
readrow(NULL);
|
readrow(NULL);
|
||||||
else
|
else
|
||||||
readrow(data + (iheight - y - 1) * iwidth);
|
readrow(data + (eheight - y - 1) * iwidth);
|
||||||
memcpy(&out.payload[3 * ewidth * y], &row[0], 3 * ewidth);
|
memcpy(&out.payload[3 * ewidth * y], &row[0], 3 * ewidth);
|
||||||
}
|
}
|
||||||
out.typecode = 0x6264;
|
out.typecode = 0x6264;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "video/avi/writer.hpp"
|
#include "video/avi/writer.hpp"
|
||||||
|
#include "core/misc.hpp"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
|
@ -72,6 +73,8 @@ void avi_writer::flush(bool force)
|
||||||
aviout.start(avifile, vcodec, acodec, curwidth, curheight, curfps_n, curfps_d, samplerate,
|
aviout.start(avifile, vcodec, acodec, curwidth, curheight, curfps_n, curfps_d, samplerate,
|
||||||
channels);
|
channels);
|
||||||
closed = false;
|
closed = false;
|
||||||
|
messages << "Start AVI: " << curwidth << "x" << curheight << "@" << curfps_n << "/" << curfps_d
|
||||||
|
<< " to '" << aviname << "'" << std::endl;
|
||||||
}
|
}
|
||||||
if(aviout.readqueue(f.data, aqueue, force))
|
if(aviout.readqueue(f.data, aqueue, force))
|
||||||
vqueue.pop_front();
|
vqueue.pop_front();
|
||||||
|
|
Loading…
Add table
Reference in a new issue