OpenHarmony开发者论坛
标题:
Video组件播放损坏的音视频文件导致应用卡死问题分析报告
[打印本页]
作者:
Laval社区小助手
时间:
2024-1-2 16:33
标题:
Video组件播放损坏的音视频文件导致应用卡死问题分析报告
[md]# 1 关键字
Video;
# 2 问题描述
开发板型号:rk3568
内核版本:Release 3.1
问题现象:
* 播放损坏的音频文件,点击了 start,然后点击 stop ,然后再点击start,应用卡死。
测试步骤:
1. 使用Video组件,设置播放的流媒体文价为损坏的的文件;
2. 调用controller.start方法;
3. 调用controller.stop方法;
4. 再调用controller.start方法,应用卡死。
# 3 问题原因
## 3.1 正常机制
播放损坏的音频文件,Video组件的OnError事件可以回调,在收到OnError回调后,切换媒体资源文件。
## 3.2 异常机制
播放损坏的音频文件,Video组件的OnError事件没有回调,没有切换媒体资源文件,调用stop方法后,video\_element.cpp 中的 isStop 变量设置为true。
```
void VideoElement::Stop()
{
OnCurrentTimeChange(0);
OnPlayerStatus(PlaybackStatus::STOPPED);
......
isStop_ = true;
}
```
再次调用start,由于isStop 为true,mediaPlayer->
repare() 方法执行,导致应用卡死。
```
void VideoElement::Start()
{
......
if (isStop_) {
// 方法执行,应用卡死
if (mediaPlayer_->
repare() != 0) {
LOGE("
layer prepare failed");
return;
}
}
......
}
```
* video\_element.cpp 文件路径:foundation\\ace\\ace\_engine\\frameworks\\core\\components\\video\\video\_element.cpp
# 4 解决方案
将媒体底层上报的错误回调给Video组件。
修改 media\_player\_callback.h,将OnError事件反馈给video\_element。
```
using ErrorEvent = std::function<void()>;
void OnError(Media:
layerErrorType errorType, int32_t errorCode) override
{
LOGE("OnError callback, errorType: %{public}d, errorCode: %{public}d", errorType, errorCode);
ContainerScope scope(instanceId_);
if (errorEvent_) {
errorEvent_();
}
}
void SetErrorEvent(ErrorEvent&& errorEvent)
{
errorEvent_ = std::move(errorEvent);
}
private:
......
StateChangedEvent stateChangedEvent_;
ErrorEvent errorEvent_;
......
```
修改 video\_element.cpp,添加OnError回调。
```
void VideoElement::RegistMediaPlayerEvent()
{
......
auto&& errorEvent = [videoElement, uiTaskExecutor]() {
uiTaskExecutor.PostTask([&videoElement] {
auto video = videoElement.Upgrade();
if (video) {
LOGD("OnError");
video->OnError("", "");
}
});
};
mediaPlayerCallback_ = std::make_shared<MediaPlayerCallback>(ContainerScope::CurrentId());
mediaPlayerCallback_->SetPositionUpdatedEvent(positionUpdatedEvent);
mediaPlayerCallback_->SetStateChangedEvent(stateChangedEvent);
// 添加回调
mediaPlayerCallback_->SetEndOfStreamEvent(endOfStreamEvent);
mediaPlayer_->SetPlayerCallback(mediaPlayerCallback_);
}
```
在前端ETS中,为Video设置onError监听,onError回调,设置下一个资源文件。
# 5 定位过程
为video\_element.cpp中的OnStart添加日志,在调用Stop后再次调用Start,代码执行了mediaPlayer->
repare()方法,导致应用卡死。
```
void VideoElement::Start()
{
......
if (isStop_) {
// 方法执行,应用卡死
if (mediaPlayer_->
repare() != 0) {
LOGE("
layer prepare failed");
return;
}
}
......
}
```
媒体文件缓冲失败,media\_player\_callback.h 中的OnError会打印error日志。
```
void OnError(Media:
layerErrorType errorType, int32_t errorCode) override
{
LOGE("OnError callback, errorType: %{public}d, errorCode: %{public}d", errorType, errorCode);
}
```
这里只回调打印了日志,没有将错误回调给Video组件。
# 6 知识分享
视频播放源的路径,支持本地视频路径和网络路径,使用网络视频时,需要在config或者module.json对应的"abilities"中添加网络使用权限ohos.permission.INTERNET。
支持在resources下面的video或rawfile文件夹里放置媒体资源。
支持dataability://的路径前缀,用于访问通过 DataAbility提供的视频路径。
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5