Пример #1
0
void FFMS_VideoSource::SetVideoProperties() {
	VP.RFFDenominator = CodecContext->time_base.num;
	VP.RFFNumerator = CodecContext->time_base.den;
	if (CodecContext->codec_id == FFMS_ID(H264)) {
		if (VP.RFFNumerator & 1)
			VP.RFFDenominator *= 2;
		else
			VP.RFFNumerator /= 2;
	}
	VP.NumFrames = Frames.VisibleFrameCount();
	VP.TopFieldFirst = DecodeFrame->top_field_first;
	VP.ColorSpace = CodecContext->colorspace;
	VP.ColorRange = CodecContext->color_range;
	// these pixfmt's are deprecated but still used
	if (
		CodecContext->pix_fmt == PIX_FMT_YUVJ420P
		|| CodecContext->pix_fmt == PIX_FMT_YUVJ422P
		|| CodecContext->pix_fmt == PIX_FMT_YUVJ444P
		)
		VP.ColorRange = AVCOL_RANGE_JPEG;


	VP.FirstTime = ((Frames.front().PTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
	VP.LastTime = ((Frames.back().PTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;

	if (CodecContext->width <= 0 || CodecContext->height <= 0)
		throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
		"Codec returned zero size video");

	// attempt to correct framerate to the proper NTSC fraction, if applicable
	CorrectNTSCRationalFramerate(&VP.FPSNumerator, &VP.FPSDenominator);
	// correct the timebase, if necessary
	CorrectTimebase(&VP, &Frames.TB);

	// Set AR variables
	VP.SARNum = CodecContext->sample_aspect_ratio.num;
	VP.SARDen = CodecContext->sample_aspect_ratio.den;

	// Set input and output formats now that we have a CodecContext
	DetectInputFormat();

	OutputFormat = InputFormat;
	OutputColorSpace = InputColorSpace;
	OutputColorRange = InputColorRange;
}
Пример #2
0
void FlushBuffers(AVCodecContext *CodecContext) {
	if (CodecContext->codec->flush)
		avcodec_flush_buffers(CodecContext);
	else {
		// If the codec doesn't have flush(), it might not need it... or it
		// might need it and just not implement it as in the case of VC-1, so
		// close and reopen the codec
		const AVCodec *codec = CodecContext->codec;

		// Only flush blacklisted codecs, closing and reopening breaks far too
        // many decoders to always do as a fallback!!!

        // Further notes: VC1 does have a flush in recent versions so
        // maybe just remove all this junk unless more formats are found that
        // need it
		if (codec->id == FFMS_ID(VC1)) {
			avcodec_close(CodecContext);
			// Whether or not codec is const varies between versions
			if (avcodec_open2(CodecContext, const_cast<AVCodec *>(codec), nullptr) < 0)
				throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_CODEC,
				"Couldn't re-open codec.");
		}
	}
}
Пример #3
0
FFHaaliVideo::FFHaaliVideo(const char *SourceFile, int Track,
	FFMS_Index &Index, int Threads, FFMS_Sources SourceMode)
: Res(FFSourceResources<FFMS_VideoSource>(this)), FFMS_VideoSource(SourceFile, Index, Track, Threads) {
	BitStreamFilter = NULL;

	pMMC = HaaliOpenFile(SourceFile, SourceMode);

	CComPtr<IEnumUnknown> pEU;
	if (!SUCCEEDED(pMMC->EnumTracks(&pEU)))
		throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
			"Failed to enumerate tracks");

	CComPtr<IUnknown> pU;
	int CurrentTrack = -1;
	while (pEU->Next(1, &pU, NULL) == S_OK && ++CurrentTrack != Track) pU = NULL;
	CComQIPtr<IPropertyBag> pBag = pU;

	if (CurrentTrack != Track || !pBag)
		throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
			"Failed to find track");

	HCodecContext = InitializeCodecContextFromHaaliInfo(pBag);
	CodecContext = HCodecContext;

	const AVCodec *Codec = NULL;
	std::swap(Codec, CodecContext->codec);
	if (avcodec_open2(CodecContext, Codec, NULL) < 0)
		throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
			"Could not open video codec");

	CodecContext->thread_count = DecodingThreads;

	if (CodecContext->codec->id == FFMS_ID(H264) && SourceMode == FFMS_SOURCE_HAALIMPEG)
		BitStreamFilter = av_bitstream_filter_init("h264_mp4toannexb");

	Res.CloseCodec(true);

	// Always try to decode a frame to make sure all required parameters are known
	int64_t Dummy;
	DecodeNextFrame(&Dummy);

	VP.FPSDenominator = 1;
	VP.FPSNumerator = 30;

	// Calculate the average framerate
	if (Frames.size() >= 2) {
		double PTSDiff = (double)(Frames.back().PTS - Frames.front().PTS);
		VP.FPSDenominator = (unsigned int)(PTSDiff  / (double)1000 / (double)(Frames.size() - 1) + 0.5);
		VP.FPSNumerator = 1000000;
	}

	// Set the video properties from the codec context
	SetVideoProperties();

	// Output the already decoded frame so it isn't wasted
	OutputFrame(DecodeFrame);

	// Set AR variables
	CComVariant pV;

	USHORT Num = 0, Den = 0;

	pV.Clear();
	if (SUCCEEDED(pBag->Read(L"Video.DisplayWidth", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4)))
		Num = pV.uiVal;
	pV.Clear();
	if (SUCCEEDED(pBag->Read(L"Video.DisplayHeight", &pV, NULL)) && SUCCEEDED(pV.ChangeType(VT_UI4)))
		Den = pV.uiVal;

	if (Num && Den) {
		VP.SARNum = LocalFrame.EncodedHeight * Num;
		VP.SARDen = LocalFrame.EncodedWidth * Den;
	}
}
Пример #4
0
FFMS_CodecID MatroskaToFFCodecID(char *Codec, void *CodecPrivate, unsigned int FourCC, unsigned int BitsPerSample) {
	/* Look up native codecs */
	for (int i = 0; mkv_codec_tags[i].id != FFMS_ID(NONE); i++){
		if (!strncmp(mkv_codec_tags[i].str, Codec, strlen(mkv_codec_tags[i].str))) {
			// Uncompressed and exotic format fixup
			// This list is incomplete
			FFMS_CodecID CID = mkv_codec_tags[i].id;
			switch (CID) {
				case FFMS_ID(PCM_S16LE):
					switch (BitsPerSample) {
						case 8: CID = FFMS_ID(PCM_S8); break;
						case 16: CID = FFMS_ID(PCM_S16LE); break;
						case 24: CID = FFMS_ID(PCM_S24LE); break;
						case 32: CID = FFMS_ID(PCM_S32LE); break;
					}
					break;
				case FFMS_ID(PCM_S16BE):
					switch (BitsPerSample) {
						case 8: CID = FFMS_ID(PCM_S8); break;
						case 16: CID = FFMS_ID(PCM_S16BE); break;
						case 24: CID = FFMS_ID(PCM_S24BE); break;
						case 32: CID = FFMS_ID(PCM_S32BE); break;
					}
					break;
				default:
					break;
			}

			return CID;
		}
	}

	/* Video codecs for "avi in mkv" mode */
	const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), 0 };

	if (!strcmp(Codec, "V_MS/VFW/FOURCC")) {
		FFMS_BITMAPINFOHEADER *b = reinterpret_cast<FFMS_BITMAPINFOHEADER *>(CodecPrivate);
		return av_codec_get_id(tags, b->biCompression);
	}

	if (!strcmp(Codec, "V_FOURCC")) {
		return av_codec_get_id(tags, FourCC);
	}

	// FIXME
	/* Audio codecs for "acm in mkv" mode */
	//#include "Mmreg.h"
	//((WAVEFORMATEX *)TI->CodecPrivate)->wFormatTag

	/* Fixup for uncompressed video formats */

	/* Fixup for uncompressed audio formats */

	return FFMS_ID(NONE);
}
Пример #5
0
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.

#include "codectype.h"

#include "matroskaparser.h"
#include "utils.h"

typedef struct CodecTags {
	char str[20];
	FFMS_CodecID id;
} CodecTags;

static const CodecTags mkv_codec_tags[] = {
	{"A_AAC"               , FFMS_ID(AAC)},
	{"A_AC3"               , FFMS_ID(AC3)},
	{"A_DTS"               , FFMS_ID(DTS)},
	{"A_EAC3"              , FFMS_ID(EAC3)},
	{"A_FLAC"              , FFMS_ID(FLAC)},
	{"A_MLP"               , FFMS_ID(MLP)},
	{"A_MPEG/L2"           , FFMS_ID(MP2)},
	{"A_MPEG/L1"           , FFMS_ID(MP2)},
	{"A_MPEG/L3"           , FFMS_ID(MP3)},
#if VERSION_CHECK(LIBAVCODEC_VERSION_INT, >=, 54, 29, 0, 54, 60, 100)
	{"A_OPUS"              , FFMS_ID(OPUS)},
	{"A_OPUS/EXPERIMENTAL" , FFMS_ID(OPUS)}, /* Pre-final ID, for compatibility */
#endif
	{"A_PCM/FLOAT/IEEE"    , FFMS_ID(PCM_F32LE)},
	{"A_PCM/FLOAT/IEEE"    , FFMS_ID(PCM_F64LE)},
	{"A_PCM/INT/BIG"       , FFMS_ID(PCM_S16BE)},