[视频] 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<TUid> 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);
      }
  );
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值