예제 #1
0
long long PrePostRollFlagger::findBreakInrange(long long startFrame,
                                               long long stopFrame,
                                               long long totalFrames,
                                               long long &framesProcessed,
                                             QTime &flagTime, bool findLast)
{
    float flagFPS;
    int requiredBuffer = 30;
    long long currentFrameNumber;
    int prevpercent = -1;

    if(startFrame > 0)
        startFrame--;
    else
        startFrame = 0;

    player->DiscardVideoFrame(player->GetRawVideoFrame(0));

    long long tmpStartFrame = startFrame;
    VideoFrame* f = player->GetRawVideoFrame(tmpStartFrame);
    float aspect = player->GetVideoAspect();
    currentFrameNumber = f->frameNumber;
    LOG(VB_COMMFLAG, LOG_INFO, QString("Starting with frame %1")
            .arg(currentFrameNumber));
    player->DiscardVideoFrame(f);

    long long foundFrame = 0;

    while (player->GetEof() == kEofStateNone)
    {
        struct timeval startTime;
        if (stillRecording)
            gettimeofday(&startTime, NULL);

        VideoFrame* currentFrame = player->GetRawVideoFrame();
        currentFrameNumber = currentFrame->frameNumber;

        if(currentFrameNumber % 1000 == 0)
        {
            LOG(VB_COMMFLAG, LOG_INFO, QString("Processing frame %1")
                    .arg(currentFrameNumber));
        }

        if(currentFrameNumber > stopFrame || (!findLast && foundFrame))
        {
            player->DiscardVideoFrame(currentFrame);
            break;
        }

        double newAspect = currentFrame->aspect;
        if (newAspect != aspect)
        {
            SetVideoParams(aspect);
            aspect = newAspect;
        }

        if (((currentFrameNumber % 500) == 0) ||
            (((currentFrameNumber % 100) == 0) &&
             (stillRecording)))
        {
            emit breathe();
            if (m_bStop)
            {
                player->DiscardVideoFrame(currentFrame);
                return false;
            }
        }

        while (m_bPaused)
        {
            emit breathe();
            sleep(1);
        }

        // sleep a little so we don't use all cpu even if we're niced
        if (!fullSpeed && !stillRecording)
            usleep(10000);

        if (((currentFrameNumber % 500) == 0) ||
            ((showProgress || stillRecording) &&
             ((currentFrameNumber % 100) == 0)))
        {
            float elapsed = flagTime.elapsed() / 1000.0;

            if (elapsed)
                flagFPS = framesProcessed / elapsed;
            else
                flagFPS = 0.0;

            int percentage;
            if (stopFrame)
                percentage = framesProcessed * 100 / totalFrames;
            else
                percentage = 0;

            if (percentage > 100)
                percentage = 100;

            if (showProgress)
            {
                if (stopFrame)
                {
                    QString tmp = QString("\b\b\b\b\b\b\b\b\b\b\b%1%/%2fps")
                        .arg(percentage, 3).arg((int)flagFPS, 3);
                    QByteArray ba = tmp.toAscii();
                    cerr << ba.constData() << flush;
                }
                else
                {
                    QString tmp = QString("\b\b\b\b\b\b\b\b\b\b\b\b\b%1/%2fps")
                        .arg(currentFrameNumber, 6).arg((int)flagFPS, 3);
                    QByteArray ba = tmp.toAscii();
                    cerr << ba.constData() << flush;
                }
                cerr.flush();
            }

            if (stopFrame)
                emit statusUpdate(QObject::tr("%1% Completed @ %2 fps.")
                                  .arg(percentage).arg(flagFPS));
            else
                emit statusUpdate(QObject::tr("%1 Frames Completed @ %2 fps.")
                                  .arg((long)currentFrameNumber).arg(flagFPS));

            if (percentage % 10 == 0 && prevpercent != percentage)
            {
                prevpercent = percentage;
                LOG(VB_GENERAL, LOG_INFO, QString("%1%% Completed @ %2 fps.")
                    .arg(percentage) .arg(flagFPS));
            }
        }

        ProcessFrame(currentFrame, currentFrameNumber);

        if(frameInfo[currentFrameNumber].flagMask &
           (COMM_FRAME_SCENE_CHANGE | COMM_FRAME_BLANK))
        {
            foundFrame = currentFrameNumber;
        }

        if (stillRecording)
        {
            int secondsRecorded =
                recordingStartedAt.secsTo(MythDate::current());
            int secondsFlagged = (int)(framesProcessed / fps);
            int secondsBehind = secondsRecorded - secondsFlagged;
            long usecPerFrame = (long)(1.0 / player->GetFrameRate() * 1000000);

            struct timeval endTime;
            gettimeofday(&endTime, NULL);

            long long usecSleep =
                      usecPerFrame -
                      (((endTime.tv_sec - startTime.tv_sec) * 1000000) +
                       (endTime.tv_usec - startTime.tv_usec));

            if (secondsBehind > requiredBuffer)
            {
                if (fullSpeed)
                    usecSleep = 0;
                else
                    usecSleep = (long)(usecSleep * 0.25);
            }
            else if (secondsBehind < requiredBuffer)
                usecSleep = (long)(usecPerFrame * 1.5);

            if (usecSleep > 0)
                usleep(usecSleep);
        }

        player->DiscardVideoFrame(currentFrame);
        framesProcessed++;
    }
    return foundFrame;
}
예제 #2
0
bool PrePostRollFlagger::go()
{
    int secsSince = 0;
    int requiredBuffer = 120;
    int requiredHeadStart = requiredBuffer;
    bool wereRecording = stillRecording;

    secsSince = startedAt.secsTo(MythDate::current());
    while (stillRecording && (secsSince < requiredHeadStart))
    {
        emit statusUpdate(QObject::tr("Waiting to pass preroll + head start"));

        emit breathe();
        if (m_bStop)
            return false;

        sleep(5);
        secsSince = startedAt.secsTo(MythDate::current());
    }

    if (player->OpenFile() < 0)
        return false;

    Init();


    // Don't bother flagging short ~realtime recordings
    if ((wereRecording) && (!stillRecording) && (secsSince < requiredHeadStart))
        return false;

    aggressiveDetection =
        gCoreContext->GetNumSetting("AggressiveCommDetect", 1);

    if (!player->InitVideo())
    {
        LOG(VB_GENERAL, LOG_ERR,
            "NVP: Unable to initialize video for FlagCommercials.");
        return false;
    }
    player->EnableSubtitles(false);

    emit breathe();
    if (m_bStop)
        return false;

    QTime flagTime;
    flagTime.start();

    if (recordingStopsAt < MythDate::current() )
        myTotalFrames = player->GetTotalFrameCount();
    else
        myTotalFrames = (long long)(player->GetFrameRate() *
                        (recordingStartedAt.secsTo(recordingStopsAt)));



    if (showProgress)
    {
        if (myTotalFrames)
            cerr << "  0%/      ";
        else
            cerr << "     0/      ";
        cerr.flush();
    }

    float aspect = player->GetVideoAspect();

    SetVideoParams(aspect);

    emit breathe();

    long long stopFrame = preRoll + fps * 120; //look up to 2 minutes past
    long long framesToProcess = 0;
    if(preRoll)
        framesToProcess += stopFrame;
    if(postRoll)
        //guess two minutes before
        framesToProcess += myTotalFrames - postRoll + fps * 120;


    long long framesProcessed = 0;
    if(preRoll > 0)
    {
        //check from preroll after
        LOG(VB_COMMFLAG, LOG_INFO,
            QString("Finding closest after preroll(%1-%2)")
                .arg(preRoll).arg(stopFrame));

        closestAfterPre = findBreakInrange(preRoll, stopFrame, framesToProcess,
                                           framesProcessed, flagTime, false);

        LOG(VB_COMMFLAG, LOG_INFO, QString("Closest after preroll: %1")
                .arg(closestAfterPre));


        //check before preroll
        long long startFrame = 0;
        if(closestAfterPre)
            startFrame = preRoll - (closestAfterPre - preRoll) - 1;

        LOG(VB_COMMFLAG, LOG_INFO, QString("Finding before preroll (%1-%2)")
                .arg(startFrame).arg(preRoll));
        closestBeforePre = findBreakInrange(startFrame, preRoll,
                                            framesToProcess, framesProcessed,
                                            flagTime, true);
        LOG(VB_COMMFLAG, LOG_INFO, QString("Closest before preroll: %1")
                .arg(closestBeforePre));

        if(closestBeforePre || closestAfterPre)
            emit gotNewCommercialBreakList();

        // for better processing percent
        framesToProcess -= (stopFrame - framesProcessed);

    }

    if(stillRecording)
    {
        while (MythDate::current() <= recordingStopsAt)
        {
            emit breathe();
            if (m_bStop)
                return false;
            emit statusUpdate(QObject::tr("Waiting for recording to finish"));
            sleep(5);
        }
        stillRecording = false;
         myTotalFrames = player->GetTotalFrameCount();
    }

    if(postRoll > 0)
    {
        //check from preroll after
        long long postRollStartLoc = myTotalFrames - postRoll;
        LOG(VB_COMMFLAG, LOG_INFO,
            QString("Finding closest after postroll(%1-%2)")
                .arg(postRollStartLoc).arg(myTotalFrames));
        closestAfterPost = findBreakInrange(postRollStartLoc, myTotalFrames,
                                            framesToProcess, framesProcessed,
                                            flagTime, false);
        LOG(VB_COMMFLAG, LOG_INFO, QString("Closest after postRoll: %1")
                .arg(closestAfterPost));

        //check before preroll
        long long startFrame = 0;
        if(closestAfterPost)
            startFrame = postRollStartLoc
                         - (closestAfterPost - postRollStartLoc) - 1;

        LOG(VB_COMMFLAG, LOG_INFO,
            QString("finding closest before preroll(%1-%2)")
                .arg(startFrame).arg(postRollStartLoc));
        closestBeforePost = findBreakInrange(startFrame, postRollStartLoc,
                                             framesToProcess, framesProcessed,
                                             flagTime, true);
        LOG(VB_COMMFLAG, LOG_INFO, QString("Closest before postroll: %1")
                .arg(closestBeforePost));

        framesToProcess = framesProcessed;
    }

    if (showProgress)
    {
        //float elapsed = flagTime.elapsed() / 1000.0;

        //float flagFPS = (elapsed > 0.0f) ? (framesProcessed / elapsed) : 0.0f;

        if (myTotalFrames)
            cerr << "\b\b\b\b\b\b      \b\b\b\b\b\b";
        else
            cerr << "\b\b\b\b\b\b\b\b\b\b\b\b\b             "
                    "\b\b\b\b\b\b\b\b\b\b\b\b\b";
        cerr.flush();
    }

    return true;
}
예제 #3
0
HRESULT InitializeVideoEncoder(  AM_MEDIA_TYPE      *pmtInput,
							   VideoEncParams       *pParams,
							   IMediaObject         **ppDMO,
							   AM_MEDIA_TYPE        *pmtOutput,
							   CHandlingMediaBuffer *pMediaBuffer )
{
	HRESULT       hr             = S_OK;
	DWORD         cbInputBuffer  = 0;
	DWORD         cbOutputBuffer = 0;

	if( NULL == pmtInput || NULL == pParams || NULL == ppDMO )
	{
		return ( E_INVALIDARG );
	}

#ifdef SUPPORT_INTERLACE
	//
	// Interlace encoding using IYUV or I420 at the input is not supported
	//
	if( NULL == pmtInput->pbFormat )
	{
		return ( E_INVALIDARG );
	}
	if( WMCFOURCC_IYUV == ((VIDEOINFOHEADER*)pmtInput->pbFormat)->bmiHeader.biCompression ||
		WMCFOURCC_I420 == ((VIDEOINFOHEADER*)pmtInput->pbFormat)->bmiHeader.biCompression )
	{
		if( TRUE == pParams->fIsInterlaced )
		{
			return ( E_VIDEO_INTERLACE_REJECTED );
		}
	}
#endif //SUPPORT_INTERLACE

	*ppDMO = NULL;

	//
	//check to see if the video bitrate has been set; if not calculate the default
	//
	if( pParams->nBitrate <= 0 )
	{
		hr = DefaultVideoBitrate( pmtInput, pParams->dFrameRate, &pParams->nBitrate );
		if( FAILED( hr ) )
		{
			return ( hr );
		}
		if( pParams->nPeakBitrate <= 0 )
		{
			pParams->nPeakBitrate = 3 * pParams->nBitrate;
		}
	}
	do
	{
		//
		// Create the DMO Encoder
		//
		CLSID clsid=CLSID_NULL;
		char fcc[]="1234";memcpy(fcc,&pParams->dwTag,4);
		switch (pParams->dwTag)
		{
		case WMCFOURCC_MSS1:
		case WMCFOURCC_MSS2:
			clsid=CLSID_CMSSCEncMediaObject2;
			break;
		case WMCFOURCC_WMVA:
		case WMCFOURCC_WVP2:
			clsid=CLSID_CWMV9EncMediaObject;
			break;
		case WMCFOURCC_WMV1:
		case WMCFOURCC_WMV2:
		case WMCFOURCC_WMV3:
		case WMCFOURCC_WMVP:
		case WMCFOURCC_MP4S:
		case WMCFOURCC_MP43:
		default:
			clsid=CLSID_CWMVEncMediaObject2;
			break;
		}  
		hr = CoCreateInstance( clsid,
			NULL,
			CLSCTX_INPROC_SERVER,
			IID_IMediaObject,
			(void**)ppDMO);

		if( FAILED( hr ) )
		{
			break;
		}

		hr = SetVideoParams( *ppDMO, pParams );
		if( FAILED( hr ) )
		{
			break;
		}

		hr = SetVideoTypes( *ppDMO, pmtInput, pParams, pmtOutput, &cbInputBuffer, &cbOutputBuffer );
		if( FAILED( hr ) )
		{
			break;
		}

#ifdef SUPPORT_INTERLACE
		if( pParams->dwTag == WMCFOURCC_WMV3 && pParams->fIsInterlaced)
		{
			INSSBuffer3 *pINSSBuffer3 = NULL;
			BYTE        bType         = WM_CT_INTERLACED;

			hr = pMediaBuffer->QueryInterface( IID_INSSBuffer3, (void**)&pINSSBuffer3 );
			if( FAILED( hr ) )
			{
				break;
			}
			pINSSBuffer3->SetProperty( WM_SampleExtension_ContentType,
				&bType,
				1 );
			SAFERELEASE( pINSSBuffer3 );
		}
#endif //SUPPORT_INTERLACE

	}
	while ( FALSE );

	if( S_OK != hr )
	{
		SAFERELEASE( *ppDMO );
	}

	return ( hr );
}