Revert "Refactor movie capture to use FFMPEG only"
parent
7b52f23c97
commit
f731579681
|
@ -23,7 +23,8 @@ set(CELESTIA_SOURCES
|
|||
|
||||
if(ENABLE_FFMPEG)
|
||||
list(APPEND CELESTIA_SOURCES
|
||||
moviecapture.cpp
|
||||
ffmpegcapture.cpp
|
||||
ffmpegcapture.h
|
||||
moviecapture.h
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -87,13 +87,6 @@ static const float MinimumFOV = degToRad(0.001f);
|
|||
static float KeyRotationAccel = degToRad(120.0f);
|
||||
static float MouseRotationSensitivity = degToRad(1.0f);
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
enum CodecID
|
||||
{
|
||||
CEL_CODEC_ID_FFVHUFF = AV_CODEC_ID_FFVHUFF,
|
||||
CEL_CODEC_ID_H264 = AV_CODEC_ID_H264,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void warning(string s)
|
||||
{
|
||||
|
@ -176,10 +169,8 @@ CelestiaCore::CelestiaCore() :
|
|||
|
||||
CelestiaCore::~CelestiaCore()
|
||||
{
|
||||
#ifdef USE_FFMPEG
|
||||
if (movieCapture != nullptr)
|
||||
recordEnd();
|
||||
#endif
|
||||
|
||||
delete timer;
|
||||
delete renderer;
|
||||
|
@ -816,7 +807,6 @@ void CelestiaCore::keyDown(int key, int modifiers)
|
|||
case Key_F7:
|
||||
sim->setTargetSpeed(1.0_ly);
|
||||
break;
|
||||
#ifdef USE_FFMPEG
|
||||
case Key_F11:
|
||||
if (movieCapture != nullptr)
|
||||
{
|
||||
|
@ -830,7 +820,6 @@ void CelestiaCore::keyDown(int key, int modifiers)
|
|||
if (movieCapture != nullptr)
|
||||
recordEnd();
|
||||
break;
|
||||
#endif
|
||||
case Key_NumPad2:
|
||||
case Key_NumPad4:
|
||||
case Key_NumPad6:
|
||||
|
@ -1926,7 +1915,6 @@ void CelestiaCore::tick()
|
|||
// The time step is normally driven by the system clock; however, when
|
||||
// recording a movie, we fix the time step the frame rate of the movie.
|
||||
double dt = 0.0;
|
||||
#ifdef USE_FFMPEG
|
||||
if (movieCapture != nullptr && recording)
|
||||
{
|
||||
dt = 1.0 / movieCapture->getFrameRate();
|
||||
|
@ -1935,9 +1923,6 @@ void CelestiaCore::tick()
|
|||
{
|
||||
dt = sysTime - lastTime;
|
||||
}
|
||||
#else
|
||||
dt = sysTime - lastTime;
|
||||
#endif
|
||||
|
||||
// Pause script execution
|
||||
if (scriptState == ScriptPaused)
|
||||
|
@ -2147,10 +2132,8 @@ void CelestiaCore::draw()
|
|||
if (toggleAA)
|
||||
renderer->enableMSAA();
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
if (movieCapture != nullptr && recording)
|
||||
movieCapture->captureFrame();
|
||||
#endif
|
||||
|
||||
// Frame rate counter
|
||||
nFrames++;
|
||||
|
@ -3523,7 +3506,6 @@ void CelestiaCore::renderOverlay()
|
|||
overlay->setFont(font);
|
||||
}
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
if (movieCapture != nullptr)
|
||||
{
|
||||
int movieWidth = movieCapture->getWidth();
|
||||
|
@ -3571,7 +3553,6 @@ void CelestiaCore::renderOverlay()
|
|||
|
||||
overlay->restorePos();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (editMode)
|
||||
{
|
||||
|
@ -4417,33 +4398,25 @@ void CelestiaCore::setOverlayElements(int _overlayElements)
|
|||
overlayElements = _overlayElements;
|
||||
}
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
bool CelestiaCore::initMovieCapture(const fs::path &path, int width, int height,
|
||||
float fps, int64_t bitrate, int codec)
|
||||
void CelestiaCore::initMovieCapture(MovieCapture* mc)
|
||||
{
|
||||
if (movieCapture != nullptr)
|
||||
return false;
|
||||
|
||||
movieCapture = make_unique<celestia::MovieCapture>(getRenderer());
|
||||
movieCapture->setVideoCodec(static_cast<AVCodecID>(codec));
|
||||
movieCapture->setBitRate(bitrate);
|
||||
if (codec == CEL_CODEC_ID_H264)
|
||||
movieCapture->setEncoderOptions(getConfig()->x264EncoderOptions);
|
||||
else
|
||||
movieCapture->setEncoderOptions(getConfig()->ffvhEncoderOptions);
|
||||
|
||||
return movieCapture->start(path, width, height, fps);
|
||||
if (movieCapture == nullptr)
|
||||
movieCapture = mc;
|
||||
}
|
||||
|
||||
void CelestiaCore::recordBegin()
|
||||
{
|
||||
if (movieCapture != nullptr)
|
||||
{
|
||||
recording = true;
|
||||
movieCapture->recordingStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CelestiaCore::recordPause()
|
||||
{
|
||||
recording = false;
|
||||
if (movieCapture != nullptr) movieCapture->recordingStatus(false);
|
||||
}
|
||||
|
||||
void CelestiaCore::recordEnd()
|
||||
|
@ -4452,6 +4425,7 @@ void CelestiaCore::recordEnd()
|
|||
{
|
||||
recordPause();
|
||||
movieCapture->end();
|
||||
delete movieCapture;
|
||||
movieCapture = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -4465,7 +4439,6 @@ bool CelestiaCore::isRecording()
|
|||
{
|
||||
return recording;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CelestiaCore::flash(const string& s, double duration)
|
||||
{
|
||||
|
@ -4779,43 +4752,3 @@ void CelestiaCore::setLogFile(const fs::path &fn)
|
|||
fmt::fprintf(cerr, "Unable to open log file %s\n", fn.string());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
auto CelestiaCore::getSupportedMovieSizes() const
|
||||
-> celestia::util::array_view<MovieSize>
|
||||
{
|
||||
static std::array<MovieSize, 8> MovieSizes =
|
||||
{{
|
||||
{ 320, 240 },
|
||||
{ 640, 480 },
|
||||
{ 720, 480 },
|
||||
{ 720, 576 },
|
||||
{ 1024, 768 },
|
||||
{ 1280, 720 },
|
||||
{ 1920, 1080 },
|
||||
{ 3840, 2160 }
|
||||
}};
|
||||
return MovieSizes;
|
||||
}
|
||||
|
||||
auto CelestiaCore::getSupportedMovieFramerates() const
|
||||
-> celestia::util::array_view<float>
|
||||
{
|
||||
static std::array<float, 5> MovieFramerates =
|
||||
{
|
||||
15.0f, 24.0f, 25.0f, 29.97f, 30.0f
|
||||
};
|
||||
return MovieFramerates;
|
||||
}
|
||||
|
||||
auto CelestiaCore::getSupportedMovieCodecs() const
|
||||
-> celestia::util::array_view<MovieCodec>
|
||||
{
|
||||
static std::array<MovieCodec, 2> MovieCodecs =
|
||||
{{
|
||||
{ CEL_CODEC_ID_FFVHUFF, N_("Lossless") },
|
||||
{ CEL_CODEC_ID_H264, N_("Lossy (H.264)") }
|
||||
}};
|
||||
return MovieCodecs;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <celutil/filetype.h>
|
||||
#include <celutil/timer.h>
|
||||
#include <celutil/watcher.h>
|
||||
|
@ -29,9 +28,7 @@
|
|||
#include "configfile.h"
|
||||
#include "favorites.h"
|
||||
#include "destination.h"
|
||||
#ifdef USE_FFMPEG
|
||||
#include "moviecapture.h"
|
||||
#endif
|
||||
#include "view.h"
|
||||
#ifdef CELX
|
||||
#include <celscript/lua/celx.h>
|
||||
|
@ -58,18 +55,6 @@ public:
|
|||
virtual void update(const std::string&) = 0;
|
||||
};
|
||||
|
||||
struct MovieSize
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
struct MovieCodec
|
||||
{
|
||||
int codecId;
|
||||
const char *codecDescr;
|
||||
};
|
||||
|
||||
class CelestiaCore // : public Watchable<CelestiaCore>
|
||||
{
|
||||
public:
|
||||
|
@ -259,17 +244,12 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
void setTextEnterMode(int);
|
||||
int getTextEnterMode() const;
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
bool initMovieCapture(const fs::path &path, int width, int height, float fps, int64_t bitrate, int codec);
|
||||
void initMovieCapture(MovieCapture*);
|
||||
void recordBegin();
|
||||
void recordPause();
|
||||
void recordEnd();
|
||||
bool isCaptureActive();
|
||||
bool isRecording();
|
||||
celestia::util::array_view<MovieSize> getSupportedMovieSizes() const;
|
||||
celestia::util::array_view<float> getSupportedMovieFramerates() const;
|
||||
celestia::util::array_view<MovieCodec> getSupportedMovieCodecs() const;
|
||||
#endif
|
||||
|
||||
void runScript(const fs::path& filename, bool i18n = true);
|
||||
void cancelScript();
|
||||
|
@ -491,10 +471,8 @@ class CelestiaCore // : public Watchable<CelestiaCore>
|
|||
bool shiftKeysPressed[KeyCount];
|
||||
double KeyAccel{ 1.0 };
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
std::unique_ptr<celestia::MovieCapture> movieCapture;
|
||||
MovieCapture* movieCapture{ nullptr };
|
||||
bool recording{ false };
|
||||
#endif
|
||||
|
||||
Alerter* alerter{ nullptr };
|
||||
std::vector<CelestiaWatcher*> watchers;
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
#define AVCODEC_DEBUG 0
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <fmt/format.h>
|
||||
#include "ffmpegcapture.h"
|
||||
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
extern "C"
|
||||
{
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/timestamp.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
@ -15,18 +12,17 @@ extern "C"
|
|||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
#include <celengine/render.h>
|
||||
#include "moviecapture.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace celestia
|
||||
{
|
||||
// a wrapper around a single output AVStream
|
||||
class MovieCapturePrivate
|
||||
class FFMPEGCapturePrivate
|
||||
{
|
||||
MovieCapturePrivate() = default;
|
||||
~MovieCapturePrivate();
|
||||
FFMPEGCapturePrivate() = default;
|
||||
~FFMPEGCapturePrivate();
|
||||
|
||||
bool init(const fs::path& fn);
|
||||
bool addStream(int w, int h, float fps);
|
||||
|
@ -45,7 +41,7 @@ class MovieCapturePrivate
|
|||
AVFrame *tmpfr { nullptr };
|
||||
AVCodecContext *enc { nullptr };
|
||||
AVFormatContext *oc { nullptr };
|
||||
const AVCodec *vc { nullptr };
|
||||
AVCodec *vc { nullptr };
|
||||
AVPacket *pkt { nullptr };
|
||||
SwsContext *swsc { nullptr };
|
||||
|
||||
|
@ -54,7 +50,7 @@ class MovieCapturePrivate
|
|||
// pts of the next frame that will be generated
|
||||
int64_t nextPts { 0 };
|
||||
// requested bitrate
|
||||
int64_t bitrate { 400000 };
|
||||
int64_t bit_rate { 400000 };
|
||||
|
||||
AVCodecID vc_id { AV_CODEC_ID_FFVHUFF };
|
||||
AVPixelFormat format { AV_PIX_FMT_NONE };
|
||||
|
@ -69,22 +65,22 @@ class MovieCapturePrivate
|
|||
#if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)) // ffmpeg < 4.0
|
||||
static bool registered;
|
||||
#endif
|
||||
friend class MovieCapture;
|
||||
friend class FFMPEGCapture;
|
||||
};
|
||||
|
||||
#if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)) // ffmpeg < 4.0
|
||||
bool MovieCapturePrivate::registered = false;
|
||||
bool FFMPEGCapturePrivate::registered = false;
|
||||
#endif
|
||||
|
||||
bool MovieCapturePrivate::init(const fs::path& filename)
|
||||
bool FFMPEGCapturePrivate::init(const fs::path& filename)
|
||||
{
|
||||
this->filename = filename;
|
||||
|
||||
#if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)) // ffmpeg < 4.0
|
||||
if (!MovieCapturePrivate::registered)
|
||||
if (!FFMPEGCapturePrivate::registered)
|
||||
{
|
||||
av_register_all();
|
||||
MovieCapturePrivate::registered = true;
|
||||
FFMPEGCapturePrivate::registered = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -96,7 +92,7 @@ bool MovieCapturePrivate::init(const fs::path& filename)
|
|||
return oc != nullptr;
|
||||
}
|
||||
|
||||
bool MovieCapturePrivate::isSupportedPixelFormat(enum AVPixelFormat format) const
|
||||
bool FFMPEGCapturePrivate::isSupportedPixelFormat(enum AVPixelFormat format) const
|
||||
{
|
||||
const enum AVPixelFormat *p = vc->pix_fmts;
|
||||
if (p == nullptr)
|
||||
|
@ -193,7 +189,7 @@ static void listEncoderParameters(const AVCodec *vc)
|
|||
}
|
||||
#endif
|
||||
|
||||
int MovieCapturePrivate::writePacket()
|
||||
int FFMPEGCapturePrivate::writePacket()
|
||||
{
|
||||
// rescale output packet timestamp values from codec to stream timebase
|
||||
av_packet_rescale_ts(pkt, enc->time_base, st->time_base);
|
||||
|
@ -204,7 +200,7 @@ int MovieCapturePrivate::writePacket()
|
|||
}
|
||||
|
||||
// add an output stream
|
||||
bool MovieCapturePrivate::addStream(int width, int height, float fps)
|
||||
bool FFMPEGCapturePrivate::addStream(int width, int height, float fps)
|
||||
{
|
||||
this->fps = fps;
|
||||
|
||||
|
@ -235,12 +231,13 @@ bool MovieCapturePrivate::addStream(int width, int height, float fps)
|
|||
return false;
|
||||
}
|
||||
|
||||
enc->codec_id = vc_id;
|
||||
enc->bit_rate = bitrate;
|
||||
enc->codec_id = oc->oformat->video_codec = vc_id;
|
||||
|
||||
enc->bit_rate = bit_rate;
|
||||
#if 0
|
||||
enc->rc_min_rate = ...;
|
||||
enc->rc_max_rate = ...;
|
||||
enc->bitrate_tolerance = 0;
|
||||
enc->bit_rate_tolerance = 0;
|
||||
#endif
|
||||
// Resolution must be a multiple of two
|
||||
enc->width = width;
|
||||
|
@ -290,7 +287,7 @@ bool MovieCapturePrivate::addStream(int width, int height, float fps)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MovieCapturePrivate::start()
|
||||
bool FFMPEGCapturePrivate::start()
|
||||
{
|
||||
// open the output file, if needed
|
||||
if ((oc->oformat->flags & AVFMT_NOFILE) == 0)
|
||||
|
@ -320,7 +317,7 @@ bool MovieCapturePrivate::start()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MovieCapturePrivate::openVideo()
|
||||
bool FFMPEGCapturePrivate::openVideo()
|
||||
{
|
||||
AVDictionary *opts = nullptr;
|
||||
const char *str = "";
|
||||
|
@ -419,7 +416,7 @@ static void captureImage(AVFrame *pict, int width, int height, const Renderer *r
|
|||
|
||||
// encode one video frame and send it to the muxer
|
||||
// return 1 when encoding is finished, 0 otherwise
|
||||
bool MovieCapturePrivate::writeVideoFrame(bool finalize)
|
||||
bool FFMPEGCapturePrivate::writeVideoFrame(bool finalize)
|
||||
{
|
||||
AVFrame *frame = finalize ? nullptr : this->frame;
|
||||
const int bytesPerPixel = hasAlpha ? 4 : 3;
|
||||
|
@ -451,9 +448,7 @@ bool MovieCapturePrivate::writeVideoFrame(bool finalize)
|
|||
frame->pts = nextPts++;
|
||||
}
|
||||
|
||||
#if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100))
|
||||
av_init_packet(pkt);
|
||||
#endif
|
||||
|
||||
// encode the image
|
||||
if (avcodec_send_frame(enc, frame) < 0)
|
||||
|
@ -485,7 +480,7 @@ bool MovieCapturePrivate::writeVideoFrame(bool finalize)
|
|||
return true;
|
||||
}
|
||||
|
||||
void MovieCapturePrivate::finish()
|
||||
void FFMPEGCapturePrivate::finish()
|
||||
{
|
||||
writeVideoFrame(true);
|
||||
|
||||
|
@ -499,7 +494,7 @@ void MovieCapturePrivate::finish()
|
|||
avio_closep(&oc->pb);
|
||||
}
|
||||
|
||||
MovieCapturePrivate::~MovieCapturePrivate()
|
||||
FFMPEGCapturePrivate::~FFMPEGCapturePrivate()
|
||||
{
|
||||
avcodec_free_context(&enc);
|
||||
av_frame_free(&frame);
|
||||
|
@ -509,40 +504,41 @@ MovieCapturePrivate::~MovieCapturePrivate()
|
|||
av_packet_free(&pkt);
|
||||
}
|
||||
|
||||
MovieCapture::MovieCapture(const Renderer *r) :
|
||||
d(new MovieCapturePrivate)
|
||||
FFMPEGCapture::FFMPEGCapture(const Renderer *r) :
|
||||
MovieCapture(r),
|
||||
d(new FFMPEGCapturePrivate)
|
||||
{
|
||||
d->renderer = r;
|
||||
d->hasAlpha = r->getPreferredCaptureFormat() == PixelFormat::RGBA;
|
||||
d->format = d->hasAlpha ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24;
|
||||
}
|
||||
|
||||
MovieCapture::~MovieCapture()
|
||||
FFMPEGCapture::~FFMPEGCapture()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
int MovieCapture::getFrameCount() const
|
||||
int FFMPEGCapture::getFrameCount() const
|
||||
{
|
||||
return d->nextPts;
|
||||
}
|
||||
|
||||
int MovieCapture::getWidth() const
|
||||
int FFMPEGCapture::getWidth() const
|
||||
{
|
||||
return d->enc->width;
|
||||
}
|
||||
|
||||
int MovieCapture::getHeight() const
|
||||
int FFMPEGCapture::getHeight() const
|
||||
{
|
||||
return d->enc->height;
|
||||
}
|
||||
|
||||
float MovieCapture::getFrameRate() const
|
||||
float FFMPEGCapture::getFrameRate() const
|
||||
{
|
||||
return d->fps;
|
||||
}
|
||||
|
||||
bool MovieCapture::start(const fs::path& filename, int width, int height, float fps)
|
||||
bool FFMPEGCapture::start(const fs::path& filename, int width, int height, float fps)
|
||||
{
|
||||
if (!d->init(filename) ||
|
||||
!d->addStream(width, height, fps) ||
|
||||
|
@ -557,7 +553,7 @@ bool MovieCapture::start(const fs::path& filename, int width, int height, float
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MovieCapture::end()
|
||||
bool FFMPEGCapture::end()
|
||||
{
|
||||
if (!d->capturing)
|
||||
return false;
|
||||
|
@ -569,23 +565,22 @@ bool MovieCapture::end()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MovieCapture::captureFrame()
|
||||
bool FFMPEGCapture::captureFrame()
|
||||
{
|
||||
return d->capturing && d->writeVideoFrame();
|
||||
}
|
||||
|
||||
void MovieCapture::setVideoCodec(AVCodecID vc_id)
|
||||
void FFMPEGCapture::setVideoCodec(AVCodecID vc_id)
|
||||
{
|
||||
d->vc_id = vc_id;
|
||||
}
|
||||
|
||||
void MovieCapture::setBitRate(int64_t bitrate)
|
||||
void FFMPEGCapture::setBitRate(int64_t bit_rate)
|
||||
{
|
||||
d->bitrate = bitrate;
|
||||
d->bit_rate = bit_rate;
|
||||
}
|
||||
|
||||
void MovieCapture::setEncoderOptions(const std::string &s)
|
||||
void FFMPEGCapture::setEncoderOptions(const std::string &s)
|
||||
{
|
||||
d->vc_options = s;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include "moviecapture.h"
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
#include <celengine/hash.h>
|
||||
|
||||
class FFMPEGCapturePrivate;
|
||||
|
||||
class FFMPEGCapture : public MovieCapture
|
||||
{
|
||||
public:
|
||||
FFMPEGCapture(const Renderer *r);
|
||||
~FFMPEGCapture() override;
|
||||
|
||||
bool start(const fs::path&, int, int, float) override;
|
||||
bool end() override;
|
||||
bool captureFrame() override;
|
||||
|
||||
int getFrameCount() const override;
|
||||
int getWidth() const override;
|
||||
int getHeight() const override;
|
||||
float getFrameRate() const override;
|
||||
|
||||
void setAspectRatio(int, int) override {};
|
||||
void setQuality(float) override {};
|
||||
void recordingStatus(bool) override {};
|
||||
|
||||
void setVideoCodec(AVCodecID);
|
||||
void setBitRate(int64_t);
|
||||
void setEncoderOptions(const std::string&);
|
||||
|
||||
private:
|
||||
FFMPEGCapturePrivate *d{ nullptr };
|
||||
};
|
|
@ -30,6 +30,9 @@
|
|||
#include <celcompat/charconv.h>
|
||||
#include <celutil/filetype.h>
|
||||
#include <celutil/gettext.h>
|
||||
#ifdef USE_FFMPEG
|
||||
#include <celestia/ffmpegcapture.h>
|
||||
#endif
|
||||
|
||||
#include "actions.h"
|
||||
#include "common.h"
|
||||
|
@ -53,14 +56,41 @@ using namespace std;
|
|||
static void openScript(const char* filename, AppData* app);
|
||||
static void captureImage(const char* filename, AppData* app);
|
||||
#ifdef USE_FFMPEG
|
||||
static void captureMovie(const char* filename, int w, int h, float fps,
|
||||
int codec, int64_t bitrate, AppData* app);
|
||||
static void captureMovie(const char* filename, const int resolution[], float fps,
|
||||
AVCodecID codec, float bitrate, AppData* app);
|
||||
#endif
|
||||
static void textInfoDialog(const char *txt, const char *title, AppData* app);
|
||||
static void setRenderFlag(AppData* a, uint64_t flag, gboolean state);
|
||||
static void setOrbitMask(AppData* a, int mask, gboolean state);
|
||||
static void setLabelMode(AppData* a, int mode, gboolean state);
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
static const int MovieSizes[][2] =
|
||||
{
|
||||
{ 160, 120 },
|
||||
{ 320, 240 },
|
||||
{ 640, 480 },
|
||||
{ 720, 480 },
|
||||
{ 720, 576 },
|
||||
{ 1024, 768 },
|
||||
{ 1280, 720 },
|
||||
{ 1920, 1080 }
|
||||
};
|
||||
|
||||
static const float MovieFramerates[] = { 15.0f, 23.976f, 24.0f, 25.0f, 29.97f, 30.0f, 60.0f };
|
||||
|
||||
struct MovieCodec
|
||||
{
|
||||
AVCodecID codecId;
|
||||
const char *codecDesc;
|
||||
};
|
||||
|
||||
static MovieCodec MovieCodecs[2] =
|
||||
{
|
||||
{ AV_CODEC_ID_FFVHUFF, N_("Lossless") },
|
||||
{ AV_CODEC_ID_H264, N_("Lossy (H.264)") }
|
||||
};
|
||||
|
||||
static void insert_text_event(GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer data)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
|
@ -72,6 +102,7 @@ static void insert_text_event(GtkEditable *editable, const gchar *text, gint len
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* File -> Copy URL */
|
||||
void actionCopyURL(GtkAction*, AppData* app)
|
||||
|
@ -237,12 +268,10 @@ void actionCaptureMovie(GtkAction*, AppData* app)
|
|||
gtk_box_pack_start(GTK_BOX(hbox), rlabel, TRUE, TRUE, 0);
|
||||
|
||||
GtkWidget* vscombo = gtk_combo_box_text_new();
|
||||
auto movieSizes = app->core->getSupportedMovieSizes();
|
||||
for (const auto& size : movieSizes)
|
||||
for (const auto& size : MovieSizes)
|
||||
{
|
||||
auto s = fmt::format("{} x {}", size.width, size.height);
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vscombo),
|
||||
s.c_str());
|
||||
fmt::format("{} x {}", size[0], size[1]).c_str());
|
||||
}
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(vscombo), 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vscombo, FALSE, FALSE, 0);
|
||||
|
@ -251,8 +280,7 @@ void actionCaptureMovie(GtkAction*, AppData* app)
|
|||
gtk_box_pack_start(GTK_BOX(hbox), flabel, TRUE, TRUE, 0);
|
||||
|
||||
GtkWidget* frcombo = gtk_combo_box_text_new();
|
||||
auto movieFramerates = app->core->getSupportedMovieFramerates();
|
||||
for (float i : movieFramerates)
|
||||
for (float i : MovieFramerates)
|
||||
{
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(frcombo),
|
||||
fmt::format("{:.3f}", i).c_str());
|
||||
|
@ -264,11 +292,10 @@ void actionCaptureMovie(GtkAction*, AppData* app)
|
|||
gtk_box_pack_start(GTK_BOX(hbox), vclabel, TRUE, TRUE, 0);
|
||||
|
||||
GtkWidget* vccombo = gtk_combo_box_text_new();
|
||||
auto movieCodecs = app->core->getSupportedMovieCodecs();
|
||||
for (const auto &mcodec : movieCodecs)
|
||||
for (const auto &mcodec : MovieCodecs)
|
||||
{
|
||||
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vccombo),
|
||||
mcodec.codecDescr);
|
||||
mcodec.codecDesc);
|
||||
}
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(vccombo), 0);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), vccombo, FALSE, FALSE, 0);
|
||||
|
@ -290,17 +317,17 @@ void actionCaptureMovie(GtkAction*, AppData* app)
|
|||
int fridx = gtk_combo_box_get_active(GTK_COMBO_BOX(frcombo));
|
||||
int vcidx = gtk_combo_box_get_active(GTK_COMBO_BOX(vccombo));
|
||||
const gchar *brtext = gtk_entry_get_text(GTK_ENTRY(brentry));
|
||||
const auto &dim = movieSizes[vsidx];
|
||||
float fps = movieFramerates[fridx];
|
||||
int codec = movieCodecs[vcidx].codecId;
|
||||
int64_t bitrate = 400000;
|
||||
const int *resolution = MovieSizes[vsidx];
|
||||
float fps = MovieFramerates[fridx];
|
||||
AVCodecID codec = MovieCodecs[vcidx].codecId;
|
||||
float bitrate = 400000;
|
||||
const gchar *last = &brtext[gtk_entry_get_text_length(GTK_ENTRY(brentry))];
|
||||
std::from_chars(brtext, last, bitrate);
|
||||
|
||||
gtk_widget_destroy(fs);
|
||||
for (int i=0; i < 10 && gtk_events_pending ();i++)
|
||||
gtk_main_iteration ();
|
||||
captureMovie(filename, dim.width, dim.height, fps, codec, bitrate, app);
|
||||
captureMovie(filename, resolution, fps, codec, bitrate, app);
|
||||
g_free(filename);
|
||||
}
|
||||
else
|
||||
|
@ -1085,17 +1112,26 @@ static void captureImage(const char* filename, AppData* app)
|
|||
|
||||
/* Image capturing helper called by actionCaptureImage() */
|
||||
#ifdef USE_FFMPEG
|
||||
static void captureMovie(const char* filename,
|
||||
int width, int height,
|
||||
float fps, int codec,
|
||||
int64_t bitrate, AppData* app)
|
||||
static void captureMovie(const char* filename, const int resolution[], float fps,
|
||||
AVCodecID codec, float bitrate, AppData* app)
|
||||
{
|
||||
bool ok = app->core->initMovieCapture(filename,
|
||||
width, height,
|
||||
fps, bitrate,
|
||||
codec);
|
||||
if (!ok)
|
||||
auto* movieCapture = new FFMPEGCapture(app->renderer);
|
||||
movieCapture->setVideoCodec(codec);
|
||||
movieCapture->setBitRate(bitrate);
|
||||
if (codec == AV_CODEC_ID_H264)
|
||||
movieCapture->setEncoderOptions(app->core->getConfig()->x264EncoderOptions);
|
||||
else
|
||||
movieCapture->setEncoderOptions(app->core->getConfig()->ffvhEncoderOptions);
|
||||
|
||||
bool success = movieCapture->start(filename, resolution[0], resolution[1], fps);
|
||||
if (success)
|
||||
{
|
||||
app->core->initMovieCapture(movieCapture);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete movieCapture;
|
||||
|
||||
GtkWidget* errBox = gtk_message_dialog_new(GTK_WINDOW(app->mainWindow),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR,
|
||||
|
|
|
@ -1,34 +1,44 @@
|
|||
#pragma once
|
||||
// moviecapture.h
|
||||
//
|
||||
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
|
||||
//
|
||||
// This program 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.
|
||||
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
extern "C"
|
||||
{
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
#ifndef _MOVIECAPTURE_H_
|
||||
#define _MOVIECAPTURE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <celengine/render.h>
|
||||
#include <celcompat/filesystem.h>
|
||||
|
||||
namespace celestia
|
||||
{
|
||||
class MovieCapturePrivate;
|
||||
class MovieCapture
|
||||
{
|
||||
public:
|
||||
MovieCapture(const Renderer *r);
|
||||
~MovieCapture();
|
||||
MovieCapture(const Renderer *r) : renderer(r) {};
|
||||
virtual ~MovieCapture() {};
|
||||
|
||||
bool start(const fs::path&, int, int, float);
|
||||
bool end();
|
||||
bool captureFrame();
|
||||
virtual bool start(const fs::path& filename,
|
||||
int width, int height,
|
||||
float fps) = 0;
|
||||
virtual bool end() = 0;
|
||||
virtual bool captureFrame() = 0;
|
||||
|
||||
int getFrameCount() const;
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
float getFrameRate() const;
|
||||
virtual int getFrameCount() const = 0;
|
||||
virtual int getWidth() const = 0;
|
||||
virtual int getHeight() const = 0;
|
||||
virtual float getFrameRate() const = 0;
|
||||
|
||||
void setVideoCodec(AVCodecID);
|
||||
void setBitRate(int64_t);
|
||||
void setEncoderOptions(const std::string&);
|
||||
virtual void setAspectRatio(int aspectNumerator, int aspectDenominator) = 0;
|
||||
virtual void setQuality(float) = 0;
|
||||
virtual void recordingStatus(bool started) = 0; /* to update UI recording status indicator */
|
||||
|
||||
private:
|
||||
MovieCapturePrivate *d{ nullptr };
|
||||
protected:
|
||||
const Renderer *renderer{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _MOVIECAPTURE_H_
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
// of the License, or (at your option) any later version.
|
||||
|
||||
|
||||
//#include <ctime>
|
||||
#include <memory>
|
||||
|
||||
#include <QStandardPaths>
|
||||
|
@ -64,6 +65,10 @@
|
|||
#include <celestia/url.h>
|
||||
#include "qtbookmark.h"
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
#include "celestia/ffmpegcapture.h"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DATA_DIR
|
||||
#define CONFIG_DATA_DIR "./"
|
||||
#endif
|
||||
|
@ -84,6 +89,22 @@ static const int CELESTIA_MAIN_WINDOW_VERSION = 12;
|
|||
static int fps_to_ms(int fps) { return fps > 0 ? 1000 / fps : 0; }
|
||||
static int ms_to_fps(int ms) { return ms > 0? 1000 / ms : 0; }
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
static const int videoSizes[][2] =
|
||||
{
|
||||
{ 160, 120 },
|
||||
{ 320, 240 },
|
||||
{ 640, 480 },
|
||||
{ 720, 480 },
|
||||
{ 720, 576 },
|
||||
{ 1024, 768 },
|
||||
{ 1280, 720 },
|
||||
{ 1920, 1080 }
|
||||
};
|
||||
|
||||
static const float videoFrameRates[] = { 15.0f, 23.976f, 24.0f, 25.0f, 29.97f, 30.0f, 60.0f };
|
||||
#endif
|
||||
|
||||
// Progress notifier class receives update messages from CelestiaCore
|
||||
// at startup. This simple implementation just forwards messages on
|
||||
// to the main Celestia window.
|
||||
|
@ -644,27 +665,20 @@ void CelestiaAppWindow::slotCaptureVideo()
|
|||
QComboBox* resolutionCombo = new QComboBox(&videoInfoDialog);
|
||||
layout->addWidget(new QLabel(_("Resolution:"), &videoInfoDialog), 0, 0);
|
||||
layout->addWidget(resolutionCombo, 0, 1);
|
||||
auto videoSizes = m_appCore->getSupportedMovieSizes();
|
||||
for (const auto& size : videoSizes)
|
||||
{
|
||||
int w = size.width;
|
||||
int h = size.height;
|
||||
resolutionCombo->addItem(QString(_("%1 x %2")).arg(w).arg(h), QSize(w, h));
|
||||
}
|
||||
resolutionCombo->addItem(QString(_("%1 x %2")).arg(size[0]).arg(size[1]), QSize(size[0], size[1]));
|
||||
|
||||
QComboBox* frameRateCombo = new QComboBox(&videoInfoDialog);
|
||||
layout->addWidget(new QLabel(_("Frame rate:"), &videoInfoDialog), 1, 0);
|
||||
layout->addWidget(frameRateCombo, 1, 1);
|
||||
auto videoFrameRates = m_appCore->getSupportedMovieFramerates();
|
||||
for (float i : videoFrameRates)
|
||||
frameRateCombo->addItem(QString::number(i), i);
|
||||
|
||||
QComboBox* codecCombo = new QComboBox(&videoInfoDialog);
|
||||
layout->addWidget(new QLabel(_("Video codec:"), &videoInfoDialog), 2, 0);
|
||||
layout->addWidget(codecCombo, 2, 1);
|
||||
auto videoCodecs = m_appCore->getSupportedMovieCodecs();
|
||||
for (const auto &c : videoCodecs)
|
||||
codecCombo->addItem(_(c.codecDescr), c.codecId);
|
||||
codecCombo->addItem(_("Lossless"), AV_CODEC_ID_FFVHUFF);
|
||||
codecCombo->addItem(_("Lossy (H.264)"), AV_CODEC_ID_H264);
|
||||
|
||||
QLineEdit* bitrateEdit = new QLineEdit("400000", &videoInfoDialog);
|
||||
bitrateEdit->setInputMask("D000000000");
|
||||
|
@ -682,12 +696,24 @@ void CelestiaAppWindow::slotCaptureVideo()
|
|||
{
|
||||
QSize videoSize = resolutionCombo->itemData(resolutionCombo->currentIndex()).toSize();
|
||||
float frameRate = frameRateCombo->itemData(frameRateCombo->currentIndex()).toFloat();
|
||||
int codec = codecCombo->itemData(codecCombo->currentIndex()).toInt();
|
||||
int64_t bitrate = bitrateEdit->text().toLongLong();
|
||||
AVCodecID vc = static_cast<AVCodecID>(codecCombo->itemData(codecCombo->currentIndex()).toInt());
|
||||
int br = bitrateEdit->text().toLongLong();
|
||||
|
||||
m_appCore->initMovieCapture(saveAsName.toStdString(),
|
||||
videoSize.width(), videoSize.height(),
|
||||
frameRate, bitrate, codec);
|
||||
auto *movieCapture = new FFMPEGCapture(m_appCore->getRenderer());
|
||||
movieCapture->setVideoCodec(vc);
|
||||
movieCapture->setBitRate(br);
|
||||
if (vc == AV_CODEC_ID_H264)
|
||||
movieCapture->setEncoderOptions(m_appCore->getConfig()->x264EncoderOptions);
|
||||
else
|
||||
movieCapture->setEncoderOptions(m_appCore->getConfig()->ffvhEncoderOptions);
|
||||
|
||||
bool ok = movieCapture->start(saveAsName.toStdString(),
|
||||
videoSize.width(), videoSize.height(),
|
||||
frameRate);
|
||||
if (ok)
|
||||
m_appCore->initMovieCapture(movieCapture);
|
||||
else
|
||||
delete movieCapture;
|
||||
}
|
||||
|
||||
settings.beginGroup("Preferences");
|
||||
|
|
|
@ -488,9 +488,9 @@ FONT 8, "Segoe UI", 0, 0, 0
|
|||
COMBOBOX IDC_COMBO_MOVIE_SIZE, 38, 2, 82, 93, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT
|
||||
RTEXT "Frame rate:", IDC_STATIC, 120, 4, 74, 8, SS_RIGHT, WS_EX_LEFT
|
||||
COMBOBOX IDC_COMBO_MOVIE_FRAMERATE, 196, 2, 82, 90, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT
|
||||
LTEXT "Codec:", IDC_STATIC, 6, 20, 30, 8, SS_LEFT, WS_EX_LEFT
|
||||
COMBOBOX IDC_COMBO_MOVIE_CODEC, 38, 18, 82, 90, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST, WS_EX_LEFT
|
||||
RTEXT "Bitrate:", IDC_STATIC, 120, 20, 74, 8, SS_RIGHT, WS_EX_LEFT
|
||||
LTEXT "Codec:", 0, 6, 20, 30, 8, SS_LEFT, WS_EX_LEFT
|
||||
COMBOBOX IDC_COMBO_MOVIE_CODEC, 38, 18, 82, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_LEFT
|
||||
RTEXT "Bitrate:", 0, 120, 20, 74, 8, SS_RIGHT, WS_EX_LEFT
|
||||
EDITTEXT IDC_EDIT_MOVIE_BITRATE, 196, 18, 82, 14, ES_AUTOHSCROLL | ES_NUMBER, WS_EX_LEFT
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,8 @@
|
|||
#include <process.h>
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
#include <windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
|
||||
#include <commctrl.h>
|
||||
#include <mmsystem.h>
|
||||
#include <oleidl.h> // IDropTarget
|
||||
#include <commdlg.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
|
@ -44,6 +42,7 @@
|
|||
#include <celscript/legacy/cmdparser.h>
|
||||
|
||||
#include "celestia/celestiacore.h"
|
||||
#include "celestia/ffmpegcapture.h"
|
||||
#include "celestia/helper.h"
|
||||
#include "celestia/scriptmenu.h"
|
||||
#include "celestia/url.h"
|
||||
|
@ -128,6 +127,31 @@ static POINT lastMouseMove;
|
|||
class WinCursorHandler;
|
||||
WinCursorHandler* cursorHandler = NULL;
|
||||
|
||||
static int MovieSizes[8][2] = {
|
||||
{ 160, 120 },
|
||||
{ 320, 240 },
|
||||
{ 640, 480 },
|
||||
{ 720, 480 },
|
||||
{ 720, 576 },
|
||||
{ 1024, 768 },
|
||||
{ 1280, 720 },
|
||||
{ 1920, 1080 }
|
||||
};
|
||||
|
||||
static float MovieFramerates[5] = { 15.0f, 24.0f, 25.0f, 29.97f, 30.0f };
|
||||
|
||||
struct MovieCodec
|
||||
{
|
||||
AVCodecID codecId;
|
||||
const char *codecDesc;
|
||||
};
|
||||
|
||||
static MovieCodec MovieCodecs[2] =
|
||||
{
|
||||
{ AV_CODEC_ID_FFVHUFF, N_("Lossless") },
|
||||
{ AV_CODEC_ID_H264, N_("Lossy (H.264)") }
|
||||
};
|
||||
|
||||
static int movieSize = 1;
|
||||
static int movieFramerate = 1;
|
||||
static int movieCodec = 1;
|
||||
|
@ -417,6 +441,31 @@ static void ShowLocalTime(CelestiaCore* appCore)
|
|||
}
|
||||
|
||||
|
||||
static bool BeginMovieCapture(const Renderer* renderer,
|
||||
const std::string& filename,
|
||||
int width, int height,
|
||||
float framerate,
|
||||
AVCodecID codec,
|
||||
int64_t bitrate)
|
||||
{
|
||||
auto* movieCapture = new FFMPEGCapture(renderer);
|
||||
movieCapture->setVideoCodec(codec);
|
||||
movieCapture->setBitRate(bitrate);
|
||||
if (vc == AV_CODEC_ID_H264)
|
||||
movieCapture->setEncoderOptions(appCore->getConfig()->x264EncoderOptions);
|
||||
else
|
||||
movieCapture->setEncoderOptions(appCore->getConfig()->ffvhEncoderOptions);
|
||||
|
||||
bool success = movieCapture->start(filename, width, height, framerate);
|
||||
if (success)
|
||||
appCore->initMovieCapture(movieCapture);
|
||||
else
|
||||
delete movieCapture;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
static bool CopyStateURLToClipboard()
|
||||
{
|
||||
BOOL b;
|
||||
|
@ -628,7 +677,6 @@ BOOL APIENTRY GLInfoProc(HWND hDlg,
|
|||
}
|
||||
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
UINT CALLBACK ChooseMovieParamsProc(HWND hDlg, UINT message,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -638,32 +686,33 @@ UINT CALLBACK ChooseMovieParamsProc(HWND hDlg, UINT message,
|
|||
{
|
||||
char buf[100];
|
||||
HWND hwnd = GetDlgItem(hDlg, IDC_COMBO_MOVIE_SIZE);
|
||||
int nSizes = sizeof MovieSizes / sizeof MovieSizes[0];
|
||||
|
||||
auto movieSizes = appCore->getSupportedMovieSizes();
|
||||
for (auto const &s : movieSizes)
|
||||
for (int i = 0; i < nSizes; i++)
|
||||
{
|
||||
sprintf(buf, _("%d x %d"), s.width, s.height);
|
||||
sprintf(buf, _("%d x %d"), MovieSizes[i][0], MovieSizes[i][1]);
|
||||
SendMessage(hwnd, CB_INSERTSTRING, -1,
|
||||
reinterpret_cast<LPARAM>(buf));
|
||||
}
|
||||
SendMessage(hwnd, CB_SETCURSEL, movieSize, 0);
|
||||
|
||||
hwnd = GetDlgItem(hDlg, IDC_COMBO_MOVIE_FRAMERATE);
|
||||
auto movieFramerates = appCore->getSupportedMovieFramerates();
|
||||
for (float fps : movieFramerates)
|
||||
int nFramerates = sizeof MovieFramerates / sizeof MovieFramerates[0];
|
||||
for (int i = 0; i < nFramerates; i++)
|
||||
{
|
||||
sprintf(buf, "%.2f", fps);
|
||||
sprintf(buf, "%.2f", MovieFramerates[i]);
|
||||
SendMessage(hwnd, CB_INSERTSTRING, -1,
|
||||
reinterpret_cast<LPARAM>(buf));
|
||||
}
|
||||
SendMessage(hwnd, CB_SETCURSEL, movieFramerate, 0);
|
||||
|
||||
hwnd = GetDlgItem(hDlg, IDC_COMBO_MOVIE_CODEC);
|
||||
auto movieCodecs = appCore->getSupportedMovieCodecs();
|
||||
for (auto &c : movieCodecs)
|
||||
int nCodecs = sizeof MovieCodecs / sizeof MovieCodecs[0];
|
||||
for (int i = 0; i < nCodecs; i++)
|
||||
{
|
||||
SendMessage(hwnd, CB_INSERTSTRING, -1,
|
||||
reinterpret_cast<LPARAM>(_(c.codecDescr)));
|
||||
SendMessage(hwnd, CB_INSERTSTRING,
|
||||
reinterpret_cast<WPARAM>(MovieCodecs[i].codecId),
|
||||
reinterpret_cast<LPARAM>(_(MovieCodecs[i].codecDesc)));
|
||||
}
|
||||
SendMessage(hwnd, CB_SETCURSEL, movieCodec, 0);
|
||||
|
||||
|
@ -705,15 +754,14 @@ UINT CALLBACK ChooseMovieParamsProc(HWND hDlg, UINT message,
|
|||
movieCodec = item;
|
||||
}
|
||||
}
|
||||
else if (LOWORD(wParam) == IDOK)
|
||||
else if (LOWORD(wParam) == IDOK IDC_EDIT_MOVIE_BITRATE)
|
||||
{
|
||||
char buf[24], out[24];
|
||||
wchar_t wbuff[48];
|
||||
int wlen = 0;
|
||||
int len = GetDlgItemText(hDlg, IDC_EDIT_MOVIE_BITRATE, buf, sizeof(buf));
|
||||
if (len > 0)
|
||||
{
|
||||
wlen = MultiByteToWideChar(CP_ACP, 0, buf, -1, wbuff, sizeof(wbuff));
|
||||
int wlen = MultiByteToWideChar(CP_ACP, 0, buf, -1, wbuff, sizeof(wbuff));
|
||||
WideCharToMultiByte(CP_UTF8, 0, wbuff, wlen, out, sizeof(out), NULL, NULL);
|
||||
|
||||
}
|
||||
|
@ -728,7 +776,6 @@ UINT CALLBACK ChooseMovieParamsProc(HWND hDlg, UINT message,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
BOOL APIENTRY FindObjectProc(HWND hDlg,
|
||||
|
@ -2691,7 +2738,6 @@ static void HandleCaptureImage(HWND hWnd)
|
|||
}
|
||||
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
static void HandleCaptureMovie(HWND hWnd)
|
||||
{
|
||||
// TODO: The menu item should be disable so that the user doesn't even
|
||||
|
@ -2785,15 +2831,13 @@ static void HandleCaptureMovie(HWND hWnd)
|
|||
}
|
||||
else
|
||||
{
|
||||
auto movieSizes = appCore->getSupportedMovieSizes();
|
||||
auto movieFramerates = appCore->getSupportedMovieFramerates();
|
||||
auto movieCodecs = appCore->getSupportedMovieCodecs();
|
||||
success = appCore->initMovieCapture(Ofn.lpstrFile,
|
||||
movieSizes[movieSize].width,
|
||||
movieSizes[movieSize].height,
|
||||
movieFramerates[movieFramerate],
|
||||
movieBitrate,
|
||||
movieCodecs[movieCodec].codecId);
|
||||
success = BeginMovieCapture(appCore->getRenderer(),
|
||||
string(Ofn.lpstrFile),
|
||||
MovieSizes[movieSize][0],
|
||||
MovieSizes[movieSize][1],
|
||||
MovieFramerates[movieFramerate],
|
||||
MovieCodecs[movieCodec],
|
||||
movieBitrate);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
|
@ -2809,7 +2853,6 @@ static void HandleCaptureMovie(HWND hWnd)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void HandleOpenScript(HWND hWnd, CelestiaCore* appCore)
|
||||
|
@ -4268,11 +4311,9 @@ LRESULT CALLBACK MainWindowProc(HWND hWnd,
|
|||
HandleCaptureImage(hWnd);
|
||||
break;
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
case ID_FILE_CAPTUREMOVIE:
|
||||
HandleCaptureMovie(hWnd);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ID_FILE_EXIT:
|
||||
SendMessage(hWnd, WM_CLOSE, 0, 0);
|
||||
|
|
Loading…
Reference in New Issue