Skip to content

Commit

Permalink
データストリームをコピーするオプションを追加する。(--data-copy)
Browse files Browse the repository at this point in the history
  • Loading branch information
rigaya committed Jun 26, 2019
1 parent 8a4a8e8 commit 946da1b
Show file tree
Hide file tree
Showing 14 changed files with 314 additions and 159 deletions.
1 change: 1 addition & 0 deletions QSVEncC/QSVEncC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ static tstring help() {
_T(" --caption2ass [<string>] enable caption2ass during encode.\n")
_T(" !! This feature requires Caption.dll !!\n")
_T(" supported formats ... srt (default), ass\n")
_T(" --data-copy [<int>[,...]] copy data stream to output file.\n")
_T("\n")
_T(" --avsync <string> method for AV sync (default: cfr)\n")
_T(" cfr ... assume cfr\n")
Expand Down
3 changes: 3 additions & 0 deletions QSVEncC_Options.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,9 @@ Enable internal caption2ass process. This feature requires Caption.dll.

supported formats ... srt (default), ass

### --data-copy [&lt;int&gt;[,&lt;int&gt;]...]
Copy data stream from input file. Available only when avhw / avsw reader is used.

### -m, --mux-option &lt;string1&gt;:&lt;string2&gt;
Pass optional parameters to muxer. Specify the option name in &lt;string1&gt, and the option value in &lt;string2&gt;.

Expand Down
3 changes: 3 additions & 0 deletions QSVEncC_Options.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,9 @@ mp4にmuxする際は、必ずsrt形式を選択してください。内部で
- srt (デフォルト)
- ass

### --data-copy [&lt;int&gt;[,&lt;int&gt;]...]
データストリームをコピーする。avhw/avswリーダー使用時のみ有効。

### -m, --mux-option &lt;string1&gt;:&lt;string2&gt;
mux時にオプションパラメータを渡す。&lt;string1&gt;にオプション名、&lt;string2&gt;にオプションの値を指定する。

Expand Down
49 changes: 49 additions & 0 deletions QSVPipeline/qsv_cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ static int getSubTrackIdx(const sInputParams *pParams, int iTrack) {
return -1;
}

static int getDataTrackIdx(const sInputParams *pParams, int iTrack) {
for (int i = 0; i < pParams->nDataSelectCount; i++) {
if (iTrack == pParams->ppDataSelectList[i]->trackID) {
return i;
}
}
return -1;
}


struct sArgsData {
int outputDepth = 8;
Expand Down Expand Up @@ -869,6 +878,46 @@ int ParseOneOption(const TCHAR *option_name, const TCHAR* strInput[], int& i, in
pParams->caption2ass = FORMAT_INVALID;
return 0;
}
if (0 == _tcscmp(option_name, _T("data-copy"))) {
pParams->nAVMux |= (RGY_MUX_VIDEO | RGY_MUX_SUBTITLE);
std::map<int, DataSelect> trackSet; //重複しないように
if (i+1 < nArgNum && (strInput[i+1][0] != _T('-') && strInput[i+1][0] != _T('\0'))) {
i++;
auto trackListStr = split(strInput[i], _T(","));
for (auto str : trackListStr) {
int iTrack = 0;
if (1 != _stscanf(str.c_str(), _T("%d"), &iTrack) || iTrack < 1) {
SET_ERR(strInput[0], _T("Unknown value"), option_name, strInput[i]);
return 1;
} else {
trackSet[iTrack].trackID = iTrack;
}
}
} else {
trackSet[0].trackID = 0;
}

for (auto it = trackSet.begin(); it != trackSet.end(); it++) {
int trackId = it->first;
DataSelect *pDataSelect = nullptr;
int dataIdx = getDataTrackIdx(pParams, trackId);
if (dataIdx < 0) {
pDataSelect = new DataSelect();
} else {
pDataSelect = pParams->ppDataSelectList[dataIdx];
}
pDataSelect[0] = it->second;

if (dataIdx < 0) {
dataIdx = pParams->nDataSelectCount;
//新たに要素を追加
pParams->ppDataSelectList = (DataSelect **)realloc(pParams->ppDataSelectList, sizeof(pParams->ppDataSelectList[0]) * (pParams->nDataSelectCount + 1));
pParams->ppDataSelectList[pParams->nDataSelectCount] = pDataSelect;
pParams->nDataSelectCount++;
}
}
return 0;
}
if (0 == _tcscmp(option_name, _T("avsync"))) {
int value = 0;
i++;
Expand Down
61 changes: 43 additions & 18 deletions QSVPipeline/qsv_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2404,11 +2404,11 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
}

for (auto& stream : streamList) {
bool bStreamIsSubtitle = stream.nTrackId < 0;
const auto streamMediaType = trackMediaType(stream.nTrackId);
//audio-fileで別ファイルとして抽出するものは除く
bool usedInAudioFile = false;
for (int i = 0; i < (int)pParams->nAudioSelectCount; i++) {
if (stream.nTrackId == pParams->ppAudioSelectList[i]->trackID
if (trackID(stream.nTrackId) == pParams->ppAudioSelectList[i]->trackID
&& pParams->ppAudioSelectList[i]->extractFilename.length() > 0) {
usedInAudioFile = true;
}
Expand All @@ -2418,7 +2418,7 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
}
const AudioSelect *pAudioSelect = nullptr;
for (int i = 0; i < pParams->nAudioSelectCount; i++) {
if (stream.nTrackId == pParams->ppAudioSelectList[i]->trackID
if (trackID(stream.nTrackId) == pParams->ppAudioSelectList[i]->trackID
&& pParams->ppAudioSelectList[i]->extractFilename.length() == 0) {
pAudioSelect = pParams->ppAudioSelectList[i];
}
Expand All @@ -2434,9 +2434,9 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
}
}
const SubtitleSelect *pSubtitleSelect = nullptr;
if (bStreamIsSubtitle) {
if (streamMediaType == AVMEDIA_TYPE_SUBTITLE) {
for (int i = 0; i < pParams->nSubtitleSelectCount; i++) {
if (std::abs(stream.nTrackId) == pParams->ppSubtitleSelectList[i]->trackID) {
if (trackID(stream.nTrackId) == pParams->ppSubtitleSelectList[i]->trackID) {
pSubtitleSelect = pParams->ppSubtitleSelectList[i];
}
}
Expand All @@ -2450,9 +2450,26 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
}
}
}
if (pAudioSelect != nullptr || audioCopyAll || bStreamIsSubtitle) {
const DataSelect *pDataSelect = nullptr;
if (streamMediaType == AVMEDIA_TYPE_DATA) {
for (int i = 0; i < pParams->nDataSelectCount; i++) {
if (trackID(stream.nTrackId) == pParams->ppDataSelectList[i]->trackID) {
pDataSelect = pParams->ppDataSelectList[i];
}
}
if (pSubtitleSelect == nullptr) {
//一致するTrackIDがなければ、trackID = 0 (全指定)を探す
for (int i = 0; i < pParams->nDataSelectCount; i++) {
if (pParams->ppDataSelectList[i]->trackID == 0) {
pDataSelect = pParams->ppDataSelectList[i];
break;
}
}
}
}
if (pAudioSelect != nullptr || audioCopyAll || streamMediaType != AVMEDIA_TYPE_AUDIO) {
streamTrackUsed.push_back(stream.nTrackId);
if (bStreamIsSubtitle && pParams->vpp.subburn.nTrack != 0) {
if (streamMediaType == AVMEDIA_TYPE_SUBTITLE && pParams->vpp.subburn.nTrack != 0) {
continue;
}
AVOutputStreamPrm prm;
Expand All @@ -2473,8 +2490,8 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
prm.asdata = pSubtitleSelect->asdata;
}
PrintMes(RGY_LOG_DEBUG, _T("Output: Added %s track#%d (stream idx %d) for mux, bitrate %d, codec: %s %s %s\n"),
(bStreamIsSubtitle) ? _T("sub") : _T("audio"),
stream.nTrackId, stream.nIndex, prm.bitrate, prm.encodeCodec.c_str(),
char_to_tstring(av_get_media_type_string(streamMediaType)).c_str(),
trackID(stream.nTrackId), stream.nIndex, prm.bitrate, prm.encodeCodec.c_str(),
prm.encodeCodecProfile.c_str(),
prm.encodeCodecPrm.c_str());
writerPrm.inputStreamList.push_back(std::move(prm));
Expand Down Expand Up @@ -2539,7 +2556,7 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
for (auto usedTrack : streamTrackUsed) {
if (usedTrack == audioTrack.nTrackId) {
bTrackAlreadyUsed = true;
PrintMes(RGY_LOG_DEBUG, _T("Audio track #%d is already set to be muxed, so cannot be extracted to file.\n"), audioTrack.nTrackId);
PrintMes(RGY_LOG_DEBUG, _T("Audio track #%d is already set to be muxed, so cannot be extracted to file.\n"), trackID(audioTrack.nTrackId));
break;
}
}
Expand All @@ -2548,17 +2565,17 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
}
const AudioSelect *pAudioSelect = nullptr;
for (int i = 0; i < pParams->nAudioSelectCount; i++) {
if (audioTrack.nTrackId == pParams->ppAudioSelectList[i]->trackID
if (trackID(audioTrack.nTrackId) == pParams->ppAudioSelectList[i]->trackID
&& pParams->ppAudioSelectList[i]->extractFilename.length() > 0) {
pAudioSelect = pParams->ppAudioSelectList[i];
}
}
if (pAudioSelect == nullptr) {
PrintMes(RGY_LOG_ERROR, _T("Audio track #%d is not used anyware, this should not happen.\n"), audioTrack.nTrackId);
PrintMes(RGY_LOG_ERROR, _T("Audio track #%d is not used anyware, this should not happen.\n"), trackID(audioTrack.nTrackId));
return MFX_ERR_INVALID_AUDIO_PARAM;
}
PrintMes(RGY_LOG_DEBUG, _T("Output: Output audio track #%d (stream index %d) to \"%s\", format: %s, codec %s, bitrate %d\n"),
audioTrack.nTrackId, audioTrack.nIndex, pAudioSelect->extractFilename.c_str(), pAudioSelect->extractFormat.c_str(), pAudioSelect->encCodec.c_str(), pAudioSelect->encBitrate);
trackID(audioTrack.nTrackId), audioTrack.nIndex, pAudioSelect->extractFilename.c_str(), pAudioSelect->extractFormat.c_str(), pAudioSelect->encCodec.c_str(), pAudioSelect->encBitrate);

AVOutputStreamPrm prm;
prm.src = audioTrack;
Expand Down Expand Up @@ -2587,7 +2604,7 @@ mfxStatus CQSVPipeline::InitOutput(sInputParams *pParams) {
PrintMes(RGY_LOG_ERROR, pWriter->GetOutputMessage());
return err_to_mfx(ret);
}
PrintMes(RGY_LOG_DEBUG, _T("Output: Intialized audio output for track #%d.\n"), audioTrack.nTrackId);
PrintMes(RGY_LOG_DEBUG, _T("Output: Intialized audio output for track #%d.\n"), trackID(audioTrack.nTrackId));
bool audioStdout = pWriter->outputStdout();
if (ret != RGY_ERR_NONE) {
PrintMes(RGY_LOG_ERROR, _T("Multiple stream outputs are set to stdout, please remove conflict.\n"));
Expand All @@ -2607,6 +2624,7 @@ mfxStatus CQSVPipeline::InitInput(sInputParams *pParams) {

int sourceAudioTrackIdStart = 1; //トラック番号は1スタート
int sourceSubtitleTrackIdStart = 1; //トラック番号は1スタート
int sourceDataTrackIdStart = 1; //トラック番号は1スタート
if (!m_pEncSatusInfo) {
m_pEncSatusInfo = std::make_shared<EncodeStatus>();
}
Expand Down Expand Up @@ -2753,17 +2771,21 @@ mfxStatus CQSVPipeline::InitInput(sInputParams *pParams) {
avcodecReaderPrm.nVideoStreamId = pParams->nVideoStreamId;
avcodecReaderPrm.bReadChapter = !!pParams->bCopyChapter;
avcodecReaderPrm.bReadSubtitle = pParams->nSubtitleSelectCount + pParams->vpp.subburn.nTrack > 0;
avcodecReaderPrm.bReadData = pParams->nDataSelectCount > 0;
avcodecReaderPrm.pTrimList = pParams->pTrimList;
avcodecReaderPrm.nTrimCount = pParams->nTrimCount;
avcodecReaderPrm.nReadAudio |= pParams->nAudioSelectCount > 0;
avcodecReaderPrm.nAnalyzeSec = pParams->nAVDemuxAnalyzeSec;
avcodecReaderPrm.nVideoAvgFramerate = std::make_pair(pParams->nFPSRate, pParams->nFPSScale);
avcodecReaderPrm.nAudioTrackStart = sourceAudioTrackIdStart;
avcodecReaderPrm.nSubtitleTrackStart = sourceSubtitleTrackIdStart;
avcodecReaderPrm.nDataTrackStart = sourceDataTrackIdStart;
avcodecReaderPrm.ppAudioSelect = pParams->ppAudioSelectList;
avcodecReaderPrm.nAudioSelectCount = pParams->nAudioSelectCount;
avcodecReaderPrm.ppSubtitleSelect = (pParams->vpp.subburn.nTrack) ? &subBurnTrackPtr : pParams->ppSubtitleSelectList;
avcodecReaderPrm.nSubtitleSelectCount = (pParams->vpp.subburn.nTrack) ? 1 : pParams->nSubtitleSelectCount;
avcodecReaderPrm.ppDataSelect = pParams->ppDataSelectList;
avcodecReaderPrm.nDataSelectCount = pParams->nDataSelectCount;
avcodecReaderPrm.nProcSpeedLimit = pParams->nProcSpeedLimit;
avcodecReaderPrm.nAVSyncMode = RGY_AVSYNC_ASSUME_CFR;
avcodecReaderPrm.fSeekSec = pParams->fSeekSec;
Expand Down Expand Up @@ -2799,6 +2821,7 @@ mfxStatus CQSVPipeline::InitInput(sInputParams *pParams) {
PrintMes(RGY_LOG_DEBUG, _T("Input: reader initialization successful.\n"));
sourceAudioTrackIdStart += m_pFileReader->GetAudioTrackCount();
sourceSubtitleTrackIdStart += m_pFileReader->GetSubtitleTrackCount();
sourceDataTrackIdStart += m_pFileReader->GetDataTrackCount();

#if ENABLE_AVSW_READER
if (pParams->nAudioSourceCount && pParams->ppAudioSourceList) {
Expand All @@ -2815,6 +2838,7 @@ mfxStatus CQSVPipeline::InitInput(sInputParams *pParams) {
avcodecReaderPrm.nVideoAvgFramerate = std::make_pair(videoInfo.fpsN, videoInfo.fpsD);
avcodecReaderPrm.nAudioTrackStart = sourceAudioTrackIdStart;
avcodecReaderPrm.nSubtitleTrackStart = sourceSubtitleTrackIdStart;
avcodecReaderPrm.nDataTrackStart = sourceDataTrackIdStart;
avcodecReaderPrm.ppAudioSelect = pParams->ppAudioSelectList;
avcodecReaderPrm.nAudioSelectCount = pParams->nAudioSelectCount;
avcodecReaderPrm.nProcSpeedLimit = pParams->nProcSpeedLimit;
Expand All @@ -2830,7 +2854,8 @@ mfxStatus CQSVPipeline::InitInput(sInputParams *pParams) {
return err_to_mfx(ret);
}
sourceAudioTrackIdStart += audioReader->GetAudioTrackCount();
sourceSubtitleTrackIdStart += audioReader->GetSubtitleTrackCount();
sourceSubtitleTrackIdStart += m_pFileReader->GetSubtitleTrackCount();
sourceDataTrackIdStart += m_pFileReader->GetDataTrackCount();
m_AudioReaders.push_back(std::move(audioReader));
}
}
Expand Down Expand Up @@ -2999,13 +3024,13 @@ mfxStatus CQSVPipeline::CheckParam(sInputParams *pParams) {
if (!check_OS_Win8orLater()) {
memType &= (~D3D11_MEMORY);
}
//d3d11モードが必要なら、vpp-subは実行できない
//d3d11モードが必要なら、vpp-otherは実行できない
if (HW_MEMORY == (memType & HW_MEMORY) && check_if_d3d11_necessary()) {
memType &= (~D3D11_MEMORY);
PrintMes(RGY_LOG_DEBUG, _T("d3d11 mode required on this system, but vpp-sub does not support d3d11 mode.\n"));
return MFX_ERR_UNSUPPORTED;
}
//d3d11を要求するvpp-rotateとd3d11では実行できないvpp-subは競合する
//d3d11を要求するvpp-rotateとd3d11では実行できないvpp-otherは競合する
if (pParams->vpp.rotate) {
PrintMes(RGY_LOG_ERROR, _T("vpp-sub could not be used with vpp-rotate.\n"));
PrintMes(RGY_LOG_ERROR, _T("vpp-rotate requires d3d11 mode, but vpp-sub does not support d3d11 mode.\n"));
Expand Down Expand Up @@ -4034,7 +4059,7 @@ mfxStatus CQSVPipeline::RunEncode() {
}
//パケットを各Writerに分配する
for (uint32_t i = 0; i < packetList.size(); i++) {
const int nTrackId = (int16_t)(packetList[i].flags >> 16);
const int nTrackId = (int)((uint32_t)packetList[i].flags >> 16);
if (pWriterForAudioStreams.count(nTrackId)) {
auto pWriter = pWriterForAudioStreams[nTrackId];
if (pWriter == nullptr) {
Expand Down
2 changes: 2 additions & 0 deletions QSVPipeline/qsv_prm.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ struct sInputParams
mfxU16 nFadeDetect;
int nSubtitleSelectCount;
SubtitleSelect **ppSubtitleSelectList;
int nDataSelectCount;
DataSelect **ppDataSelectList;
int64_t nPerfMonitorSelect;
int64_t nPerfMonitorSelectMatplot;
int nPerfMonitorInterval;
Expand Down
5 changes: 4 additions & 1 deletion QSVPipeline/rgy_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,14 @@ class RGYInput {
virtual int GetAudioTrackCount() {
return 0;
}

//入力ファイルに存在する字幕のトラック数を返す
virtual int GetSubtitleTrackCount() {
return 0;
}
//入力ファイルに存在するデータのトラック数を返す
virtual int GetDataTrackCount() {
return 0;
}
const TCHAR *GetInputMessage() {
const TCHAR *mes = m_strInputInfo.c_str();
return (mes) ? mes : _T("");
Expand Down
Loading

0 comments on commit 946da1b

Please sign in to comment.