Remove unused VideoRecorder from Atlas.
This was SVN commit r14181.
This commit is contained in:
parent
d459e97d33
commit
47b26e56d3
@ -1,448 +0,0 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#define USE_FFMPEG 0
|
||||
|
||||
#include "FFmpeg.h"
|
||||
|
||||
/*
|
||||
|
||||
Code originally taken from ffmpeg's output_example.c
|
||||
This is all rather hacked together and unreliable. In particular, I should:
|
||||
* Change the fprintf/exit error handling so that it works in Atlas.
|
||||
* Send all the logging output to wx too.
|
||||
* Support variable bitrate (set qscale to 1 (best) .. 31 (worst), sameq)
|
||||
* See if other codecs (particularly lossless ones) could be made to work.
|
||||
(Currently it half assumes that it's passed a .mp4 filename.)
|
||||
* See if other compression parameters would give better quality/speed/etc.
|
||||
* Make the frame size variable.
|
||||
* Tidy everything up a bit.
|
||||
|
||||
Please complain if I forget to do those things.
|
||||
|
||||
*/
|
||||
#if USE_FFMPEG
|
||||
|
||||
#ifdef __GNUC__
|
||||
// ugly hack to make recent versions of FFmpeg work
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#undef _STDINT_H
|
||||
#undef _STDINT_H_
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "FFmpeg.h"
|
||||
#if _MSC_VER // HACK
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable: 4100 4505 4510 4610)
|
||||
// Doesn't have inttypes.h, so cheat before including the ffmpeg headers
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
#endif
|
||||
|
||||
#define WXUNUSED(arg)
|
||||
|
||||
extern "C" {
|
||||
#include "ffmpeg/avformat.h"
|
||||
#include "ffmpeg/swscale.h"
|
||||
}
|
||||
// (Have to use a sufficiently recent version to get swscale - it needs the ~x86 keyword on Gentoo)
|
||||
|
||||
struct VideoEncoderImpl
|
||||
{
|
||||
int framerate;
|
||||
int bitrate;
|
||||
float duration;
|
||||
int width, height;
|
||||
|
||||
AVStream *video_st;
|
||||
AVFormatContext *oc;
|
||||
AVOutputFormat *fmt;
|
||||
|
||||
AVFrame *picture, *tmp_picture;
|
||||
uint8_t *video_outbuf;
|
||||
int frame_count, video_outbuf_size;
|
||||
|
||||
VideoEncoderImpl()
|
||||
{
|
||||
video_st = NULL;
|
||||
oc = NULL;
|
||||
fmt = NULL;
|
||||
|
||||
picture = NULL;
|
||||
tmp_picture = NULL;
|
||||
video_outbuf = NULL;
|
||||
frame_count = 0;
|
||||
video_outbuf_size = 0;
|
||||
}
|
||||
|
||||
AVStream *add_video_stream(AVFormatContext *oc, int codec_id)
|
||||
{
|
||||
AVCodecContext *c;
|
||||
AVStream *st;
|
||||
|
||||
st = av_new_stream(oc, 0);
|
||||
if (!st) {
|
||||
fprintf(stderr, "Could not alloc stream\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
c = st->codec;
|
||||
c->codec_id = (CodecID)codec_id;
|
||||
c->codec_type = CODEC_TYPE_VIDEO;
|
||||
|
||||
// c->bit_rate = bitrate*1000;
|
||||
// TODO: support compressed formats, using qscale
|
||||
|
||||
c->width = width;
|
||||
c->height = height;
|
||||
|
||||
c->time_base.den = framerate;
|
||||
c->time_base.num = 1;
|
||||
|
||||
// c->pix_fmt = PIX_FMT_YUV420P;
|
||||
c->pix_fmt = PIX_FMT_RGBA32;
|
||||
|
||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
AVFrame *alloc_picture(int pix_fmt, int width, int height)
|
||||
{
|
||||
AVFrame *picture;
|
||||
uint8_t *picture_buf;
|
||||
int size;
|
||||
|
||||
picture = avcodec_alloc_frame();
|
||||
if (!picture)
|
||||
return NULL;
|
||||
size = avpicture_get_size(pix_fmt, width, height);
|
||||
picture_buf = (uint8_t*)av_malloc(size);
|
||||
if (!picture_buf) {
|
||||
av_free(picture);
|
||||
return NULL;
|
||||
}
|
||||
avpicture_fill((AVPicture *)picture, picture_buf,
|
||||
pix_fmt, width, height);
|
||||
return picture;
|
||||
}
|
||||
|
||||
void open_video(AVFormatContext *oc, AVStream *st)
|
||||
{
|
||||
AVCodec *codec;
|
||||
AVCodecContext *c;
|
||||
|
||||
c = st->codec;
|
||||
|
||||
/* find the video encoder */
|
||||
codec = avcodec_find_encoder(c->codec_id);
|
||||
if (!codec) {
|
||||
fprintf(stderr, "codec not found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* open the codec */
|
||||
if (avcodec_open(c, codec) < 0) {
|
||||
fprintf(stderr, "could not open codec\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
video_outbuf = NULL;
|
||||
if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
|
||||
/* allocate output buffer */
|
||||
/* XXX: API change will be done */
|
||||
/* buffers passed into lav* can be allocated any way you prefer,
|
||||
as long as they're aligned enough for the architecture, and
|
||||
they're freed appropriately (such as using av_free for buffers
|
||||
allocated with av_malloc) */
|
||||
video_outbuf_size = c->width * c->height * 4;
|
||||
video_outbuf = (uint8_t*)av_malloc(video_outbuf_size);
|
||||
}
|
||||
|
||||
/* allocate the encoded raw picture */
|
||||
picture = alloc_picture(c->pix_fmt, c->width, c->height);
|
||||
if (!picture) {
|
||||
fprintf(stderr, "Could not allocate picture\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* if the output format is not YUV420P, then a temporary YUV420P
|
||||
picture is needed too. It is then converted to the required
|
||||
output format */
|
||||
tmp_picture = NULL;
|
||||
if (c->pix_fmt != PIX_FMT_RGB24) {
|
||||
tmp_picture = alloc_picture(PIX_FMT_RGB24, c->width, c->height);
|
||||
if (!tmp_picture) {
|
||||
fprintf(stderr, "Could not allocate temporary picture\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void copy_rgb_image(AVFrame *pict, int width, int height, const unsigned char* buffer)
|
||||
{
|
||||
for(int y=0;y<height;y++) {
|
||||
memcpy(&pict->data[0][y * pict->linesize[0]], buffer+y*width*3, width*3);
|
||||
}
|
||||
}
|
||||
|
||||
void write_video_frame(AVFormatContext *oc, AVStream *st, const unsigned char* buffer)
|
||||
{
|
||||
AVCodecContext *c;
|
||||
static struct SwsContext *img_convert_ctx;
|
||||
int out_size, ret;
|
||||
|
||||
c = st->codec;
|
||||
|
||||
if (!buffer || frame_count >= (int)(duration*framerate)) {
|
||||
/* no more frame to compress. The codec has a latency of a few
|
||||
frames if using B frames, so we get the last frames by
|
||||
passing the same picture again */
|
||||
} else {
|
||||
if (c->pix_fmt != PIX_FMT_RGB24) {
|
||||
/* as we only generate a YUV420P picture, we must convert it
|
||||
to the codec pixel format if needed */
|
||||
if (img_convert_ctx == NULL) {
|
||||
img_convert_ctx = sws_getContext(c->width, c->height,
|
||||
PIX_FMT_RGB24,
|
||||
c->width, c->height,
|
||||
c->pix_fmt,
|
||||
SWS_BICUBIC, NULL, NULL, NULL);
|
||||
if (img_convert_ctx == NULL) {
|
||||
fprintf(stderr, "Cannot initialize the conversion context\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
copy_rgb_image(tmp_picture, c->width, c->height, buffer);
|
||||
sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,
|
||||
0, c->height, picture->data, picture->linesize);
|
||||
} else {
|
||||
copy_rgb_image(picture, c->width, c->height, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (oc->oformat->flags & AVFMT_RAWPICTURE) {
|
||||
/* raw video case. The API will change slightly in the near
|
||||
future for that */
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
pkt.flags |= PKT_FLAG_KEY;
|
||||
pkt.stream_index= st->index;
|
||||
pkt.data= (uint8_t *)picture;
|
||||
pkt.size= sizeof(AVPicture);
|
||||
|
||||
ret = av_write_frame(oc, &pkt);
|
||||
} else {
|
||||
/* encode the image */
|
||||
out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
|
||||
/* if zero size, it means the image was buffered */
|
||||
if (out_size > 0) {
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
if (c->coded_frame->pts == AV_NOPTS_VALUE)
|
||||
pkt.pts = AV_NOPTS_VALUE;
|
||||
else
|
||||
pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
|
||||
if(c->coded_frame->key_frame)
|
||||
pkt.flags |= PKT_FLAG_KEY;
|
||||
pkt.stream_index= st->index;
|
||||
pkt.data= video_outbuf;
|
||||
pkt.size= out_size;
|
||||
|
||||
/* write the compressed frame in the media file */
|
||||
ret = av_write_frame(oc, &pkt);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error while writing video frame\n");
|
||||
exit(1);
|
||||
}
|
||||
frame_count++;
|
||||
}
|
||||
|
||||
void close_video(AVFormatContext *WXUNUSED(oc), AVStream *st)
|
||||
{
|
||||
avcodec_close(st->codec);
|
||||
av_free(picture->data[0]);
|
||||
av_free(picture);
|
||||
if (tmp_picture) {
|
||||
av_free(tmp_picture->data[0]);
|
||||
av_free(tmp_picture);
|
||||
}
|
||||
av_free(video_outbuf);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void log(void* WXUNUSED(v), int i, const char* format, va_list ap)
|
||||
{
|
||||
char buf[512];
|
||||
vsnprintf(buf, sizeof(buf), format, ap);
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
wxLogDebug(L"[%d] %hs", i, buf);
|
||||
}
|
||||
|
||||
VideoEncoder::VideoEncoder(const wxString& filenameStr, int framerate, int bitrate, float duration, int width, int height)
|
||||
: m(new VideoEncoderImpl)
|
||||
{
|
||||
wxCharBuffer filename = filenameStr.ToAscii();
|
||||
m->framerate = framerate;
|
||||
m->bitrate = bitrate;
|
||||
m->duration = duration;
|
||||
m->width = width;
|
||||
m->height = height;
|
||||
|
||||
/* initialize libavcodec, and register all codecs and formats */
|
||||
av_register_all();
|
||||
|
||||
av_log_set_callback(&log);
|
||||
|
||||
/* auto detect the output format from the name. default is mpeg. */
|
||||
m->fmt = guess_format(NULL, filename, NULL);
|
||||
if (!m->fmt) {
|
||||
fprintf(stderr, "Could not deduce output format from file extension: using MPEG.\n");
|
||||
m->fmt = guess_format("mpeg", NULL, NULL);
|
||||
}
|
||||
if (!m->fmt) {
|
||||
fprintf(stderr, "Could not find suitable output format\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* allocate the output media context */
|
||||
m->oc = av_alloc_format_context();
|
||||
if (!m->oc) {
|
||||
fprintf(stderr, "Memory error\n");
|
||||
exit(1);
|
||||
}
|
||||
m->oc->oformat = m->fmt;
|
||||
strncpy(m->oc->filename, filename, sizeof(m->oc->filename));
|
||||
m->oc->filename[sizeof(m->oc->filename) - 1] = '\0';
|
||||
|
||||
/* add the audio and video streams using the default format codecs
|
||||
and initialize the codecs */
|
||||
// m->video_st = NULL;
|
||||
// if (m->fmt->video_codec != CODEC_ID_NONE) {
|
||||
// m->video_st = m->add_video_stream(m->oc, m->fmt->video_codec);
|
||||
// }
|
||||
m->video_st = m->add_video_stream(m->oc, CODEC_ID_FFV1);
|
||||
|
||||
/* set the output parameters (must be done even if no
|
||||
parameters). */
|
||||
if (av_set_parameters(m->oc, NULL) < 0) {
|
||||
fprintf(stderr, "Invalid output format parameters\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dump_format(m->oc, 0, filename, 1);
|
||||
|
||||
/* now that all the parameters are set, we can open the audio and
|
||||
video codecs and allocate the necessary encode buffers */
|
||||
if (m->video_st)
|
||||
m->open_video(m->oc, m->video_st);
|
||||
|
||||
/* open the output file, if needed */
|
||||
if (!(m->fmt->flags & AVFMT_NOFILE)) {
|
||||
if (url_fopen(&m->oc->pb, filename, URL_WRONLY) < 0) {
|
||||
fprintf(stderr, "Could not open '%s'\n", filename.data());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* write the stream header, if any */
|
||||
av_write_header(m->oc);
|
||||
|
||||
}
|
||||
|
||||
void VideoEncoder::Frame(const unsigned char* buffer)
|
||||
{
|
||||
double video_pts = (double)m->video_st->pts.val * m->video_st->time_base.num / m->video_st->time_base.den;
|
||||
if (video_pts >= m->duration)
|
||||
return;
|
||||
|
||||
m->write_video_frame(m->oc, m->video_st, buffer);
|
||||
}
|
||||
|
||||
VideoEncoder::~VideoEncoder()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
double video_pts = (double)m->video_st->pts.val * m->video_st->time_base.num / m->video_st->time_base.den;
|
||||
if (video_pts >= m->duration)
|
||||
break;
|
||||
|
||||
m->write_video_frame(m->oc, m->video_st, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* close each codec */
|
||||
if (m->video_st)
|
||||
m->close_video(m->oc, m->video_st);
|
||||
|
||||
/* write the trailer, if any */
|
||||
av_write_trailer(m->oc);
|
||||
|
||||
/* free the streams */
|
||||
for(unsigned int i = 0; i < m->oc->nb_streams; i++) {
|
||||
av_freep(&m->oc->streams[i]->codec);
|
||||
av_freep(&m->oc->streams[i]);
|
||||
}
|
||||
|
||||
if (!(m->fmt->flags & AVFMT_NOFILE)) {
|
||||
/* close the output file */
|
||||
url_fclose(&m->oc->pb);
|
||||
}
|
||||
|
||||
/* free the stream */
|
||||
av_free(m->oc);
|
||||
|
||||
|
||||
delete m;
|
||||
}
|
||||
|
||||
#else // !USE_FFMPEG:
|
||||
|
||||
VideoEncoder::VideoEncoder(const wxString& WXUNUSED(filenameStr), int WXUNUSED(framerate), int WXUNUSED(bitrate), float WXUNUSED(duration), int WXUNUSED(width), int WXUNUSED(height))
|
||||
{
|
||||
}
|
||||
|
||||
void VideoEncoder::Frame(const unsigned char* WXUNUSED(buffer))
|
||||
{
|
||||
}
|
||||
|
||||
VideoEncoder::~VideoEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
#endif // !USE_FFMPEG
|
@ -1,34 +0,0 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_FFMPEG
|
||||
#define INCLUDED_FFMPEG
|
||||
|
||||
struct VideoEncoderImpl;
|
||||
|
||||
class VideoEncoder
|
||||
{
|
||||
public:
|
||||
VideoEncoder(const wxString& filename, int framerate, int bitrate, float duration, int width, int height);
|
||||
void Frame(const unsigned char* buffer);
|
||||
~VideoEncoder();
|
||||
|
||||
private:
|
||||
VideoEncoderImpl* m;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_FFMPEG
|
@ -1,207 +0,0 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "VideoRecorder.h"
|
||||
|
||||
#include "FFmpeg.h"
|
||||
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
class RecorderDialog : public wxDialog
|
||||
{
|
||||
enum
|
||||
{
|
||||
ID_FILENAME,
|
||||
ID_FILECHOOSE,
|
||||
ID_FRAMERATE,
|
||||
ID_BITRATE,
|
||||
ID_DURATION,
|
||||
ID_FILESIZE
|
||||
};
|
||||
|
||||
public:
|
||||
RecorderDialog(wxWindow* parent, float duration)
|
||||
: wxDialog(parent, wxID_ANY, (wxString)_("Video recording options")),
|
||||
m_Duration(duration)
|
||||
{
|
||||
wxArrayString framerates;
|
||||
framerates.Add(_T("10"));
|
||||
framerates.Add(_T("15"));
|
||||
framerates.Add(_T("25"));
|
||||
framerates.Add(_T("30"));
|
||||
framerates.Add(_T("60"));
|
||||
wxString framerateDefault = _T("25");
|
||||
|
||||
wxArrayString bitrates;
|
||||
bitrates.Add(_T("500"));
|
||||
bitrates.Add(_T("800"));
|
||||
bitrates.Add(_T("1200"));
|
||||
bitrates.Add(_T("1600"));
|
||||
bitrates.Add(_T("3200"));
|
||||
wxString bitrateDefault = _T("1200");
|
||||
|
||||
|
||||
wxSizer* filenameSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
filenameSizer->Add(new wxTextCtrl(this, ID_FILENAME, _T("")), wxSizerFlags().Proportion(1));
|
||||
filenameSizer->Add(new wxButton(this, ID_FILECHOOSE, _("Browse...")));
|
||||
|
||||
wxGridSizer* gridSizer = new wxGridSizer(4);
|
||||
|
||||
gridSizer->Add(new wxStaticText(this, -1, _("Framerate (fps)")), wxSizerFlags().Right().Border(wxRIGHT, 4));
|
||||
gridSizer->Add(new wxComboBox(this, ID_FRAMERATE, framerateDefault, wxDefaultPosition, wxDefaultSize, framerates), wxSizerFlags().Proportion(1).Expand());
|
||||
// TODO: use a wxValidator to only allow digits
|
||||
|
||||
gridSizer->Add(new wxStaticText(this, -1, _("Duration (seconds):")), wxSizerFlags().Right().Border(wxLEFT, 4));
|
||||
gridSizer->Add(new wxStaticText(this, ID_DURATION, wxString::Format(_T("%.1f"), m_Duration)), wxSizerFlags().Expand().Border(wxLEFT, 4));
|
||||
|
||||
gridSizer->Add(new wxStaticText(this, -1, _("Bitrate (Kbit/s)")), wxSizerFlags().Right().Border(wxRIGHT, 4));
|
||||
gridSizer->Add(new wxComboBox(this, ID_BITRATE, bitrateDefault, wxDefaultPosition, wxDefaultSize, bitrates), wxSizerFlags().Proportion(1).Expand());
|
||||
|
||||
gridSizer->Add(new wxStaticText(this, -1, _("Estimated file size:")), wxSizerFlags().Right().Border(wxRIGHT, 4));
|
||||
gridSizer->Add(new wxStaticText(this, ID_FILESIZE, L"???"), wxSizerFlags().Expand().Border(wxLEFT, 4));
|
||||
|
||||
RecalculateSizes_();
|
||||
|
||||
wxSizer* gridSizerBox = new wxStaticBoxSizer(wxVERTICAL, this, _("Compression options"));
|
||||
gridSizerBox->Add(gridSizer, wxSizerFlags().Border(wxALL, 10));
|
||||
|
||||
wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer();
|
||||
wxButton* okButton = new wxButton(this, wxID_OK, _("Save"));
|
||||
okButton->SetDefault();
|
||||
buttonSizer->AddButton(okButton);
|
||||
buttonSizer->AddButton(new wxButton(this, wxID_CANCEL, _("Cancel")));
|
||||
buttonSizer->Realize();
|
||||
|
||||
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
sizer->Add(filenameSizer, wxSizerFlags().Border(wxALL, 10).Expand());
|
||||
sizer->Add(gridSizerBox, wxSizerFlags().Border(wxALL, 10));
|
||||
sizer->Add(buttonSizer, wxSizerFlags().Border(wxALL, 10).Centre());
|
||||
|
||||
SetSizer(sizer);
|
||||
sizer->SetSizeHints(this);
|
||||
}
|
||||
|
||||
// Outputs:
|
||||
wxString m_Filename;
|
||||
unsigned long m_Framerate;
|
||||
unsigned long m_Bitrate;
|
||||
|
||||
protected:
|
||||
|
||||
void OnButtonOK(wxCommandEvent& event)
|
||||
{
|
||||
wxTextCtrl* filenameWin = wxDynamicCast(FindWindow(ID_FILENAME), wxTextCtrl);
|
||||
wxComboBox* framerateWin = wxDynamicCast(FindWindow(ID_FRAMERATE), wxComboBox);
|
||||
wxComboBox* bitrateWin = wxDynamicCast(FindWindow(ID_BITRATE), wxComboBox);
|
||||
|
||||
wxCHECK(filenameWin && framerateWin && bitrateWin, );
|
||||
|
||||
m_Filename = filenameWin->GetValue();
|
||||
if (m_Filename.IsEmpty())
|
||||
{
|
||||
wxLogError(_("No filename specified."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!framerateWin->GetValue().ToULong(&m_Framerate) ||
|
||||
!bitrateWin->GetValue().ToULong(&m_Bitrate))
|
||||
{
|
||||
wxLogError(_("Invalid framerate/bitrate."));
|
||||
return;
|
||||
}
|
||||
|
||||
event.Skip(); // janwas: wxDialog::OnOK has been removed in 2.8 wxw; see http://wxforum.shadonet.com/viewtopic.php?t=11103
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void RecalculateSizes(wxCommandEvent& WXUNUSED(event)) { RecalculateSizes_(); }
|
||||
void RecalculateSizes_()
|
||||
{
|
||||
wxComboBox* framerateWin = wxDynamicCast(FindWindow(ID_FRAMERATE), wxComboBox);
|
||||
wxComboBox* bitrateWin = wxDynamicCast(FindWindow(ID_BITRATE), wxComboBox);
|
||||
wxStaticText* filesizeWin = wxDynamicCast(FindWindow(ID_FILESIZE), wxStaticText);
|
||||
wxCHECK(framerateWin && bitrateWin && filesizeWin, );
|
||||
unsigned long framerate = 0, bitrate = 0;
|
||||
if (!framerateWin->GetValue().ToULong(&framerate) || !bitrateWin->GetValue().ToULong(&bitrate))
|
||||
return;
|
||||
|
||||
int size = m_Duration * bitrate * 1000/8;
|
||||
wxString sizeStr;
|
||||
if (size < 1024*1024) sizeStr = wxString::Format(_T("~%.0f KiB"), (float)size/1024);
|
||||
else if (size < 1024*1024*100) sizeStr = wxString::Format(_T("~%.1f MiB"), (float)size/(1024*1024));
|
||||
else if (size < 1024*1024*1024) sizeStr = wxString::Format(_T("~%.0f MiB"), (float)size/(1024*1024));
|
||||
else sizeStr = wxString::Format(_T("~%.2f GiB"), (float)size/(1024*1024*1024));
|
||||
filesizeWin->SetLabel(sizeStr);
|
||||
}
|
||||
|
||||
void FileBrowse(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxTextCtrl* filenameWin = wxDynamicCast(FindWindow(ID_FILENAME), wxTextCtrl);
|
||||
wxCHECK(filenameWin, );
|
||||
|
||||
wxFileDialog dlg (this, wxFileSelectorPromptStr, filenameWin->GetValue(), filenameWin->GetValue(), _("MP4 files (*.mp4)|*.mp4"), wxFD_SAVE);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
|
||||
filenameWin->SetValue(dlg.GetPath());
|
||||
}
|
||||
|
||||
float m_Duration;
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(RecorderDialog, wxDialog)
|
||||
EVT_COMBOBOX(ID_FRAMERATE, RecorderDialog::RecalculateSizes)
|
||||
EVT_COMBOBOX(ID_BITRATE, RecorderDialog::RecalculateSizes)
|
||||
EVT_TEXT(ID_FRAMERATE, RecorderDialog::RecalculateSizes)
|
||||
EVT_TEXT(ID_BITRATE, RecorderDialog::RecalculateSizes)
|
||||
EVT_BUTTON(ID_FILECHOOSE, RecorderDialog::FileBrowse)
|
||||
EVT_BUTTON(wxID_OK, RecorderDialog::OnButtonOK)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
void callback(const sCinemaRecordCB* data, void* cbdata)
|
||||
{
|
||||
VideoEncoder* enc = (VideoEncoder*)cbdata;
|
||||
enc->Frame(data->buffer);
|
||||
}
|
||||
|
||||
void VideoRecorder::RecordCinematic(wxWindow* window, const wxString& trackName, float duration)
|
||||
{
|
||||
RecorderDialog dlg(window, duration);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
|
||||
wxStopWatch sw;
|
||||
|
||||
// int w = 320, h = 240;
|
||||
int w = 640, h = 480;
|
||||
|
||||
VideoEncoder venc (dlg.m_Filename, dlg.m_Framerate, dlg.m_Bitrate, duration, w, h);
|
||||
|
||||
qCinemaRecord qry((std::wstring)trackName.wc_str(), dlg.m_Framerate, duration, w, h, Callback<sCinemaRecordCB>(&callback, (void*)&venc));
|
||||
qry.Post();
|
||||
|
||||
wxLogMessage(_("Finished recording (took %.1f seconds)\n"), sw.Time()/1000.f);
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_VIDEORECORDER
|
||||
#define INCLUDED_VIDEORECORDER
|
||||
|
||||
class VideoRecorder
|
||||
{
|
||||
public:
|
||||
static void RecordCinematic(wxWindow* window, const wxString& trackName, float duration);
|
||||
};
|
||||
|
||||
#endif // INCLUDED_VIDEORECORDER
|
Loading…
Reference in New Issue
Block a user