[视频] Symbian中视频API的使用 (S60 3rd FP1)

Clients using either of the CVideoPlayerUtility and CVideoRecorderUtility classes must have an active scheduler running in their thread because the implementations use active objects and callbacks.
 
一.CVideoPlayerUtility
二.CVideoRecorderUtility
 
一.CVideoPlayerUtility
播放视频。注意,经过试验,这个类是通过直接写屏的方式来播放视频的。
 
class CMediaContainer : public CCoeControl
{
...
public:
    inline RWindow& ClientWindow();
...
};
...
inline RWindow& CMediaContainer::ClientWindow()
    {
     return Window(); // CCoeControl::Window()方法是protected类型的。
   
}
...
CMediaContainer * iAppView = CMediaContainer::NewLC(aRect);
...
CVideoPlayerUtility * iPlayer = CVideoPlayerUtility::NewL(
    aMVideoPlayerUtilityObserver,
    EMdaPriorityNormal, EMdaPriorityPreferenceTimeAndQuality,
    iAppView->ControlEnv()->WsSession(), 
    *(iAppView->ControlEnv()->ScreenDevice()), iAppView->ClientWindow(),
    iAppView->Rect(), iAppView->Rect());
...
iPlayer->OpenFileL( KDirVideos); /* 打开资源。异步方法,打开完成后会调用aMVideoPlayerUtilityObserver.MvpuoOpenComplete(TInt aError)方法 */
/* http:// URLs are not supported. However, from S60 2nd Edition FP2 onwards OpenUrlL() from CVideoPlayerUtility can be used for opening rtsp:// URLs with RealAudio (audio-only) streams. */
...
void CMyMVideoPlayerUtilityObserver::MvpuoOpenComplete(TInt aError )
    {
    if(KErrNone == aError)
    {
        /* Following the opening of the video clip, configuration adjustments can be made using the methods described below:
        SetPriorityL() and PriorityL() - sets the priority of the video/audio device which is used to arbitrate between multiple objects trying to access a controller.
        AudioEnabledL() - determines whether an audio track is present within the video clip.
        VideoFrameSizeL() - get the current frame size of the video clip.
        SetDisplayWindowL() - set the display window to use when playing back the video clip.
        VideoFormatMimeType() - retrieve the MIME type of the video clip currently opened.
        VideoTypeL() - retrieve the codecs used by the video clip .
        AudioTypeL() - retrieve the codecs used by possible audio track.
        AudioEnabledL()
        VideoBitRateL().
        AudioBitRateL().
        VideoFrameRateL().
        Volume(), SetVolumeL() and MaxVolume().
        SetBalanceL() Balance().
        */
        iPlayer->Prepare(); /* Prepares the video clip to be accessed. 异步方法,完成后会调用aMVideoPlayerUtilityObserver.MvpuoPrepareComplete(TInt aError)方法 */
    }
    else
        {
        iPlayer->Stop();
        iPlayer->Close();
        }
    }
void CMyMVideoPlayerUtilityObserver::MvpuoPrepareComplete(TInt aError )
    {
    if(KErrNone == aError)
        iPlayer->Play(); /* 播放. 异步方法,完成后会调用aMVideoPlayerUtilityObserver.MvpuoPlayComplete(TInt aError)方法。But the notify function isn't called if playback is explicitly stopped by calling Stop() */
        /* iPlayer->Play(const TTimeIntervalMicroSeconds &aStartPoint, const TTimeIntervalMicroSeconds &aEndPoint); */
        /*
        在调用了播放之后,可以调用以下方法:
        DurationL() - determine the duration of the video clip in microseconds.
        SetPositionL() - sets the current playing position within the video clip.
        GetFrame() - uses the MVideoPlayerUtilityObserver::MvpuoFrameReady() callback to return a bitmap of the frame currently being played (when playing or paused),
    But according to Forum Nokia Technical Library v1.33
Overview:
    Extracting the first frame (e.g., for the purpose of creating a thumbnail image) of a video file using CVideoPlayerUtility::GetFrameL() does not work
    Reported against:
S60 2nd Edition, S60 3rd Edition, Series 80 2nd Edition, All devices
    Detailed description:
When an application tries to extract the first frame of a video file by calling GetFrameL(), the MvpuoFrameReady method of the MVideoPlayerUtilityObserver class is never called.
    Solution:
No known solution in the public SDK – CVideoPlayerUtility::GetFrameL() is not implemented.

        RefreshFrameL() - re-draw the current frame.
        RegisterForRebufferingNotification() - activate callbacks that report on video rebuffering.
        */
    else
        {
        iPlayer->Stop();
        iPlayer->Close();
        }
    }
void CMyMVideoPlayerUtilityObserver::MvpuoPlayComplete(TInt aError)
    {
    if(aError != KErrNone)
        {
        iPlayer->Stop();
        iPlayer->Close();
        }
    }
 
/* General event notification from controller. These events are specified by the supplier of the controller */
void CMyMVideoPlayerUtilityObserver::MvpuoEvent(const TMMFEvent& aEvent)
    {
    ... // do something
    }
 
/* Notification that the frame requested by a call to GetFrameL() is ready */
void CMyMVideoPlayerUtilityObserver::MvpuoFrameReady(CFbsBitmap& aFrame,TInt aError)
    {
    ... // do something
    }
 
 
二.CVideoRecorderUtility
录制视频的工具类
 
    S60手机上不支持视频录音应用类的下列方法:
CVideoRecorderUtility::OpenDesL()
CVideoRecorderUtility::OpenFileL(const RFile &aFile, ...)
CVideoRecorderUtility::OpenUrlL()
    详细描述:
调用时,CVideoRecorderUtility::OpenDesL()OpenUrlL方法都会返回KErrNotSupported(-5)错误,这是因为Camera(Cmacorder)MMF控制器中尚未实现这些方法。尚未支持从内存缓冲中逐帧播放视频,或者录制到一个缓冲或URL位置。
同样的,在调用CVideoRecorderUtility::OpenFileL(const RFile &aFile, ...)方法时,传递一个文件句柄(RFile&)作为参数时也会发生这样的问题。调用时不会发生异常,也不会在MVideoRecorderUtilityObserver回调函数中立即返回错误。但当你尝试录音时调用到MvruoRecordComplete()方法,就会发生KErrCompletion(-17)错误。而且不会有任何数据写到前面的句柄参数中。
    解决方案:
CVideoRecorderUtility::OpenDesL()CVideoRecorderUtility::OpenUrlL()尚未支持可以使用CVideoRecorderUtility::OpenFileL(const TDesC &aFileName, ...)录制视频内容到相关文件中。
 
CVideoRecorderUtility * iUtility = CVideoRecorderUtility::NewL(aMVideoRecorderUtilityObserver);
...
// Retrieve a list of controllers
CMMFControllerPluginSelectionParameters* cSelect = CMMFControllerPluginSelectionParameters::NewLC();
// Resolve the supported video format
CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC();
 
/* Set the play and record format selection parameters to be blank. Format support is only retrieved if requested. */
cSelect->SetRequiredPlayFormatSupportL(*fSelect);
cSelect->SetRequiredRecordFormatSupportL(*fSelect);
 
 // Set the media ids
RArray mediaIds;
CleanupClosePushL(mediaIds);
User::LeaveIfError(mediaIds.Append(KUidMediaTypeVideo));
// Get plugins that support at least video
cSelect->SetMediaIdsL(mediaIds, CMMFPluginSelectionParameters::EAllowOtherMediaIds);
cSelect->SetPreferredSupplierL(KNullDesC, CMMFPluginSelectionParameters::EPreferredSupplierPluginsFirstInList);
 
// Array to hold all the controllers support the match data
RMMFControllerImplInfoArray controllers;
CleanupResetAndDestroyPushL(controllers);
cSelect->ListImplementationsL(controllers);
 
// Find the first controller with at least one record format available
for(TInt i = 0; i < controllers.Count(); ++i)
  {
  RMMFFormatImplInfoArray recordFormats = controllers[i]->RecordFormats();
  if(recordFormats.Count() > 0)
   {
   iControllerUid = controllers[i]->Uid();
   iFormatUid = recordFormats[0]->Uid();
   recordingSupported = ETrue;
   break;
   }
 }
 
CleanupStack::PopAndDestroy(&controllers);
CleanupStack::PopAndDestroy(&mediaIds);
CleanupStack::PopAndDestroy(fSelect);
CleanupStack::PopAndDestroy(cSelect);
 
// Leave if recording is not supported
if(!recordingSupported)
 {
 User::Leave(KErrNotSupported);
 }
 
...
//In 3rd edition:
//Use Feature Discovery API to see if there's camera or video recorder:
TBool isSupported = ETrue;
#ifdef __SERIES60_3X__
if (!CFeatureDiscovery::IsFeatureSupportedL(KFeatureIdCamera)
    && !CFeatureDiscovery::IsFeatureSupportedL(KFeatureIdVideoRecorder) )
    {
    isSupported = EFalse;
    }
#endif
if (isSupported)
    {
    //iEngine->SetEngineState(CVRexEngine::EPreview);
    //AppUi()->ActivateLocalViewL(KView2Id);
     if ( !CCamera::CamerasAvailable() )
     {
     //Handle KErrHardwareNotAvailable error here
     return;
     }
    iCamera = CCamera::NewL(aMCameraObserver, 0); // Use the first camera
    StartL(iCamera->Handle()); // 此方法在后边被定义
    }
else
    {
    /* This only occurs in 3rd edition if there's no camera reported by Feature Discovery API. */
    // Note that Feature Discovery API is available already in 2nd edition FP3.
    //User::Leave(KErrNotSupported);
    CAknInformationNote* informationNote;
    informationNote = new ( ELeave ) CAknInformationNote;
    informationNote->ExecuteLD( _L("There's no camera in this device"));
    }
...
void CVideoRecorderAdapter::StartL(TInt aCameraHandle)
 {
 // Set callbacks for UI updates
 // iCtrlrListener = aCallback;
 TFileName filePath = PathInfo::PhoneMemoryRootPath();
 filePath.Append(PathInfo::VideosPath());
 filePath.Append(_L("NewVideo.3gp"));
 /* Open file. On completion, MVideoRecorderUtilityObserver::MvruoOpenComplete will be called, and it will initiate the recording process by calling iUtility->Prepare. */
 iUtility->OpenFileL(filePath, aCameraHandle, iControllerUid, iFormatUid);
 }
...
void CMyMVideoRecorderUtilityObserver::MvruoOpenComplete(TInt aError)
{
 if(aError==KErrNone)
  {
  // Sets the maximum recording size for a video clip in bytes.
  TRAPD(err, iUtility->SetMaxClipSizeL(64*1024)); // 64k
  if(err==KErrNone)
   {
   iUtility->Prepare(); /* 异步方法。完成后会调用MVideoRecorderUtilityObserver::MvruoPrepareComplete()通知方法 */
   //iState = EOpenCompelete;
   }
  else
   {
   //iState = ENotInitialized;
   }
  }
 else
  {
  //iState = ENotInitialized;
  }
}
 
void CMyMVideoRecorderUtilityObserver::MvruoPrepareComplete(TInt aError)
{
 if(aError==KErrNone)
  {
  if(!iProgressUpdater->IsActive())
    {
    iProgressUpdater->Start(ETwelveOClock, aMBeating);
    // iRecPosition = 0;
    }
  iUtility->Record(); // 开始录制
  // iState = ERecording;
  }
}
 
void CMyMVideoRecorderUtilityObserver::MvruoRecordComplete(TInt aError)
{
  if((aError==KErrNone) || (aError==KErrCompletion))
  {
  iUtility->Stop();
  iUtility->Close();
  iState = ERecordComplete;
  if (iCtrlrListener)
    {
    TRAPD(ignored, iCtrlrListener->RecordCompletedL(aError));
    }
  }
}
 
/*
This method handles a regular heartbeat timer event. This type of event is one where the timer completes in synchronisation with the system clock. */
void CMyMBeating::Beat()
{
    // Keep the backlight on while recording
    User::ResetInactivityTime();
    if (iState != ERecording)
       return;
    TInt64 ret = iRecPosition % 2;
#ifndef __SERIES60_3X__
    if(ret.GetTInt())
#else
    if((TInt)ret)
#endif
    {
        iRecPosition++;
        if (iCtrlrListener)
      {
      TRAPD(ignored,iCtrlrListener->PlaybackPositionChangedL(iRecPosition, 0));
      }
    }
    else
    {
        Synchronize();
    }
}
void CVideoRecorderAdapter::Synchronize()
{
  if(iState != ERecording)
    return;
  // when is recording.
  TRAPD(ignored,
    // If live stream, fake progress
    iRecPosition = iUtility->DurationL().Int64() / KMPOneSecond;
      if (iCtrlrListener)
      {
        iCtrlrListener->PlaybackPositionChangedL(iRecPosition,0);
      }
  );
}

你可能感兴趣的:(symbian,api,symbian,fp,video,playback,parameters)