媒体子系统.md 17.0 KB
Newer Older
N
NEEN 已提交
1 2 3 4 5 6 7 8
# 媒体子系统<a name="ZH-CN_TOPIC_0000001083456986"></a>

-   [简介](#section38510214395)
-   [目录结构](#section1937963913399)
-   [约束](#section722512541395)
-   [安装](#section11914418405)
-   [使用](#section1467220266400)
-   [涉及仓](#section7666411192217)
W
wenjun 已提交
9 10 11

## 简介<a name="section38510214395"></a>

H
harmony_zhangjian 已提交
12
该仓主要用于存放媒体子系统的源码信息,旨在为多媒体应用开发者开发者提供统一的开发接口,使得开发者可以专注于应用业务的开发,轻松使用多媒体的资源。下图分别展现媒体子系统的框架及业务流程。
W
wenjun 已提交
13

N
NEEN 已提交
14 15
**图 1**  媒体子系统框架图<a name="fig14437165910531"></a>  
![](figures/媒体子系统框架图.png "媒体子系统框架图")
W
wenjun 已提交
16

N
NEEN 已提交
17
媒体子系统框架支持相机、录像和播放业务功能,这些功能支持JS应用开发及各种使用媒体能力的KIT模块开发,媒体子系统框架包括框架层,框架层对外提供应用调用的native接口及其对应的业务实现,针对相机、录像及播放业务,框架层实现了音视频输入输出,音视频编解码,视频文件的打包及解复用等功能。系统服务层,系统服务层利用平台提供的能力去实现对底层硬件及相关驱动使用。
W
wenjun 已提交
18

N
NEEN 已提交
19 20
**图 2**  媒体子系统业务流程图<a name="fig69091712152911"></a>  
![](figures/媒体子系统业务流程图.png "媒体子系统业务流程图")
W
wenjun 已提交
21

N
NEEN 已提交
22
多媒体包括camera,recorder和player,camera提供YUV、RGB、JPEG以及H264,H265数据到共享内存surface中,recorder模块将surface中h264/h265数据和音频aac数据打包成mp4文件,player模块把mp4文件解复用成音频和视频数据,分别送入对应编码器解码,然后进行播放。
W
wenjun 已提交
23

H
harmony_zhangjian 已提交
24
## 目录结构<a name="section1937963913399"></a>
W
wenjun 已提交
25

N
NEEN 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
其中媒体子系统框架的源代码目录结构如下(只列举了主要部分):

```
foundation/multimedia                                      # 媒体子系统主目录
├── audio_lite 
│   ├── frameworks                                     # 音频框架模块实现
│   └── interfaces                                     # 音频框架模块接口定义
├── camera_lite
│   ├── frameworks                                     # 相机框架模块实现
│   └── interfaces                                     # 相机框架模块接口定义
├── media_lite
│   ├── frameworks                                     
│   │   ├── player_lite                               # 播放框架模块实现
│   │   └── recorder_lite                             # 录制框架模块实现
│   └── interfaces
│   │   └── kits
│   │       ├── player_lite                            # 播放框架模块接口实现
│   │       └── recorder_lite                          # 录制框架模块接口实现
│   ├── services                                        # 服务启动代码
│   └── test                                            # 测试代码
└── utils
    └── lite                                            # 应用接口通用模块实现
         └── hals                                       # 定义媒体适配的接口头文件
```
W
wenjun 已提交
50 51 52 53 54 55 56 57

## 约束<a name="section722512541395"></a>

-   C++11版本或以上

## 安装<a name="section11914418405"></a>

-   请提前加载内核及相关驱动,参考内核及驱动子系统readme。
N
NEEN 已提交
58
-   配置合适的配置文件,可以参考applications/sample/camera/media下配置文件,如果适配其他sensor可在开源社区中求助。用户使用时将配置文件放入到开发板/storage/data目录,开发者通过该配置文件可以去适配sensor及分辨率、帧率等能力。
W
wenjun 已提交
59 60 61

## 使用<a name="section1467220266400"></a>

N
NEEN 已提交
62
Native应用接口调用可以参考applications/sample/camera/media下demo实现
H
harmony_zhangjian 已提交
63

N
NEEN 已提交
64
应用开发者使用多媒体接口实现录像、预览和播放音视频,使用可以参考《多媒体开发指南》。
H
harmony_zhangjian 已提交
65

N
NEEN 已提交
66
开发者先创建camerakit组件对象,注册各种事件回调,这些事件回调是用来响应多媒体模块中事件响应的,之后调用创建camera就可以创建一个操作camera资源的对象,使用这个对象可以启动预览、录像或抓拍取流,及设置取流的相关参数。
H
harmony_zhangjian 已提交
67

N
NEEN 已提交
68
重写事件类的代码实例如下:
W
wenjun 已提交
69 70 71 72 73 74

```
#include "camera_kit.h"
#include "recorder.h"

#include <algorithm>
N
NEEN 已提交
75 76
#include <cstring>
#include <fcntl.h>
W
wenjun 已提交
77 78 79
#include <fstream>
#include <iostream>
#include <sstream>
N
NEEN 已提交
80 81 82 83
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
W
wenjun 已提交
84 85 86 87 88

using namespace std;
using namespace OHOS;
using namespace OHOS::Media;

N
NEEN 已提交
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
static int32_t SampleGetRecordFd()
{
    struct timeval tv = {};
    gettimeofday(&tv, nullptr);
    struct tm *ltm = localtime(&tv.tv_sec);
    int32_t fd = -1;
    if (ltm != nullptr) {
        ostringstream ss("Capture_");
        ss << "Record" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".mp4";
        fd = open(("/sdcard/" + ss.str()).c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
        cout << "Open "
             << "/sdcard/" << ss.str() << endl;

        if (fd == -1) {
            cout << "Open recorder file failed. strerr=" << strerror(errno) << endl;
        }
    }
    return fd;
}

W
wenjun 已提交
109 110 111
static void SampleSaveCapture(const char *p, uint32_t size)
{
    cout << "Start saving picture" << endl;
N
NEEN 已提交
112 113
    struct timeval tv = {};
    gettimeofday(&tv, nullptr);
W
wenjun 已提交
114 115 116 117 118 119 120 121
    struct tm *ltm = localtime(&tv.tv_sec);
    if (ltm != nullptr) {
        ostringstream ss("Capture_");
        ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg";

        ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc);
        cout << "write " << size << " bytes" << endl;
        pic.write(p, size);
N
NEEN 已提交
122
        pic.close();
W
wenjun 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135 136
        cout << "Saving picture end" << endl;
    }
}

Recorder *SampleCreateRecorder()
{
    int ret = 0;
    int32_t sampleRate = 48000;
    int32_t channelCount = 1;
    AudioCodecFormat audioFormat = AAC_LC;
    AudioSourceType inputSource = AUDIO_MIC;
    int32_t audioEncodingBitRate = sampleRate;
    VideoSourceType source = VIDEO_SOURCE_SURFACE_ES;
    int32_t frameRate = 30;
N
NEEN 已提交
137
    double fps = 30;
W
wenjun 已提交
138 139 140 141 142 143 144 145 146 147 148 149
    int32_t rate = 4096;
    int32_t sourceId = 0;
    int32_t audioSourceId = 0;
    int32_t width = 1920;
    int32_t height = 1080;
    VideoCodecFormat encoder;
    encoder = HEVC;
    width = 1920;
    height = 1080;
    Recorder *recorder = new Recorder();
    if ((ret = recorder->SetVideoSource(source, sourceId)) != SUCCESS) {
        cout << "SetVideoSource failed." << ret << endl;
N
NEEN 已提交
150
        goto ERROR;
W
wenjun 已提交
151 152 153
    }
    if ((ret = recorder->SetVideoEncoder(sourceId, encoder)) != SUCCESS) {
        cout << "SetVideoEncoder failed." << ret << endl;
N
NEEN 已提交
154
        goto ERROR;
W
wenjun 已提交
155 156 157
    }
    if ((ret = recorder->SetVideoSize(sourceId, width, height)) != SUCCESS) {
        cout << "SetVideoSize failed." << ret << endl;
N
NEEN 已提交
158
        goto ERROR;
W
wenjun 已提交
159 160 161
    }
    if ((ret = recorder->SetVideoFrameRate(sourceId, frameRate)) != SUCCESS) {
        cout << "SetVideoFrameRate failed." << ret << endl;
N
NEEN 已提交
162
        goto ERROR;
W
wenjun 已提交
163 164 165
    }
    if ((ret = recorder->SetVideoEncodingBitRate(sourceId, rate)) != SUCCESS) {
        cout << "SetVideoEncodingBitRate failed." << ret << endl;
N
NEEN 已提交
166
        goto ERROR;
W
wenjun 已提交
167
    }
N
NEEN 已提交
168
    if ((ret = recorder->SetCaptureRate(sourceId, fps)) != SUCCESS) {
W
wenjun 已提交
169
        cout << "SetCaptureRate failed." << ret << endl;
N
NEEN 已提交
170
        goto ERROR;
W
wenjun 已提交
171 172 173
    }
    if ((ret = recorder->SetAudioSource(inputSource, audioSourceId)) != SUCCESS) {
        cout << "SetAudioSource failed." << ret << endl;
N
NEEN 已提交
174
        goto ERROR;
W
wenjun 已提交
175 176 177
    }
    if ((ret = recorder->SetAudioEncoder(audioSourceId, audioFormat)) != SUCCESS) {
        cout << "SetAudioEncoder failed." << ret << endl;
N
NEEN 已提交
178
        goto ERROR;
W
wenjun 已提交
179 180 181
    }
    if ((ret = recorder->SetAudioSampleRate(audioSourceId, sampleRate)) != SUCCESS) {
        cout << "SetAudioSampleRate failed." << ret << endl;
N
NEEN 已提交
182
        goto ERROR;
W
wenjun 已提交
183 184 185
    }
    if ((ret = recorder->SetAudioChannels(audioSourceId, channelCount)) != SUCCESS) {
        cout << "SetAudioChannels failed." << ret << endl;
N
NEEN 已提交
186
        goto ERROR;
W
wenjun 已提交
187 188 189
    }
    if ((ret = recorder->SetAudioEncodingBitRate(audioSourceId, audioEncodingBitRate)) != SUCCESS) {
        cout << "SetAudioEncodingBitRate failed." << ret << endl;
N
NEEN 已提交
190 191 192 193 194
        goto ERROR;
    }
    if ((ret = recorder->SetMaxDuration(36000)) != SUCCESS) { // 36000s=10h
        cout << "SetAudioEncodingBitRate failed." << ret << endl;
        goto ERROR;
W
wenjun 已提交
195 196
    }
    return recorder;
N
NEEN 已提交
197 198 199 200

ERROR:
    delete recorder;
    return nullptr;
W
wenjun 已提交
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
}

class SampleFrameStateCallback : public FrameStateCallback {
    void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override
    {
        cout << "Receive frame complete inform." << endl;
        if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) {
            cout << "Capture frame received." << endl;
            list<Surface *> surfaceList = fc.GetSurfaces();
            for (Surface *surface : surfaceList) {
                SurfaceBuffer *buffer = surface->AcquireBuffer();
                if (buffer != nullptr) {
                    char *virtAddr = static_cast<char *>(buffer->GetVirAddr());
                    if (virtAddr != nullptr) {
                        SampleSaveCapture(virtAddr, buffer->GetSize());
                    }
                    surface->ReleaseBuffer(buffer);
                }
                delete surface;
            }
        }
N
NEEN 已提交
222
        delete &fc;
W
wenjun 已提交
223 224 225 226 227 228 229 230 231
    }
};

class SampleCameraStateMng : public CameraStateCallback {
public:
    SampleCameraStateMng() = delete;
    SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {}
    ~SampleCameraStateMng()
    {
N
NEEN 已提交
232
        CloseRecorder();
W
wenjun 已提交
233 234 235 236 237 238 239 240 241 242 243 244
    }
    void OnCreated(Camera &c) override
    {
        cout << "Sample recv OnCreate camera." << endl;
        auto config = CameraConfig::CreateCameraConfig();
        config->SetFrameStateCallback(&fsCb_, &eventHdlr_);
        c.Configure(*config);
        cam_ = &c;
    }
    void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {}
    void OnReleased(Camera &c) override {}

N
NEEN 已提交
245
    void CloseRecorder()
W
wenjun 已提交
246
    {
N
NEEN 已提交
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
        if (recorder_ != nullptr) {
            recorder_->Stop(true);
            recorder_->Release();
            delete recorder_;
            recorder_ = nullptr;
        }
        if (recordFd_ != -1) {
            close(recordFd_);
            recordFd_ = -1;
        }
    }

    int PrepareRecorder()
    {
        if (cam_ == nullptr) {
            cout << "Camera is not ready." << endl;
            return -1;
W
wenjun 已提交
264 265 266 267 268
        }
        if (recorder_ == nullptr) {
            recorder_ = SampleCreateRecorder();
        }
        if (recorder_ == nullptr) {
N
NEEN 已提交
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
            cout << "Recorder not available." << endl;
            return -1;
        }
        if (recordFd_ == -1) {
            recordFd_ = SampleGetRecordFd();
        }
        if (recordFd_ == -1) {
            cout << "Create fd failed." << endl;
            return -1;
        }
        return SUCCESS;
    }

    void StartRecord()
    {
        if (recordState_ == STATE_RUNNING) {
            cout << "Camera is already recording." << endl;
            return;
        }
        int ret = PrepareRecorder();
        if (ret != SUCCESS) {
            cout << "PrepareRecorder failed." << endl;
            CloseRecorder();
W
wenjun 已提交
292 293
            return;
        }
N
NEEN 已提交
294
        ret = recorder_->SetOutputFile(recordFd_);
W
wenjun 已提交
295
        if (ret != SUCCESS) {
N
NEEN 已提交
296 297
            cout << "SetOutputPath failed. ret=" << ret << endl;
            CloseRecorder();
W
wenjun 已提交
298 299 300 301
            return;
        }
        ret = recorder_->Prepare();
        if (ret != SUCCESS) {
N
NEEN 已提交
302 303
            cout << "Prepare failed. ret=" << ret << endl;
            CloseRecorder();
W
wenjun 已提交
304 305 306 307 308
            return;
        }
        ret = recorder_->Start();
        if (ret != SUCCESS) {
            cout << "recorder start failed. ret=" << ret << endl;
N
NEEN 已提交
309
            CloseRecorder();
W
wenjun 已提交
310 311
            return;
        }
N
NEEN 已提交
312 313 314 315 316 317
        FrameConfig *fc = new FrameConfig(FRAME_CONFIG_RECORD);
        Surface *surface = (recorder_->GetSurface(0)).get();
        surface->SetWidthAndHeight(1920, 1080);
        surface->SetQueueSize(3);
        surface->SetSize(1024 * 1024);
        fc->AddSurface(*surface);
W
wenjun 已提交
318 319 320
        ret = cam_->TriggerLoopingCapture(*fc);
        if (ret != 0) {
            delete fc;
N
NEEN 已提交
321
            CloseRecorder();
W
wenjun 已提交
322 323 324
            cout << "camera start recording failed. ret=" << ret << endl;
            return;
        }
N
NEEN 已提交
325
        recordState_ = STATE_RUNNING;
W
wenjun 已提交
326 327
        cout << "camera start recording succeed." << endl;
    }
N
NEEN 已提交
328

W
wenjun 已提交
329 330
    void StartPreview()
    {
N
NEEN 已提交
331 332 333 334 335
        if (cam_ == nullptr) {
            cout << "Camera is not ready." << endl;
            return;
        }
        if (previewState_ == STATE_RUNNING) {
W
wenjun 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
            cout << "Camera is already previewing." << endl;
            return;
        }
        FrameConfig *fc = new FrameConfig(FRAME_CONFIG_PREVIEW);
        Surface *surface = Surface::CreateSurface();
        if (surface == nullptr) {
            delete fc;
            cout << "CreateSurface failed" << endl;
            return;
        }
        surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */
        surface->SetUserData("region_position_x", "0");
        surface->SetUserData("region_position_y", "0");
        surface->SetUserData("region_width", "480");
        surface->SetUserData("region_height", "480");
        fc->AddSurface(*surface);
        int32_t ret = cam_->TriggerLoopingCapture(*fc);
        if (ret != 0) {
            delete fc;
            cout << "camera start preview failed. ret=" << ret << endl;
            return;
        }
        delete surface;
N
NEEN 已提交
359
        previewState_ = STATE_RUNNING;
W
wenjun 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
        cout << "camera start preview succeed." << endl;
    }
    void Capture()
    {
        if (cam_ == nullptr) {
            cout << "Camera is not ready." << endl;
            return;
        }
        FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE);
        Surface *surface = Surface::CreateSurface();
        if (surface == nullptr) {
            delete fc;
            cout << "CreateSurface failed" << endl;
            return;
        }
        surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */
        fc->AddSurface(*surface);
        cam_->TriggerSingleCapture(*fc);
    }
    void Stop()
    {
        if (cam_ == nullptr) {
            cout << "Camera is not ready." << endl;
            return;
        }
        cam_->StopLoopingCapture();
N
NEEN 已提交
386 387 388 389 390
        if (recordState_ == STATE_RUNNING) {
            CloseRecorder();
        }
        recordState_ = STATE_IDLE;
        previewState_ = STATE_IDLE;
W
wenjun 已提交
391 392 393
    }

private:
N
NEEN 已提交
394 395 396
    enum State : int32_t { STATE_IDLE, STATE_RUNNING, STATE_BUTT };
    State previewState_ = STATE_IDLE;
    State recordState_ = STATE_IDLE;
W
wenjun 已提交
397 398
    EventHandler &eventHdlr_;
    Camera *cam_ = nullptr;
N
NEEN 已提交
399
    int32_t recordFd_ = -1;
W
wenjun 已提交
400 401 402 403
    Recorder *recorder_ = nullptr;
    SampleFrameStateCallback fsCb_;
};

N
NEEN 已提交
404 405
class SampleCameraDeviceCallback : public CameraDeviceCallback {
};
W
wenjun 已提交
406 407 408 409 410 411

void SampleHelp()
{
    cout << "*******************************************" << endl;
    cout << "Select the behavior of avrecorder." << endl;
    cout << "1: Capture" << endl;
N
NEEN 已提交
412 413
    cout << "2: Record(Press s to stop)" << endl;
    cout << "3: Preview(Press s to stop)" << endl;
W
wenjun 已提交
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
    cout << "q: quit the sample." << endl;
    cout << "*******************************************" << endl;
}

int main()
{
    cout << "Camera sample begin." << endl;
    SampleHelp();
    CameraKit *camKit = CameraKit::GetInstance();
    if (camKit == nullptr) {
        cout << "Can not get CameraKit instance" << endl;
        return 0;
    }
    list<string> camList = camKit->GetCameraIds();
    string camId;
    for (auto &cam : camList) {
        cout << "camera name:" << cam << endl;
        const CameraAbility *ability = camKit->GetCameraAbility(cam);
        /* find camera which fits user's ability */
        list<CameraPicSize> sizeList = ability->GetSupportedSizes(0);
N
NEEN 已提交
434 435 436 437 438
        for (auto &pic : sizeList) {
            if (pic.width == 1920 && pic.height == 1080) {
                camId = cam;
                break;
            }
W
wenjun 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
        }
    }

    if (camId.empty()) {
        cout << "No available camera.(1080p wanted)" << endl;
        return 0;
    }

    EventHandler eventHdlr; // Create a thread to handle callback events
    SampleCameraStateMng CamStateMng(eventHdlr);

    camKit->CreateCamera(camId, CamStateMng, eventHdlr);

    char input;
    while (cin >> input) {
        switch (input) {
            case '1':
                CamStateMng.Capture();
                break;
            case '2':
                CamStateMng.StartRecord();
                break;
            case '3':
                CamStateMng.StartPreview();
                break;
            case 's':
                CamStateMng.Stop();
                break;
            case 'q':
                CamStateMng.Stop();
                goto EXIT;
            default:
                SampleHelp();
                break;
        }
    }
EXIT:
    cout << "Camera sample end." << endl;
    return 0;
}
```

## 涉及仓<a name="section7666411192217"></a>

N
NEEN 已提交
483
/hmf/multimedia/camera\_lite
W
wenjun 已提交
484

N
NEEN 已提交
485
/hmf/multimedia/audio\_lite
W
wenjun 已提交
486

N
NEEN 已提交
487
/hmf/multimedia/media\_lite
H
harmony_zhangjian 已提交
488

N
NEEN 已提交
489
/hmf/multimedia/utils\_lite
H
harmony_zhangjian 已提交
490