libav movie options in work.
This commit is contained in:
parent
3262e182e8
commit
b514c143b6
|
@ -747,6 +747,8 @@ struct OutputStream
|
||||||
struct SwrContext *swr_ctx;
|
struct SwrContext *swr_ctx;
|
||||||
int64_t next_pts;
|
int64_t next_pts;
|
||||||
int bytesPerSample;
|
int bytesPerSample;
|
||||||
|
int frameSize;
|
||||||
|
AVCodecID selEnc;
|
||||||
|
|
||||||
OutputStream(void)
|
OutputStream(void)
|
||||||
{
|
{
|
||||||
|
@ -756,7 +758,9 @@ struct OutputStream
|
||||||
sws_ctx = NULL;
|
sws_ctx = NULL;
|
||||||
swr_ctx = NULL;
|
swr_ctx = NULL;
|
||||||
bytesPerSample = 0;
|
bytesPerSample = 0;
|
||||||
|
frameSize = 0;
|
||||||
next_pts = 0;
|
next_pts = 0;
|
||||||
|
selEnc = AV_CODEC_ID_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close(void)
|
void close(void)
|
||||||
|
@ -1077,6 +1081,7 @@ static int initAudioStream( enum AVCodecID codec_id, OutputStream *ost )
|
||||||
nb_samples = c->frame_size;
|
nb_samples = c->frame_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ost->frameSize = nb_samples;
|
||||||
ost->bytesPerSample = av_get_bytes_per_sample( c->sample_fmt );
|
ost->bytesPerSample = av_get_bytes_per_sample( c->sample_fmt );
|
||||||
|
|
||||||
ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples);
|
ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, c->sample_rate, nb_samples);
|
||||||
|
@ -1160,16 +1165,27 @@ static int initMedia( const char *filename )
|
||||||
|
|
||||||
//strncpy(oc->filename, filename, sizeof(oc->filename));
|
//strncpy(oc->filename, filename, sizeof(oc->filename));
|
||||||
|
|
||||||
if ( initVideoStream( fmt->video_codec, &video_st ) )
|
if ( video_st.selEnc == AV_CODEC_ID_NONE )
|
||||||
|
{
|
||||||
|
video_st.selEnc = fmt->video_codec;
|
||||||
|
}
|
||||||
|
if ( audio_st.selEnc == AV_CODEC_ID_NONE )
|
||||||
|
{
|
||||||
|
audio_st.selEnc = fmt->audio_codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( initVideoStream( video_st.selEnc, &video_st ) )
|
||||||
//if ( initVideoStream( AV_CODEC_ID_H264, &video_st ) )
|
//if ( initVideoStream( AV_CODEC_ID_H264, &video_st ) )
|
||||||
//if ( initVideoStream( AV_CODEC_ID_FFV1, &video_st ) )
|
//if ( initVideoStream( AV_CODEC_ID_FFV1, &video_st ) )
|
||||||
//if ( initVideoStream( AV_CODEC_ID_RV20, &video_st ) )
|
//if ( initVideoStream( AV_CODEC_ID_RV20, &video_st ) )
|
||||||
//if ( initVideoStream( AV_CODEC_ID_RAWVIDEO, &video_st ) )
|
//if ( initVideoStream( AV_CODEC_ID_RAWVIDEO, &video_st ) )
|
||||||
{
|
{
|
||||||
|
printf("Video Stream Init Failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ( initAudioStream( fmt->audio_codec, &audio_st ) )
|
if ( initAudioStream( audio_st.selEnc, &audio_st ) )
|
||||||
{
|
{
|
||||||
|
printf("Audio Stream Init Failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,6 +1208,7 @@ static int initMedia( const char *filename )
|
||||||
/* Write the stream header, if any. */
|
/* Write the stream header, if any. */
|
||||||
if ( avformat_write_header(oc, NULL) )
|
if ( avformat_write_header(oc, NULL) )
|
||||||
{
|
{
|
||||||
|
printf("Error: Failed to write avformat header\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,11 +1306,13 @@ static int encode_audio_frame( int16_t *audioOut, int numSamples)
|
||||||
}
|
}
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
int spaceAvail, samplesLeft, copySize, srcOffset = 0;
|
int spaceAvail, samplesLeft, copySize, srcOffset = 0, frameSize;
|
||||||
|
|
||||||
|
frameSize = ost->frameSize;
|
||||||
|
|
||||||
samplesLeft = ost->tmp_frame->nb_samples = ret;
|
samplesLeft = ost->tmp_frame->nb_samples = ret;
|
||||||
|
|
||||||
spaceAvail = ost->enc->frame_size - ost->frame->nb_samples;
|
spaceAvail = frameSize - ost->frame->nb_samples;
|
||||||
|
|
||||||
while ( samplesLeft > 0 )
|
while ( samplesLeft > 0 )
|
||||||
{
|
{
|
||||||
|
@ -1327,7 +1346,7 @@ static int encode_audio_frame( int16_t *audioOut, int numSamples)
|
||||||
srcOffset += copySize;
|
srcOffset += copySize;
|
||||||
samplesLeft -= copySize;
|
samplesLeft -= copySize;
|
||||||
|
|
||||||
if ( ost->frame->nb_samples >= ost->enc->frame_size )
|
if ( ost->frame->nb_samples >= frameSize )
|
||||||
{
|
{
|
||||||
if ( write_audio_frame( ost->frame ) )
|
if ( write_audio_frame( ost->frame ) )
|
||||||
{
|
{
|
||||||
|
@ -1335,7 +1354,7 @@ static int encode_audio_frame( int16_t *audioOut, int numSamples)
|
||||||
}
|
}
|
||||||
ost->frame->nb_samples = 0;
|
ost->frame->nb_samples = 0;
|
||||||
}
|
}
|
||||||
spaceAvail = ost->enc->frame_size - ost->frame->nb_samples;
|
spaceAvail = frameSize - ost->frame->nb_samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2035,3 +2054,96 @@ void AviRecordDiskThread_t::run(void)
|
||||||
}
|
}
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
//**************************************************************************************
|
//**************************************************************************************
|
||||||
|
//**************************************************************************************
|
||||||
|
//***************************** Options Pages *****************************************
|
||||||
|
//**************************************************************************************
|
||||||
|
//**************************************************************************************
|
||||||
|
#ifdef _USE_LIBAV
|
||||||
|
LibavOptionsPage::LibavOptionsPage(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
QLabel *lbl;
|
||||||
|
QVBoxLayout *vbox1;
|
||||||
|
QHBoxLayout *hbox;
|
||||||
|
|
||||||
|
vbox1 = new QVBoxLayout();
|
||||||
|
|
||||||
|
videoEncSel = new QComboBox();
|
||||||
|
audioEncSel = new QComboBox();
|
||||||
|
|
||||||
|
hbox = new QHBoxLayout();
|
||||||
|
vbox1->addLayout(hbox);
|
||||||
|
lbl = new QLabel( tr("Video Encoder:") );
|
||||||
|
hbox->addWidget( lbl );
|
||||||
|
hbox->addWidget( videoEncSel );
|
||||||
|
|
||||||
|
hbox = new QHBoxLayout();
|
||||||
|
vbox1->addLayout(hbox);
|
||||||
|
lbl = new QLabel( tr("Audio Encoder:") );
|
||||||
|
hbox->addWidget( lbl );
|
||||||
|
hbox->addWidget( audioEncSel );
|
||||||
|
|
||||||
|
initCodecLists();
|
||||||
|
|
||||||
|
setLayout(vbox1);
|
||||||
|
|
||||||
|
connect(videoEncSel, SIGNAL(currentIndexChanged(int)), this, SLOT(videoCodecChanged(int)));
|
||||||
|
connect(audioEncSel, SIGNAL(currentIndexChanged(int)), this, SLOT(audioCodecChanged(int)));
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------
|
||||||
|
LibavOptionsPage::~LibavOptionsPage(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------
|
||||||
|
void LibavOptionsPage::initCodecLists(void)
|
||||||
|
{
|
||||||
|
void *it = NULL;
|
||||||
|
const AVCodec *c;
|
||||||
|
const AVOutputFormat *ofmt;
|
||||||
|
int compatible;
|
||||||
|
|
||||||
|
ofmt = av_guess_format("avi", NULL, NULL);
|
||||||
|
|
||||||
|
c = av_codec_iterate( &it );
|
||||||
|
|
||||||
|
while ( c != NULL )
|
||||||
|
{
|
||||||
|
if ( av_codec_is_encoder(c) )
|
||||||
|
{
|
||||||
|
if ( c->type == AVMEDIA_TYPE_VIDEO )
|
||||||
|
{
|
||||||
|
compatible = avformat_query_codec( ofmt, c->id, FF_COMPLIANCE_NORMAL );
|
||||||
|
printf("Video Encoder: %i %s %s\t:%i\n", c->id, c->name, c->long_name, compatible);
|
||||||
|
if ( compatible )
|
||||||
|
{
|
||||||
|
videoEncSel->addItem( tr(c->name), c->id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( c->type == AVMEDIA_TYPE_AUDIO )
|
||||||
|
{
|
||||||
|
compatible = avformat_query_codec( ofmt, c->id, FF_COMPLIANCE_NORMAL );
|
||||||
|
printf("Audio Encoder: %i %s %s\t:%i\n", c->id, c->name, c->long_name, compatible);
|
||||||
|
if ( compatible )
|
||||||
|
{
|
||||||
|
audioEncSel->addItem( tr(c->name), c->id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c = av_codec_iterate( &it );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------
|
||||||
|
void LibavOptionsPage::videoCodecChanged(int idx)
|
||||||
|
{
|
||||||
|
LIBAV::video_st.selEnc = (AVCodecID)videoEncSel->itemData(idx).toInt();
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------
|
||||||
|
void LibavOptionsPage::audioCodecChanged(int idx)
|
||||||
|
{
|
||||||
|
LIBAV::audio_st.selEnc = (AVCodecID)audioEncSel->itemData(idx).toInt();
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------
|
||||||
|
#endif
|
||||||
|
//**************************************************************************************
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
enum aviEncoderList
|
enum aviEncoderList
|
||||||
{
|
{
|
||||||
|
@ -68,4 +70,27 @@ class AviRecordDiskThread_t : public QThread
|
||||||
signals:
|
signals:
|
||||||
void finished(void);
|
void finished(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef _USE_LIBAV
|
||||||
|
class LibavOptionsPage : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
LibavOptionsPage(QWidget *parent = nullptr);
|
||||||
|
~LibavOptionsPage(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QComboBox *videoEncSel;
|
||||||
|
QComboBox *audioEncSel;
|
||||||
|
|
||||||
|
void initCodecLists(void);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void videoCodecChanged(int idx);
|
||||||
|
void audioCodecChanged(int idx);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "Qt/input.h"
|
#include "Qt/input.h"
|
||||||
#include "Qt/config.h"
|
#include "Qt/config.h"
|
||||||
#include "Qt/keyscan.h"
|
#include "Qt/keyscan.h"
|
||||||
|
#include "Qt/AviRecord.h"
|
||||||
#include "Qt/fceuWrapper.h"
|
#include "Qt/fceuWrapper.h"
|
||||||
#include "Qt/MovieOptions.h"
|
#include "Qt/MovieOptions.h"
|
||||||
|
|
||||||
|
@ -43,13 +44,20 @@ MovieOptionsDialog_t::MovieOptionsDialog_t(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
QLabel *lbl;
|
QLabel *lbl;
|
||||||
QVBoxLayout *mainLayout;
|
QGroupBox *gbox;
|
||||||
|
QHBoxLayout *mainLayout;
|
||||||
QHBoxLayout *hbox;
|
QHBoxLayout *hbox;
|
||||||
|
QVBoxLayout *vbox1, *vbox2;
|
||||||
QPushButton *closeButton;
|
QPushButton *closeButton;
|
||||||
|
std::vector <std::string> aviDriverList;
|
||||||
|
|
||||||
setWindowTitle("Movie Options");
|
setWindowTitle("Movie Options");
|
||||||
|
|
||||||
mainLayout = new QVBoxLayout();
|
mainLayout = new QHBoxLayout();
|
||||||
|
vbox1 = new QVBoxLayout();
|
||||||
|
vbox2 = new QVBoxLayout();
|
||||||
|
|
||||||
|
mainLayout->addLayout(vbox1);
|
||||||
|
|
||||||
readOnlyReplay = new QCheckBox(tr("Always Suggest Read-Only Replay"));
|
readOnlyReplay = new QCheckBox(tr("Always Suggest Read-Only Replay"));
|
||||||
pauseAfterPlay = new QCheckBox(tr("Pause After Playback"));
|
pauseAfterPlay = new QCheckBox(tr("Pause After Playback"));
|
||||||
|
@ -63,15 +71,15 @@ MovieOptionsDialog_t::MovieOptionsDialog_t(QWidget *parent)
|
||||||
lbl = new QLabel(tr("Loading states in record mode will not immediately truncate movie, next frame input will. (VBA-rr and SNES9x style)"));
|
lbl = new QLabel(tr("Loading states in record mode will not immediately truncate movie, next frame input will. (VBA-rr and SNES9x style)"));
|
||||||
lbl->setWordWrap(true);
|
lbl->setWordWrap(true);
|
||||||
|
|
||||||
mainLayout->addWidget(readOnlyReplay);
|
vbox1->addWidget(readOnlyReplay);
|
||||||
mainLayout->addWidget(pauseAfterPlay);
|
vbox1->addWidget(pauseAfterPlay);
|
||||||
mainLayout->addWidget(closeAfterPlay);
|
vbox1->addWidget(closeAfterPlay);
|
||||||
mainLayout->addWidget(bindSaveStates);
|
vbox1->addWidget(bindSaveStates);
|
||||||
mainLayout->addWidget(dpySubTitles);
|
vbox1->addWidget(dpySubTitles);
|
||||||
mainLayout->addWidget(putSubTitlesAvi);
|
vbox1->addWidget(putSubTitlesAvi);
|
||||||
mainLayout->addWidget(autoBackUp);
|
vbox1->addWidget(autoBackUp);
|
||||||
mainLayout->addWidget(loadFullStates);
|
vbox1->addWidget(loadFullStates);
|
||||||
mainLayout->addWidget(lbl);
|
vbox1->addWidget(lbl);
|
||||||
|
|
||||||
readOnlyReplay->setChecked(suggestReadOnlyReplay);
|
readOnlyReplay->setChecked(suggestReadOnlyReplay);
|
||||||
pauseAfterPlay->setChecked(pauseAfterPlayback);
|
pauseAfterPlay->setChecked(pauseAfterPlayback);
|
||||||
|
@ -89,8 +97,40 @@ MovieOptionsDialog_t::MovieOptionsDialog_t(QWidget *parent)
|
||||||
hbox = new QHBoxLayout();
|
hbox = new QHBoxLayout();
|
||||||
hbox->addStretch(5);
|
hbox->addStretch(5);
|
||||||
hbox->addWidget( closeButton, 1 );
|
hbox->addWidget( closeButton, 1 );
|
||||||
mainLayout->addLayout( hbox );
|
vbox1->addLayout( hbox );
|
||||||
|
|
||||||
|
FCEUD_AviGetFormatOpts( aviDriverList );
|
||||||
|
|
||||||
|
gbox = new QGroupBox( tr("AVI Recording Options") );
|
||||||
|
gbox->setLayout(vbox2);
|
||||||
|
mainLayout->addWidget(gbox);
|
||||||
|
hbox = new QHBoxLayout();
|
||||||
|
aviBackend = new QComboBox();
|
||||||
|
aviPageStack = new QStackedWidget();
|
||||||
|
lbl = new QLabel(tr("AVI Backend Driver:"));
|
||||||
|
hbox->addWidget( lbl );
|
||||||
|
hbox->addWidget( aviBackend );
|
||||||
|
vbox2->addLayout( hbox );
|
||||||
|
vbox2->addWidget( aviPageStack );
|
||||||
|
|
||||||
|
for (size_t i=0; i<aviDriverList.size(); i++)
|
||||||
|
{
|
||||||
|
aviBackend->addItem(tr(aviDriverList[i].c_str()), (unsigned int)i);
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
#ifdef _USE_LIBAV
|
||||||
|
case AVI_LIBAV:
|
||||||
|
{
|
||||||
|
aviPageStack->addWidget( new LibavOptionsPage() );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
aviPageStack->addWidget( new QWidget() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
connect(readOnlyReplay, SIGNAL(stateChanged(int)), this, SLOT(readOnlyReplayChanged(int)));
|
connect(readOnlyReplay, SIGNAL(stateChanged(int)), this, SLOT(readOnlyReplayChanged(int)));
|
||||||
|
@ -101,6 +141,9 @@ MovieOptionsDialog_t::MovieOptionsDialog_t(QWidget *parent)
|
||||||
connect(putSubTitlesAvi, SIGNAL(stateChanged(int)), this, SLOT(putSubTitlesAviChanged(int)));
|
connect(putSubTitlesAvi, SIGNAL(stateChanged(int)), this, SLOT(putSubTitlesAviChanged(int)));
|
||||||
connect(autoBackUp, SIGNAL(stateChanged(int)), this, SLOT(autoBackUpChanged(int)));
|
connect(autoBackUp, SIGNAL(stateChanged(int)), this, SLOT(autoBackUpChanged(int)));
|
||||||
connect(loadFullStates, SIGNAL(stateChanged(int)), this, SLOT(loadFullStatesChanged(int)));
|
connect(loadFullStates, SIGNAL(stateChanged(int)), this, SLOT(loadFullStatesChanged(int)));
|
||||||
|
|
||||||
|
connect(aviBackend, SIGNAL(currentIndexChanged(int)), this, SLOT(aviBackendChanged(int)));
|
||||||
|
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
MovieOptionsDialog_t::~MovieOptionsDialog_t(void)
|
MovieOptionsDialog_t::~MovieOptionsDialog_t(void)
|
||||||
|
@ -165,3 +208,8 @@ void MovieOptionsDialog_t::loadFullStatesChanged(int state)
|
||||||
fullSaveStateLoads = (state != Qt::Unchecked);
|
fullSaveStateLoads = (state != Qt::Unchecked);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
void MovieOptionsDialog_t::aviBackendChanged(int idx)
|
||||||
|
{
|
||||||
|
aviPageStack->setCurrentIndex(idx);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
|
||||||
#include "Qt/main.h"
|
#include "Qt/main.h"
|
||||||
|
|
||||||
|
@ -37,6 +38,8 @@ protected:
|
||||||
QCheckBox *putSubTitlesAvi;
|
QCheckBox *putSubTitlesAvi;
|
||||||
QCheckBox *autoBackUp;
|
QCheckBox *autoBackUp;
|
||||||
QCheckBox *loadFullStates;
|
QCheckBox *loadFullStates;
|
||||||
|
QComboBox *aviBackend;
|
||||||
|
QStackedWidget *aviPageStack;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -50,4 +53,5 @@ private slots:
|
||||||
void putSubTitlesAviChanged(int state);
|
void putSubTitlesAviChanged(int state);
|
||||||
void autoBackUpChanged(int state);
|
void autoBackUpChanged(int state);
|
||||||
void loadFullStatesChanged(int state);
|
void loadFullStatesChanged(int state);
|
||||||
|
void aviBackendChanged(int idx);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue