• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hcodec.h"
17 #include "hdf_base.h"
18 #include "hitrace_meter.h"
19 #include "hcodec_list.h"
20 #include "hcodec_log.h"
21 #include "hcodec_utils.h"
22 
23 namespace OHOS::MediaAVCodec {
24 using namespace std;
25 using namespace CodecHDI;
26 
27 /**************************** BaseState Start ****************************/
OnMsgReceived(const MsgInfo & info)28 void HCodec::BaseState::OnMsgReceived(const MsgInfo &info)
29 {
30     switch (info.type) {
31         case MsgWhat::GET_HIDUMPER_INFO: {
32             ParamSP reply = make_shared<ParamBundle>();
33             reply->SetValue("hidumper-info", codec_->OnGetHidumperInfo());
34             reply->SetValue<int32_t>("err", AVCS_ERR_OK);
35             codec_->PostReply(info.id, reply);
36             return;
37         }
38         case MsgWhat::CODEC_EVENT: {
39             OnCodecEvent(info);
40             return;
41         }
42         case MsgWhat::OMX_EMPTY_BUFFER_DONE: {
43             uint32_t bufferId = 0;
44             (void)info.param->GetValue(BUFFER_ID, bufferId);
45             codec_->OnOMXEmptyBufferDone(bufferId, inputMode_);
46             return;
47         }
48         case MsgWhat::OMX_FILL_BUFFER_DONE: {
49             OmxCodecBuffer omxBuffer;
50             (void)info.param->GetValue("omxBuffer", omxBuffer);
51             codec_->OnOMXFillBufferDone(omxBuffer, outputMode_);
52             return;
53         }
54         case MsgWhat::GET_INPUT_FORMAT:
55         case MsgWhat::GET_OUTPUT_FORMAT: {
56             OnGetFormat(info);
57             return;
58         }
59         case MsgWhat::STOP:
60         case MsgWhat::RELEASE: {
61             OnShutDown(info);
62             return;
63         }
64         default: {
65             const char* msgWhat = HCodec::ToString(static_cast<MsgWhat>(info.type));
66             if (info.id == ASYNC_MSG_ID) {
67                 SLOGI("ignore msg %s in current state", msgWhat);
68             } else { // Make sure that all sync message are replied
69                 SLOGE("%s cannot be called at this state", msgWhat);
70                 ReplyErrorCode(info.id, AVCS_ERR_INVALID_STATE);
71             }
72             return;
73         }
74     }
75 }
76 
ReplyErrorCode(MsgId id,int32_t err)77 void HCodec::BaseState::ReplyErrorCode(MsgId id, int32_t err)
78 {
79     if (id == ASYNC_MSG_ID) {
80         return;
81     }
82     ParamSP reply = make_shared<ParamBundle>();
83     reply->SetValue("err", err);
84     codec_->PostReply(id, reply);
85 }
86 
OnCodecEvent(const MsgInfo & info)87 void HCodec::BaseState::OnCodecEvent(const MsgInfo &info)
88 {
89     CodecEventType event{};
90     uint32_t data1 = 0;
91     uint32_t data2 = 0;
92     (void)info.param->GetValue("event", event);
93     (void)info.param->GetValue("data1", data1);
94     (void)info.param->GetValue("data2", data2);
95     if (event == CODEC_EVENT_CMD_COMPLETE &&
96         data1 == static_cast<uint32_t>(CODEC_COMMAND_FLUSH) &&
97         data2 == static_cast<uint32_t>(OMX_ALL)) {
98         SLOGD("ignore flush all complete event");
99     } else {
100         OnCodecEvent(event, data1, data2);
101     }
102 }
103 
OnCodecEvent(CodecEventType event,uint32_t data1,uint32_t data2)104 void HCodec::BaseState::OnCodecEvent(CodecEventType event, uint32_t data1, uint32_t data2)
105 {
106     if (event == CODEC_EVENT_ERROR) {
107         SLOGE("omx report error event, data1 = %u, data2 = %u", data1, data2);
108         codec_->SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
109         if (data1 == static_cast<uint32_t>(OMX_ErrorUnsupportedSetting) ||
110             data1 == static_cast<uint32_t>(OMX_ErrorInsufficientResources)) {
111             SLOGE("unsupport or insufficient resources, need force shut down");
112             (void)codec_->ForceShutdown(codec_->stateGeneration_, false);
113         }
114     } else {
115         SLOGW("ignore event %d, data1 = %u, data2 = %u", event, data1, data2);
116     }
117 }
118 
OnGetFormat(const MsgInfo & info)119 void HCodec::BaseState::OnGetFormat(const MsgInfo &info)
120 {
121     shared_ptr<Format> fmt = (info.type == MsgWhat::GET_INPUT_FORMAT) ?
122         codec_->inputFormat_ : codec_->outputFormat_;
123     ParamSP reply = make_shared<ParamBundle>();
124     if (fmt) {
125         reply->SetValue<int32_t>("err", AVCS_ERR_OK);
126         reply->SetValue("format", *fmt);
127         codec_->PostReply(info.id, reply);
128     } else {
129         ReplyErrorCode(info.id, AVCS_ERR_UNKNOWN);
130     }
131 }
132 
OnSetParameters(const MsgInfo & info)133 void HCodec::BaseState::OnSetParameters(const MsgInfo &info)
134 {
135     Format params;
136     (void)info.param->GetValue("params", params);
137     ReplyErrorCode(info.id, codec_->OnSetParameters(params));
138 }
139 
OnCheckIfStuck(const MsgInfo & info)140 void HCodec::BaseState::OnCheckIfStuck(const MsgInfo &info)
141 {
142     int32_t generation = 0;
143     (void)info.param->GetValue("generation", generation);
144     if (generation == codec_->stateGeneration_) {
145         SLOGE("stucked");
146         codec_->PrintAllBufferInfo();
147         codec_->SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
148     }
149 }
150 
OnForceShutDown(const MsgInfo & info)151 void HCodec::BaseState::OnForceShutDown(const MsgInfo &info)
152 {
153     int32_t generation = 0;
154     bool isNeedNotifyCaller;
155     (void)info.param->GetValue("generation", generation);
156     (void)info.param->GetValue("isNeedNotifyCaller", isNeedNotifyCaller);
157     codec_->ForceShutdown(generation, isNeedNotifyCaller);
158 }
159 
OnSuspend(const MsgInfo & info)160 void HCodec::BaseState::OnSuspend(const MsgInfo &info)
161 {
162     SLOGI("begin to Suspend this codec");
163     int32_t errCode = codec_->DecreaseFreq();
164     if (errCode != AVCS_ERR_OK) {
165         SLOGE("Decrease Freq fail!");
166     }
167     ReplyErrorCode(info.id, errCode);
168 }
169 
OnResume(const MsgInfo & info)170 void HCodec::BaseState::OnResume(const MsgInfo &info)
171 {
172     SLOGI("begin to Resume this codec");
173     int32_t errCode = codec_->RecoverFreq();
174     if (errCode != AVCS_ERR_OK) {
175         SLOGE("Recover Freq Fail!");
176     }
177     ReplyErrorCode(info.id, errCode);
178 }
179 /**************************** BaseState End ******************************/
180 
181 
182 /**************************** UninitializedState start ****************************/
OnStateEntered()183 void HCodec::UninitializedState::OnStateEntered()
184 {
185     codec_->gotFirstInput_ = false;
186     codec_->gotFirstOutput_ = false;
187     codec_->onePtsInToOutTotalCostUs_ = 0;
188     codec_->inTimeMap_.clear();
189     codec_->record_[OMX_DirInput].ResetAll();
190     codec_->record_[OMX_DirOutput].ResetAll();
191     codec_->circulateHasStopped_ = false;
192     codec_->OnEnterUninitializedState();
193     codec_->ReleaseComponent();
194 }
195 
OnMsgReceived(const MsgInfo & info)196 void HCodec::UninitializedState::OnMsgReceived(const MsgInfo &info)
197 {
198     switch (info.type) {
199         case MsgWhat::INIT: {
200             int32_t err = codec_->OnAllocateComponent();
201             ReplyErrorCode(info.id, err);
202             if (err == AVCS_ERR_OK) {
203                 codec_->ChangeStateTo(codec_->initializedState_);
204             }
205             break;
206         }
207         default: {
208             BaseState::OnMsgReceived(info);
209         }
210     }
211 }
212 
OnShutDown(const MsgInfo & info)213 void HCodec::UninitializedState::OnShutDown(const MsgInfo &info)
214 {
215     ReplyErrorCode(info.id, AVCS_ERR_OK);
216 }
217 
218 /**************************** UninitializedState End ******************************/
219 
220 /**************************** InitializedState Start **********************************/
OnStateEntered()221 void HCodec::InitializedState::OnStateEntered()
222 {
223     codec_->inputPortEos_ = false;
224     codec_->outputPortEos_ = false;
225     codec_->outPortHasChanged_ = false;
226     codec_->inputFormat_.reset();
227     codec_->outputFormat_.reset();
228 
229     ProcessShutDownFromRunning();
230     codec_->notifyCallerAfterShutdownComplete_ = false;
231     codec_->ProcessDeferredMessages();
232 }
233 
ProcessShutDownFromRunning()234 void HCodec::InitializedState::ProcessShutDownFromRunning()
235 {
236     if (!codec_->isShutDownFromRunning_) {
237         return;
238     }
239     SLOGI(">>");
240     bool keepComponentAllocated = codec_->keepComponentAllocated_;
241     if (keepComponentAllocated) {
242         if (codec_->configFormat_ == nullptr) {
243             SLOGW("stored configuration is null");
244         } else {
245             Format copyOfCurConfig(*codec_->configFormat_);
246             codec_->OnConfigure(copyOfCurConfig);
247         }
248     } else {
249         codec_->ChangeStateTo(codec_->uninitializedState_);
250     }
251     if (codec_->notifyCallerAfterShutdownComplete_) {
252         SLOGI("reply to %s msg", keepComponentAllocated ? "stop" : "release");
253         MsgInfo msg { keepComponentAllocated ? MsgWhat::STOP : MsgWhat::RELEASE, 0, nullptr };
254         if (codec_->GetFirstSyncMsgToReply(msg)) {
255             ReplyErrorCode(msg.id, AVCS_ERR_OK);
256         }
257         codec_->notifyCallerAfterShutdownComplete_ = false;
258     }
259     codec_->isShutDownFromRunning_ = false;
260     codec_->keepComponentAllocated_ = false;
261 }
262 
OnMsgReceived(const MsgInfo & info)263 void HCodec::InitializedState::OnMsgReceived(const MsgInfo &info)
264 {
265     switch (info.type) {
266         case MsgWhat::SET_CALLBACK: {
267             OnSetCallBack(info);
268             return;
269         }
270         case MsgWhat::CONFIGURE: {
271             OnConfigure(info);
272             return;
273         }
274         case MsgWhat::CONFIGURE_BUFFER: {
275             std::shared_ptr<AVBuffer> buffer;
276             (void)info.param->GetValue("buffer", buffer);
277             ReplyErrorCode(info.id, codec_->OnConfigureBuffer(buffer));
278             return;
279         }
280         case MsgWhat::CREATE_INPUT_SURFACE: {
281             sptr<Surface> surface = codec_->OnCreateInputSurface();
282             ParamSP reply = make_shared<ParamBundle>();
283             reply->SetValue<int32_t>("err", surface != nullptr ? AVCS_ERR_OK : AVCS_ERR_UNKNOWN);
284             reply->SetValue("surface", surface);
285             codec_->PostReply(info.id, reply);
286             return;
287         }
288         case MsgWhat::SET_INPUT_SURFACE: {
289             sptr<Surface> surface;
290             (void)info.param->GetValue("surface", surface);
291             ReplyErrorCode(info.id, codec_->OnSetInputSurface(surface));
292             return;
293         }
294         case MsgWhat::SET_OUTPUT_SURFACE: {
295             codec_->OnSetOutputSurface(info, outputMode_);
296             return;
297         }
298         case MsgWhat::START: {
299             OnStart(info);
300             return;
301         }
302         default: {
303             BaseState::OnMsgReceived(info);
304         }
305     }
306 }
307 
OnSetCallBack(const MsgInfo & info)308 void HCodec::InitializedState::OnSetCallBack(const MsgInfo &info)
309 {
310     int32_t err;
311     shared_ptr<MediaCodecCallback> cb;
312     (void)info.param->GetValue("callback", cb);
313     if (cb == nullptr) {
314         err = AVCS_ERR_INVALID_VAL;
315         SLOGE("invalid param");
316     } else {
317         codec_->callback_ = cb;
318         err = AVCS_ERR_OK;
319     }
320     ReplyErrorCode(info.id, err);
321 }
322 
OnConfigure(const MsgInfo & info)323 void HCodec::InitializedState::OnConfigure(const MsgInfo &info)
324 {
325     Format fmt;
326     (void)info.param->GetValue("format", fmt);
327     ReplyErrorCode(info.id, codec_->OnConfigure(fmt));
328 }
329 
OnStart(const MsgInfo & info)330 void HCodec::InitializedState::OnStart(const MsgInfo &info)
331 {
332     if (!codec_->ReadyToStart()) {
333         SLOGE("callback not set or format is not configured, can't start");
334         ReplyErrorCode(info.id, AVCS_ERR_INVALID_OPERATION);
335         return;
336     }
337     SLOGI("set omx to idle");
338     int32_t ret = codec_->compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
339     if (ret == HDF_SUCCESS) {
340         codec_->ReplyToSyncMsgLater(info);
341         codec_->ChangeStateTo(codec_->startingState_);
342     } else {
343         SLOGE("set omx to idle failed, ret=%d", ret);
344         ReplyErrorCode(info.id, AVCS_ERR_UNKNOWN);
345     }
346 }
347 
OnShutDown(const MsgInfo & info)348 void HCodec::InitializedState::OnShutDown(const MsgInfo &info)
349 {
350     if (info.type == MsgWhat::STOP) {
351         SLOGI("receive STOP");
352     } else {
353         SLOGI("receive RELEASE");
354         codec_->ChangeStateTo(codec_->uninitializedState_);
355     }
356     codec_->notifyCallerAfterShutdownComplete_ = false;
357     ReplyErrorCode(info.id, AVCS_ERR_OK);
358 }
359 /**************************** InitializedState End ******************************/
360 
361 
362 /**************************** StartingState Start ******************************/
OnStateEntered()363 void HCodec::StartingState::OnStateEntered()
364 {
365     hasError_ = false;
366 
367     ParamSP msg = make_shared<ParamBundle>();
368     msg->SetValue("generation", codec_->stateGeneration_);
369 
370     int32_t ret = AllocateBuffers();
371     if (ret != AVCS_ERR_OK) {
372         SLOGE("AllocateBuffers failed, back to init state");
373         hasError_ = true;
374         ReplyStartMsg(ret);
375         codec_->ChangeStateTo(codec_->initializedState_);
376     } else {
377         codec_->SendAsyncMsg(MsgWhat::CHECK_IF_STUCK, msg, THREE_SECONDS_IN_US);
378     }
379 }
380 
AllocateBuffers()381 int32_t HCodec::StartingState::AllocateBuffers()
382 {
383     int32_t ret = codec_->AllocateBuffersOnPort(OMX_DirInput);
384     if (ret != AVCS_ERR_OK) {
385         return ret;
386     }
387     ret = codec_->AllocateBuffersOnPort(OMX_DirOutput);
388     if (ret != AVCS_ERR_OK) {
389         return ret;
390     }
391     codec_->UpdateOwner();
392     return AVCS_ERR_OK;
393 }
394 
OnMsgReceived(const MsgInfo & info)395 void HCodec::StartingState::OnMsgReceived(const MsgInfo &info)
396 {
397     switch (info.type) {
398         case MsgWhat::GET_BUFFER_FROM_SURFACE:
399         case MsgWhat::SET_PARAMETERS:
400         case MsgWhat::GET_INPUT_FORMAT:
401         case MsgWhat::GET_OUTPUT_FORMAT: {
402             codec_->DeferMessage(info);
403             return;
404         }
405         case MsgWhat::START:
406         case MsgWhat::FLUSH: {
407             ReplyErrorCode(info.id, AVCS_ERR_OK);
408             return;
409         }
410         case MsgWhat::CHECK_IF_STUCK: {
411             int32_t generation = 0;
412             if (info.param->GetValue("generation", generation) &&
413                 generation == codec_->stateGeneration_) {
414                 SLOGE("stucked, force state transition");
415                 hasError_ = true;
416                 ReplyStartMsg(AVCS_ERR_UNKNOWN);
417                 codec_->ChangeStateTo(codec_->initializedState_);
418             }
419             return;
420         }
421         default: {
422             BaseState::OnMsgReceived(info);
423         }
424     }
425 }
426 
OnCodecEvent(CodecEventType event,uint32_t data1,uint32_t data2)427 void HCodec::StartingState::OnCodecEvent(CodecEventType event, uint32_t data1, uint32_t data2)
428 {
429     if (event != CODEC_EVENT_CMD_COMPLETE) {
430         return BaseState::OnCodecEvent(event, data1, data2);
431     }
432     if (data1 != (uint32_t)CODEC_COMMAND_STATE_SET) {
433         SLOGW("ignore event: data1=%u, data2=%u", data1, data2);
434         return;
435     }
436     if (data2 == (uint32_t)CODEC_STATE_IDLE) {
437         SLOGI("now idle, set omx to executing");
438         int32_t ret = codec_->compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_EXECUTING, {});
439         if (ret != HDF_SUCCESS) {
440             SLOGE("set omx to executing failed, ret=%d", ret);
441             hasError_ = true;
442             ReplyStartMsg(AVCS_ERR_UNKNOWN);
443             codec_->ChangeStateTo(codec_->initializedState_);
444         }
445     } else if (data2 == (uint32_t)CODEC_STATE_EXECUTING) {
446         SLOGI("omx now executing");
447         ReplyStartMsg(AVCS_ERR_OK);
448         codec_->SubmitAllBuffersOwnedByUs();
449         codec_->ChangeStateTo(codec_->runningState_);
450     }
451 }
452 
OnShutDown(const MsgInfo & info)453 void HCodec::StartingState::OnShutDown(const MsgInfo &info)
454 {
455     codec_->DeferMessage(info);
456 }
457 
ReplyStartMsg(int32_t errCode)458 void HCodec::StartingState::ReplyStartMsg(int32_t errCode)
459 {
460     MsgInfo msg {MsgWhat::START, 0, nullptr};
461     if (codec_->GetFirstSyncMsgToReply(msg)) {
462         SLOGI("start %s", (errCode == 0) ? "succ" : "failed");
463         ReplyErrorCode(msg.id, errCode);
464     } else {
465         SLOGE("there should be a start msg to reply");
466     }
467 }
468 
OnStateExited()469 void HCodec::StartingState::OnStateExited()
470 {
471     if (hasError_) {
472         SLOGW("error occured, roll omx back to loaded and free allocated buffers");
473         if (codec_->RollOmxBackToLoaded()) {
474             codec_->ClearBufferPool(OMX_DirInput);
475             codec_->ClearBufferPool(OMX_DirOutput);
476         }
477     }
478     codec_->lastOwnerChangeTime_ = chrono::steady_clock::now();
479     ParamSP param = make_shared<ParamBundle>();
480     param->SetValue(KEY_LAST_OWNER_CHANGE_TIME, codec_->lastOwnerChangeTime_);
481     codec_->SendAsyncMsg(MsgWhat::PRINT_ALL_BUFFER_OWNER, param, THREE_SECONDS_IN_US);
482     BaseState::OnStateExited();
483 }
484 
485 /**************************** StartingState End ******************************/
486 
487 /**************************** RunningState Start ********************************/
OnStateEntered()488 void HCodec::RunningState::OnStateEntered()
489 {
490     codec_->ProcessDeferredMessages();
491 }
492 
OnMsgReceived(const MsgInfo & info)493 void HCodec::RunningState::OnMsgReceived(const MsgInfo &info)
494 {
495     switch (info.type) {
496         case MsgWhat::START:
497             ReplyErrorCode(info.id, codec_->SubmitAllBuffersOwnedByUs());
498             break;
499         case MsgWhat::SET_PARAMETERS:
500             OnSetParameters(info);
501             break;
502         case MsgWhat::REQUEST_IDR_FRAME:
503             ReplyErrorCode(info.id, codec_->RequestIDRFrame());
504             break;
505         case MsgWhat::FLUSH:
506             SetThreadInteractiveQos(true);
507             OnFlush(info);
508             break;
509         case MsgWhat::GET_BUFFER_FROM_SURFACE:
510             codec_->OnGetBufferFromSurface(info.param);
511             break;
512         case MsgWhat::CHECK_IF_REPEAT:
513             codec_->RepeatIfNecessary(info.param);
514             break;
515         case MsgWhat::QUEUE_INPUT_BUFFER:
516             if (codec_->outPortHasChanged_) {
517                 codec_->DynamicModeSubmitBuffer();
518             }
519             codec_->OnQueueInputBuffer(info, inputMode_);
520             break;
521         case MsgWhat::SUBMIT_DYNAMIC_IF_EOS:
522             if (codec_->inputPortEos_ && !codec_->outputPortEos_) {
523                 codec_->DynamicModeSubmitBuffer();
524                 codec_->DynamicModeSubmitIfEos();
525             }
526             break;
527         case MsgWhat::NOTIFY_EOS:
528             codec_->OnSignalEndOfInputStream(info);
529             break;
530         case MsgWhat::RENDER_OUTPUT_BUFFER:
531             codec_->OnRenderOutputBuffer(info, outputMode_);
532             break;
533         case MsgWhat::RELEASE_OUTPUT_BUFFER:
534             codec_->OnReleaseOutputBuffer(info, outputMode_);
535             break;
536         case MsgWhat::SET_OUTPUT_SURFACE:
537             codec_->OnSetOutputSurface(info, outputMode_);
538             return;
539         case MsgWhat::PRINT_ALL_BUFFER_OWNER:
540             codec_->OnPrintAllBufferOwner(info);
541             return;
542         case MsgWhat::CHECK_IF_STUCK:
543             return;
544         case MsgWhat::BUFFER_RECYCLE: {
545             OnBufferRecycle(info);
546             break;
547         }
548         case MsgWhat::SUSPEND:{
549             OnSuspend(info);
550             break;
551         }
552         case MsgWhat::RESUME:{
553             OnResume(info);
554             return;
555         }
556         default:
557             BaseState::OnMsgReceived(info);
558             break;
559     }
560 }
561 
OnCodecEvent(CodecEventType event,uint32_t data1,uint32_t data2)562 void HCodec::RunningState::OnCodecEvent(CodecEventType event, uint32_t data1, uint32_t data2)
563 {
564     switch (event) {
565         case CODEC_EVENT_PORT_SETTINGS_CHANGED: {
566             if (data1 != OMX_DirOutput) {
567                 SLOGI("ignore input port changed");
568                 return;
569             }
570             if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
571                 SLOGI("output port settings changed, disable out port");
572                 codec_->UpdateOutPortFormat();
573                 int32_t ret = codec_->compNode_->SendCommand(
574                     CODEC_COMMAND_PORT_DISABLE, OMX_DirOutput, {});
575                 if (ret == HDF_SUCCESS) {
576                     codec_->EraseOutBuffersOwnedByUsOrSurface();
577                     codec_->ChangeStateTo(codec_->outputPortChangedState_);
578                 } else {
579                     SLOGE("ask omx to disable out port failed");
580                     codec_->SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
581                 }
582             } else if (data2 == OMX_IndexColorAspects) {
583                 codec_->UpdateColorAspects();
584             } else {
585                 SLOGI("unknown data2 0x%x for CODEC_EVENT_PORT_SETTINGS_CHANGED", data2);
586             }
587             return;
588         }
589         default: {
590             BaseState::OnCodecEvent(event, data1, data2);
591         }
592     }
593 }
594 
OnShutDown(const MsgInfo & info)595 void HCodec::RunningState::OnShutDown(const MsgInfo &info)
596 {
597     SetThreadInteractiveQos(true);
598     codec_->isShutDownFromRunning_ = true;
599     codec_->notifyCallerAfterShutdownComplete_ = true;
600     codec_->keepComponentAllocated_ = (info.type == MsgWhat::STOP);
601     codec_->isBufferCirculating_ = false;
602     codec_->PrintAllBufferInfo();
603     SLOGI("receive %s msg, set omx to idle", info.type == MsgWhat::RELEASE ? "release" : "stop");
604     int32_t ret = codec_->compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {});
605     if (ret == HDF_SUCCESS) {
606         codec_->ReplyToSyncMsgLater(info);
607         codec_->ChangeStateTo(codec_->stoppingState_);
608     } else {
609         SLOGE("set omx to idle failed, ret=%d", ret);
610         ReplyErrorCode(info.id, AVCS_ERR_UNKNOWN);
611     }
612 }
613 
OnFlush(const MsgInfo & info)614 void HCodec::RunningState::OnFlush(const MsgInfo &info)
615 {
616     codec_->isBufferCirculating_ = false;
617     SLOGD("begin to ask omx to flush");
618     int32_t ret = codec_->compNode_->SendCommand(CODEC_COMMAND_FLUSH, OMX_ALL, {});
619     if (ret == HDF_SUCCESS) {
620         codec_->ReplyToSyncMsgLater(info);
621         codec_->ChangeStateTo(codec_->flushingState_);
622     } else {
623         SLOGI("ask omx to flush failed, ret=%d", ret);
624         ReplyErrorCode(info.id, AVCS_ERR_UNKNOWN);
625     }
626 }
627 /**************************** RunningState End ********************************/
628 
629 
630 /**************************** OutputPortChangedState Start ********************************/
OnStateEntered()631 void HCodec::OutputPortChangedState::OnStateEntered()
632 {
633     ParamSP msg = make_shared<ParamBundle>();
634     msg->SetValue("generation", codec_->stateGeneration_);
635     codec_->SendAsyncMsg(MsgWhat::CHECK_IF_STUCK, msg, THREE_SECONDS_IN_US);
636 }
637 
638 // LCOV_EXCL_START
OnMsgReceived(const MsgInfo & info)639 void HCodec::OutputPortChangedState::OnMsgReceived(const MsgInfo &info)
640 {
641     switch (info.type) {
642         case MsgWhat::FLUSH:
643             OnFlush(info);
644             return;
645         case MsgWhat::START:
646             codec_->DeferMessage(info);
647             return;
648         case MsgWhat::SET_PARAMETERS:
649             OnSetParameters(info);
650             return;
651         case MsgWhat::QUEUE_INPUT_BUFFER: {
652             codec_->OnQueueInputBuffer(info, inputMode_);
653             return;
654         }
655         case MsgWhat::NOTIFY_EOS: {
656             codec_->OnSignalEndOfInputStream(info);
657             return;
658         }
659         case MsgWhat::RENDER_OUTPUT_BUFFER: {
660             codec_->OnRenderOutputBuffer(info, outputMode_);
661             return;
662         }
663         case MsgWhat::RELEASE_OUTPUT_BUFFER: {
664             codec_->OnReleaseOutputBuffer(info, outputMode_);
665             return;
666         }
667         case MsgWhat::FORCE_SHUTDOWN: {
668             OnForceShutDown(info);
669             return;
670         }
671         case MsgWhat::CHECK_IF_STUCK: {
672             OnCheckIfStuck(info);
673             return;
674         }
675         case MsgWhat::SET_OUTPUT_SURFACE: {
676             codec_->OnSetOutputSurface(info, outputMode_);
677             return;
678         }
679         case MsgWhat::PRINT_ALL_BUFFER_OWNER: {
680             codec_->OnPrintAllBufferOwner(info);
681             return;
682         }
683         case MsgWhat::GET_BUFFER_FROM_SURFACE:
684             return;
685         default: {
686             BaseState::OnMsgReceived(info);
687         }
688     }
689 }
690 // LCOV_EXCL_STOP
691 
OnShutDown(const MsgInfo & info)692 void HCodec::OutputPortChangedState::OnShutDown(const MsgInfo &info)
693 {
694     if (codec_->hasFatalError_) {
695         ParamSP stopMsg = make_shared<ParamBundle>();
696         stopMsg->SetValue("generation", codec_->stateGeneration_);
697         stopMsg->SetValue("isNeedNotifyCaller", true);
698         codec_->SendAsyncMsg(MsgWhat::FORCE_SHUTDOWN, stopMsg, THREE_SECONDS_IN_US);
699     }
700     codec_->ReclaimBuffer(OMX_DirOutput, BufferOwner::OWNED_BY_USER, true);
701     codec_->DeferMessage(info);
702 }
703 
OnCheckIfStuck(const MsgInfo & info)704 void HCodec::OutputPortChangedState::OnCheckIfStuck(const MsgInfo &info)
705 {
706     int32_t generation = 0;
707     (void)info.param->GetValue("generation", generation);
708     if (generation != codec_->stateGeneration_) {
709         return;
710     }
711 
712     if (std::none_of(codec_->outputBufferPool_.begin(), codec_->outputBufferPool_.end(), [](const BufferInfo& info) {
713             return info.owner == BufferOwner::OWNED_BY_OMX;
714         })) {
715         SLOGI("output buffers owned by omx has been returned");
716         return;
717     }
718     codec_->PrintAllBufferInfo();
719     codec_->SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
720     SLOGE("stucked, need force shut down");
721     (void)codec_->ForceShutdown(codec_->stateGeneration_, false);
722 }
723 
OnCodecEvent(CodecEventType event,uint32_t data1,uint32_t data2)724 void HCodec::OutputPortChangedState::OnCodecEvent(CodecEventType event, uint32_t data1, uint32_t data2)
725 {
726     switch (event) {
727         case CODEC_EVENT_CMD_COMPLETE: {
728             if (data1 == CODEC_COMMAND_PORT_DISABLE) {
729                 if (data2 != OMX_DirOutput) {
730                     SLOGW("ignore input port disable complete");
731                     return;
732                 }
733                 SLOGI("output port is disabled");
734                 HandleOutputPortDisabled();
735             } else if (data1 == CODEC_COMMAND_PORT_ENABLE) {
736                 if (data2 != OMX_DirOutput) {
737                     SLOGW("ignore input port enable complete");
738                     return;
739                 }
740                 SLOGI("output port is enabled");
741                 HandleOutputPortEnabled();
742             }
743             return;
744         }
745         case CODEC_EVENT_PORT_SETTINGS_CHANGED: {
746             if (data2 == OMX_IndexColorAspects) {
747                 codec_->UpdateColorAspects();
748             }
749             break;
750         }
751         default: {
752             BaseState::OnCodecEvent(event, data1, data2);
753         }
754     }
755 }
756 
HandleOutputPortDisabled()757 void HCodec::OutputPortChangedState::HandleOutputPortDisabled()
758 {
759     int32_t ret = AVCS_ERR_OK;
760     if (!codec_->outputBufferPool_.empty()) {
761         SLOGE("output port is disabled but not empty: %zu", codec_->outputBufferPool_.size());
762         ret = AVCS_ERR_UNKNOWN;
763     }
764 
765     if (ret == AVCS_ERR_OK) {
766         SLOGI("enable out port");
767         if (codec_->isLpp_) {
768             codec_->callback_->OnOutputBufferUnbinded();
769         }
770         int32_t err = codec_->compNode_->SendCommand(CODEC_COMMAND_PORT_ENABLE, OMX_DirOutput, {});
771         if (err == HDF_SUCCESS) {
772             ret = codec_->AllocateBuffersOnPort(OMX_DirOutput);
773             codec_->UpdateOwner(OMX_DirOutput);
774         } else {
775             SLOGE("ask omx to enable out port failed, ret=%d", ret);
776             ret = AVCS_ERR_UNKNOWN;
777         }
778     }
779     if (ret != AVCS_ERR_OK) {
780         codec_->SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
781         (void)codec_->ForceShutdown(codec_->stateGeneration_, false);
782     }
783 }
784 
HandleOutputPortEnabled()785 void HCodec::OutputPortChangedState::HandleOutputPortEnabled()
786 {
787     if (codec_->isBufferCirculating_) {
788         codec_->SubmitOutBufToOmx();
789     }
790     codec_->outPortHasChanged_ = true;
791     SLOGI("output format changed: %s", codec_->outputFormat_->Stringify().c_str());
792     codec_->callback_->OnOutputFormatChanged(*(codec_->outputFormat_.get()));
793     codec_->ChangeStateTo(codec_->runningState_);
794 }
795 
OnFlush(const MsgInfo & info)796 void HCodec::OutputPortChangedState::OnFlush(const MsgInfo &info)
797 {
798     if (codec_->hasFatalError_) {
799         ParamSP stopMsg = make_shared<ParamBundle>();
800         stopMsg->SetValue("generation", codec_->stateGeneration_);
801         stopMsg->SetValue("isNeedNotifyCaller", false);
802         codec_->SendAsyncMsg(MsgWhat::FORCE_SHUTDOWN, stopMsg, THREE_SECONDS_IN_US);
803     }
804     codec_->ReclaimBuffer(OMX_DirOutput, BufferOwner::OWNED_BY_USER, true);
805     codec_->DeferMessage(info);
806 }
807 /**************************** OutputPortChangedState End ********************************/
808 
809 
810 /**************************** FlushingState Start ********************************/
OnStateEntered()811 void HCodec::FlushingState::OnStateEntered()
812 {
813     flushCompleteFlag_[OMX_DirInput] = false;
814     flushCompleteFlag_[OMX_DirOutput] = false;
815     codec_->ReclaimBuffer(OMX_DirInput, BufferOwner::OWNED_BY_USER);
816     codec_->ReclaimBuffer(OMX_DirOutput, BufferOwner::OWNED_BY_USER);
817     SLOGD("all buffer owned by user are now owned by us");
818 
819     ParamSP msg = make_shared<ParamBundle>();
820     msg->SetValue("generation", codec_->stateGeneration_);
821     codec_->SendAsyncMsg(MsgWhat::CHECK_IF_STUCK, msg, THREE_SECONDS_IN_US);
822 }
823 
824 // LCOV_EXCL_START
OnMsgReceived(const MsgInfo & info)825 void HCodec::FlushingState::OnMsgReceived(const MsgInfo &info)
826 {
827     switch (info.type) {
828         case MsgWhat::GET_BUFFER_FROM_SURFACE: {
829             codec_->DeferMessage(info);
830             return;
831         }
832         case MsgWhat::FLUSH: {
833             ReplyErrorCode(info.id, AVCS_ERR_OK);
834             return;
835         }
836         case MsgWhat::FORCE_SHUTDOWN: {
837             OnForceShutDown(info);
838             return;
839         }
840         case MsgWhat::CHECK_IF_STUCK: {
841             OnCheckIfStuck(info);
842             return;
843         }
844         case MsgWhat::PRINT_ALL_BUFFER_OWNER: {
845             codec_->OnPrintAllBufferOwner(info);
846             return;
847         }
848         default: {
849             BaseState::OnMsgReceived(info);
850         }
851     }
852 }
853 // LCOV_EXCL_STOP
854 
OnCodecEvent(CodecEventType event,uint32_t data1,uint32_t data2)855 void HCodec::FlushingState::OnCodecEvent(CodecEventType event, uint32_t data1, uint32_t data2)
856 {
857     switch (event) {
858         case CODEC_EVENT_CMD_COMPLETE: {
859             auto ret = UpdateFlushStatusOnPorts(data1, data2);
860             if (ret == AVCS_ERR_OK && IsFlushCompleteOnAllPorts()) {
861                 ChangeStateIfWeOwnAllBuffers();
862             }
863             return;
864         }
865         case CODEC_EVENT_PORT_SETTINGS_CHANGED: {
866             ParamSP portSettingChangedMsg = make_shared<ParamBundle>();
867             portSettingChangedMsg->SetValue("generation", codec_->stateGeneration_);
868             portSettingChangedMsg->SetValue("event", event);
869             portSettingChangedMsg->SetValue("data1", data1);
870             portSettingChangedMsg->SetValue("data2", data2);
871             codec_->DeferMessage(MsgInfo {MsgWhat::CODEC_EVENT, 0, portSettingChangedMsg});
872             SLOGI("deferring CODEC_EVENT_PORT_SETTINGS_CHANGED");
873             return;
874         }
875         default: {
876             BaseState::OnCodecEvent(event, data1, data2);
877         }
878     }
879 }
880 
UpdateFlushStatusOnPorts(uint32_t data1,uint32_t data2)881 int32_t HCodec::FlushingState::UpdateFlushStatusOnPorts(uint32_t data1, uint32_t data2)
882 {
883     if (data2 == OMX_DirInput || data2 == OMX_DirOutput) {
884         if (flushCompleteFlag_[data2]) {
885             SLOGE("flush already completed for port (%u)", data2);
886             return AVCS_ERR_OK;
887         }
888         flushCompleteFlag_[data2] = true;
889     } else if (data2 == OMX_ALL) {
890         if (!IsFlushCompleteOnAllPorts()) {
891             SLOGW("received flush complete event for OMX_ALL, portFlushStatue=(%d/%d)",
892                 flushCompleteFlag_[OMX_DirInput], flushCompleteFlag_[OMX_DirOutput]);
893             return AVCS_ERR_INVALID_VAL;
894         }
895     } else {
896         SLOGW("unexpected data2(%d) for CODEC_COMMAND_FLUSH complete", data2);
897     }
898     return AVCS_ERR_OK;
899 }
900 
IsFlushCompleteOnAllPorts()901 bool HCodec::FlushingState::IsFlushCompleteOnAllPorts()
902 {
903     return flushCompleteFlag_[OMX_DirInput] && flushCompleteFlag_[OMX_DirOutput];
904 }
905 
ChangeStateIfWeOwnAllBuffers()906 void HCodec::FlushingState::ChangeStateIfWeOwnAllBuffers()
907 {
908     if (!IsFlushCompleteOnAllPorts()) {
909         return;
910     }
911     int32_t ret = AVCS_ERR_OK;
912     if (!codec_->IsAllBufferOwnedByUsOrSurface()) {
913         ParamSP stopMsg = make_shared<ParamBundle>();
914         stopMsg->SetValue("generation", codec_->stateGeneration_);
915         stopMsg->SetValue("isNeedNotifyCaller", false);
916         codec_->SendAsyncMsg(MsgWhat::FORCE_SHUTDOWN, stopMsg);
917         SLOGE("Try to change state but buffer state error");
918         ret = AVCS_ERR_UNKNOWN;
919     }
920     MsgInfo msg {MsgWhat::FLUSH, 0, nullptr};
921     if (codec_->GetFirstSyncMsgToReply(msg)) {
922         ReplyErrorCode(msg.id, ret);
923     }
924     if (ret == AVCS_ERR_OK) {
925         codec_->inputPortEos_ = false;
926         codec_->outputPortEos_ = false;
927         codec_->gotFirstInput_ = false;
928         codec_->gotFirstOutput_ = false;
929         codec_->ChangeStateTo(codec_->runningState_);
930     }
931 }
932 
OnShutDown(const MsgInfo & info)933 void HCodec::FlushingState::OnShutDown(const MsgInfo &info)
934 {
935     codec_->DeferMessage(info);
936     if (codec_->hasFatalError_) {
937         ParamSP stopMsg = make_shared<ParamBundle>();
938         stopMsg->SetValue("generation", codec_->stateGeneration_);
939         stopMsg->SetValue("isNeedNotifyCaller", true);
940         codec_->SendAsyncMsg(MsgWhat::FORCE_SHUTDOWN, stopMsg, THREE_SECONDS_IN_US);
941     }
942 }
943 /**************************** FlushingState End ********************************/
944 
945 
946 /**************************** StoppingState Start ********************************/
OnStateEntered()947 void HCodec::StoppingState::OnStateEntered()
948 {
949     omxNodeInIdleState_ = false;
950     omxNodeIsChangingToLoadedState_ = false;
951     codec_->ReclaimBuffer(OMX_DirInput, BufferOwner::OWNED_BY_USER);
952     codec_->ReclaimBuffer(OMX_DirOutput, BufferOwner::OWNED_BY_USER);
953     SLOGD("all buffer owned by user are now owned by us");
954 
955     ParamSP msg = make_shared<ParamBundle>();
956     msg->SetValue("generation", codec_->stateGeneration_);
957     codec_->SendAsyncMsg(MsgWhat::CHECK_IF_STUCK, msg, THREE_SECONDS_IN_US);
958 }
959 
OnMsgReceived(const MsgInfo & info)960 void HCodec::StoppingState::OnMsgReceived(const MsgInfo &info)
961 {
962     switch (info.type) {
963         case MsgWhat::CHECK_IF_STUCK: {
964             int32_t generation = 0;
965             (void)info.param->GetValue("generation", generation);
966             if (generation == codec_->stateGeneration_) {
967                 SLOGE("stucked, force state transition");
968                 codec_->ReclaimBuffer(OMX_DirInput, BufferOwner::OWNED_BY_OMX);
969                 codec_->ReclaimBuffer(OMX_DirOutput, BufferOwner::OWNED_BY_OMX);
970                 SLOGI("all buffer owned by omx are now owned by us");
971                 ChangeOmxNodeToLoadedState(true);
972                 codec_->ChangeStateTo(codec_->initializedState_);
973             }
974             return;
975         }
976         default: {
977             BaseState::OnMsgReceived(info);
978         }
979     }
980 }
981 
OnCodecEvent(CodecEventType event,uint32_t data1,uint32_t data2)982 void HCodec::StoppingState::OnCodecEvent(CodecEventType event, uint32_t data1, uint32_t data2)
983 {
984     switch (event) {
985         case CODEC_EVENT_CMD_COMPLETE: {
986             if (data1 != (uint32_t)CODEC_COMMAND_STATE_SET) {
987                 SLOGW("unexpected CODEC_EVENT_CMD_COMPLETE: %u %u", data1, data2);
988                 return;
989             }
990             if (data2 == (uint32_t)CODEC_STATE_IDLE) {
991                 SLOGI("omx now idle");
992                 omxNodeInIdleState_ = true;
993                 ChangeStateIfWeOwnAllBuffers();
994             } else if (data2 == (uint32_t)CODEC_STATE_LOADED) {
995                 SLOGI("omx now loaded");
996                 codec_->ChangeStateTo(codec_->initializedState_);
997             }
998             return;
999         }
1000         default: {
1001             BaseState::OnCodecEvent(event, data1, data2);
1002         }
1003     }
1004 }
1005 
ChangeStateIfWeOwnAllBuffers()1006 void HCodec::StoppingState::ChangeStateIfWeOwnAllBuffers()
1007 {
1008     if (omxNodeInIdleState_ && codec_->IsAllBufferOwnedByUsOrSurface()) {
1009         ChangeOmxNodeToLoadedState(false);
1010     } else {
1011         SLOGD("cannot change state yet");
1012     }
1013 }
1014 
ChangeOmxNodeToLoadedState(bool forceToFreeBuffer)1015 void HCodec::StoppingState::ChangeOmxNodeToLoadedState(bool forceToFreeBuffer)
1016 {
1017     if (!omxNodeIsChangingToLoadedState_) {
1018         SLOGI("set omx to loaded");
1019         int32_t ret = codec_->compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_LOADED, {});
1020         if (ret == HDF_SUCCESS) {
1021             omxNodeIsChangingToLoadedState_ = true;
1022         } else {
1023             SLOGE("set omx to loaded failed, ret=%d", ret);
1024         }
1025     }
1026     if (forceToFreeBuffer || omxNodeIsChangingToLoadedState_) {
1027         codec_->ClearBufferPool(OMX_DirInput);
1028         codec_->ClearBufferPool(OMX_DirOutput);
1029         return;
1030     }
1031     codec_->SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN);
1032 }
1033 
OnShutDown(const MsgInfo & info)1034 void HCodec::StoppingState::OnShutDown(const MsgInfo &info)
1035 {
1036     codec_->DeferMessage(info);
1037 }
1038 
1039 /**************************** StoppingState End ********************************/
1040 }