• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2024 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 #define HST_LOG_TAG "StreamDemuxer"
17 
18 #include "stream_demuxer.h"
19 
20 #include <algorithm>
21 #include <map>
22 #include <memory>
23 
24 #include "avcodec_common.h"
25 #include "avcodec_trace.h"
26 #include "cpp_ext/type_traits_ext.h"
27 #include "buffer/avallocator.h"
28 #include "common/event.h"
29 #include "common/log.h"
30 #include "meta/media_types.h"
31 #include "meta/meta.h"
32 #include "osal/utils/dump_buffer.h"
33 #include "plugin/plugin_buffer.h"
34 #include "plugin/plugin_info.h"
35 #include "plugin/plugin_time.h"
36 #include "source/source.h"
37 
38 namespace {
39 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "StreamDemuxer" };
40 }
41 
42 namespace OHOS {
43 namespace Media {
44 
45 const int32_t TRY_READ_SLEEP_TIME = 10;  //ms
46 const int32_t TRY_READ_TIMES = 10;
47 constexpr uint64_t LIVE_CONTENT_LENGTH = 2147483646;
StreamDemuxer()48 StreamDemuxer::StreamDemuxer() : position_(0)
49 {
50     MEDIA_LOG_I("VodStreamDemuxer called");
51 }
52 
~StreamDemuxer()53 StreamDemuxer::~StreamDemuxer()
54 {
55     MEDIA_LOG_I("~VodStreamDemuxer called");
56     ResetAllCache();
57 }
58 
ReadFrameData(int32_t streamID,uint64_t offset,size_t size,std::shared_ptr<Buffer> & bufferPtr)59 Status StreamDemuxer::ReadFrameData(int32_t streamID, uint64_t offset, size_t size,
60     std::shared_ptr<Buffer>& bufferPtr)
61 {
62     if (IsDash() || GetIsDataSrcNoSeek()) {
63         MEDIA_LOG_D("GetPeekRange read cache, offset: " PUBLIC_LOG_U64 " streamID: " PUBLIC_LOG_D32, offset, streamID);
64         if (cacheDataMap_.find(streamID) != cacheDataMap_.end() && cacheDataMap_[streamID].CheckCacheExist(offset)) {
65             MEDIA_LOG_D("GetPeekRange read cache, offset: " PUBLIC_LOG_U64, offset);
66             auto memory = cacheDataMap_[streamID].GetData()->GetMemory();
67             if (memory != nullptr && memory->GetSize() > 0) {
68                 MEDIA_LOG_D("GetPeekRange read cache, Read data from cache data. streamID: " PUBLIC_LOG_D32, streamID);
69                 return PullDataWithCache(streamID, offset, size, bufferPtr);
70             }
71         }
72     }
73     return PullData(streamID, offset, size, bufferPtr);
74 }
75 
ReadHeaderData(int32_t streamID,uint64_t offset,size_t size,std::shared_ptr<Buffer> & bufferPtr)76 Status StreamDemuxer::ReadHeaderData(int32_t streamID, uint64_t offset, size_t size,
77     std::shared_ptr<Buffer>& bufferPtr)
78 {
79     if (cacheDataMap_.find(streamID) != cacheDataMap_.end() && cacheDataMap_[streamID].CheckCacheExist(offset)) {
80         MEDIA_LOG_D("GetPeekRange read cache, offset: " PUBLIC_LOG_U64, offset);
81         auto memory = cacheDataMap_[streamID].GetData()->GetMemory();
82         if (memory != nullptr && memory->GetSize() > 0) {
83             MEDIA_LOG_D("GetPeekRange read cache, Read data from cache data.");
84             return PullDataWithCache(streamID, offset, size, bufferPtr);
85         }
86     }
87     return PullDataWithoutCache(streamID, offset, size, bufferPtr);
88 }
89 
GetPeekRange(int32_t streamID,uint64_t offset,size_t size,std::shared_ptr<Buffer> & bufferPtr)90 Status StreamDemuxer::GetPeekRange(int32_t streamID, uint64_t offset, size_t size, std::shared_ptr<Buffer>& bufferPtr)
91 {
92     FALSE_RETURN_V_MSG_E(!isInterruptNeeded_.load(), Status::ERROR_WRONG_STATE,
93         "GetPeekRange interrupt " PUBLIC_LOG_D32 " " PUBLIC_LOG_U64 " " PUBLIC_LOG_ZU, streamID, offset, size);
94     if (bufferPtr == nullptr) {
95         MEDIA_LOG_E("GetPeekRange bufferPtr invalid.");
96         return Status::ERROR_INVALID_PARAMETER;
97     }
98     bufferPtr->streamID = streamID;
99     Status ret = Status::OK;
100     if (pluginStateMap_[streamID] == DemuxerState::DEMUXER_STATE_PARSE_FRAME) {
101         ret = ReadFrameData(streamID, offset, size, bufferPtr);
102     } else {
103         ret = ReadHeaderData(streamID, offset, size, bufferPtr);
104     }
105     if (ret != Status::OK) {
106         return ret;
107     }
108     return CheckChangeStreamID(streamID, bufferPtr);
109 }
110 
Init(const std::string & uri)111 Status StreamDemuxer::Init(const std::string& uri)
112 {
113     MediaAVCodec::AVCodecTrace trace("StreamDemuxer::Init");
114     MEDIA_LOG_I("StreamDemuxer::Init called");
115     checkRange_ = [](int32_t streamID, uint64_t offset, uint32_t size) {
116         return Status::OK;
117     };
118     peekRange_ = [this](int32_t streamID, uint64_t offset, size_t size, std::shared_ptr<Buffer>& bufferPtr) -> Status {
119         return GetPeekRange(streamID, offset, size, bufferPtr);
120     };
121     getRange_ = peekRange_;
122     uri_ = uri;
123     return Status::OK;
124 }
125 
PullDataWithCache(int32_t streamID,uint64_t offset,size_t size,std::shared_ptr<Buffer> & bufferPtr)126 Status StreamDemuxer::PullDataWithCache(int32_t streamID, uint64_t offset, size_t size,
127     std::shared_ptr<Buffer>& bufferPtr)
128 {
129     FALSE_RETURN_V_MSG_E(bufferPtr->GetMemory() != nullptr, Status::ERROR_UNKNOWN, "bufferPtr invalid");
130     auto memory = cacheDataMap_[streamID].GetData()->GetMemory();
131     FALSE_RETURN_V_MSG_E(memory != nullptr, Status::ERROR_UNKNOWN, "memory invalid");
132     MEDIA_LOG_D("PullDataWithCache, Read data from cache data. streamID: " PUBLIC_LOG_D32, streamID);
133     uint64_t offsetInCache = offset - cacheDataMap_[streamID].GetOffset();
134     if (size <= memory->GetSize() - offsetInCache) {
135         MEDIA_LOG_D("Readfromcache. streamID: " PUBLIC_LOG_D32, streamID);
136         bufferPtr->GetMemory()->Write(memory->GetReadOnlyData() + offsetInCache, size, 0);
137         return Status::OK;
138     }
139     bufferPtr->GetMemory()->Write(memory->GetReadOnlyData() + offsetInCache, memory->GetSize() - offsetInCache, 0);
140     uint64_t remainOffset = cacheDataMap_[streamID].GetOffset() + memory->GetSize();
141     uint64_t remainSize = size - (memory->GetSize() - offsetInCache);
142     std::shared_ptr<Buffer> tempBuffer = Buffer::CreateDefaultBuffer(remainSize);
143     if (tempBuffer == nullptr || tempBuffer->GetMemory() == nullptr) {
144         MEDIA_LOG_W("PullDataWithCache, Read data from cache data. only get partial data.");
145         return Status::ERROR_UNKNOWN;
146     }
147     Status ret = PullData(streamID, remainOffset, remainSize, tempBuffer);
148     if (ret == Status::OK) {
149         FALSE_RETURN_V_MSG_E(tempBuffer->GetMemory() != nullptr, Status::ERROR_UNKNOWN, "tempBuffer invalid");
150         bufferPtr->GetMemory()->Write(tempBuffer->GetMemory()->GetReadOnlyData(),
151             tempBuffer->GetMemory()->GetSize(), memory->GetSize() - offsetInCache);
152         if (pluginStateMap_[streamID] == DemuxerState::DEMUXER_STATE_PARSE_FRAME) {
153             MEDIA_LOG_W("PullDataWithCache, not cache begin.");
154             return ret;
155         }
156         std::shared_ptr<Buffer> mergedBuffer = Buffer::CreateDefaultBuffer(
157             tempBuffer->GetMemory()->GetSize() + memory->GetSize());
158         FALSE_RETURN_V_MSG_E(mergedBuffer != nullptr, Status::ERROR_UNKNOWN, "mergedBuffer invalid");
159         FALSE_RETURN_V_MSG_E(mergedBuffer->GetMemory() != nullptr, Status::ERROR_UNKNOWN,
160             "mergedBuffer->GetMemory invalid");
161         mergedBuffer->GetMemory()->Write(memory->GetReadOnlyData(), memory->GetSize(), 0);
162         mergedBuffer->GetMemory()->Write(tempBuffer->GetMemory()->GetReadOnlyData(),
163             tempBuffer->GetMemory()->GetSize(), memory->GetSize());
164         cacheDataMap_[streamID].SetData(mergedBuffer);
165         memory = cacheDataMap_[streamID].GetData()->GetMemory();
166         FALSE_RETURN_V_MSG_E(memory != nullptr, Status::ERROR_UNKNOWN, "memory invalid");
167         MEDIA_LOG_I("PullDataWithCache, offset: " PUBLIC_LOG_U64 ", cache offset: " PUBLIC_LOG_U64
168             ", cache size: " PUBLIC_LOG_ZU, offset, cacheDataMap_[streamID].GetOffset(), memory->GetSize());
169     }
170     FALSE_RETURN_V_MSG_E(ret != Status::END_OF_STREAM, Status::OK, "eos&data return data");
171     return ret;
172 }
173 
ProcInnerDash(int32_t streamID,uint64_t offset,std::shared_ptr<Buffer> & bufferPtr)174 Status StreamDemuxer::ProcInnerDash(int32_t streamID,  uint64_t offset, std::shared_ptr<Buffer>& bufferPtr)
175 {
176     FALSE_RETURN_V_MSG_E(bufferPtr != nullptr, Status::ERROR_UNKNOWN, "bufferPtr invalid");
177     if (IsDash()) {
178         MEDIA_LOG_D("dash PullDataWithoutCache, cacheDataMap_ exist streamID , merge it.");
179         FALSE_RETURN_V_MSG_E(cacheDataMap_[streamID].GetData() != nullptr, Status::ERROR_UNKNOWN, "getdata invalid");
180         auto cacheMemory = cacheDataMap_[streamID].GetData()->GetMemory();
181         auto bufferMemory = bufferPtr->GetMemory();
182         FALSE_RETURN_V_MSG_E(bufferMemory != nullptr, Status::ERROR_UNKNOWN, "bufferPtr invalid");
183         FALSE_RETURN_V_MSG_E(cacheMemory != nullptr, Status::ERROR_UNKNOWN, "cacheMemory invalid");
184         std::shared_ptr<Buffer> mergedBuffer = Buffer::CreateDefaultBuffer(
185             bufferMemory->GetSize() + cacheMemory->GetSize());
186         FALSE_RETURN_V_MSG_E(mergedBuffer != nullptr, Status::ERROR_UNKNOWN, "mergedBuffer invalid");
187         auto mergeMemory = mergedBuffer->GetMemory();
188         FALSE_RETURN_V_MSG_E(mergeMemory != nullptr, Status::ERROR_UNKNOWN, "mergeMemory invalid");
189         MEDIA_LOG_I("dash PullDataWithoutCache merge before: cache offset: " PUBLIC_LOG_U64
190             ", cache size: " PUBLIC_LOG_ZU, cacheDataMap_[streamID].GetOffset(), cacheMemory->GetSize());
191         mergeMemory->Write(cacheMemory->GetReadOnlyData(), cacheMemory->GetSize(), 0);
192         mergeMemory->Write(bufferMemory->GetReadOnlyData(), bufferMemory->GetSize(), cacheMemory->GetSize());
193         cacheDataMap_[streamID].SetData(mergedBuffer);
194         MEDIA_LOG_I("dash PullDataWithoutCache merge after: " PUBLIC_LOG_U64 ", cache offset: " PUBLIC_LOG_U64,
195             offset, cacheDataMap_[streamID].GetOffset());
196     }
197     return Status::OK;
198 }
199 
PullDataWithoutCache(int32_t streamID,uint64_t offset,size_t size,std::shared_ptr<Buffer> & bufferPtr)200 Status StreamDemuxer::PullDataWithoutCache(int32_t streamID, uint64_t offset, size_t size,
201     std::shared_ptr<Buffer>& bufferPtr)
202 {
203     Status ret = PullData(streamID, offset, size, bufferPtr);
204     if (ret != Status::OK) {
205         MEDIA_LOG_E("PullDataWithoutCache, PullData error " PUBLIC_LOG_D32, static_cast<int32_t>(ret));
206         return ret;
207     }
208     if (cacheDataMap_.find(streamID) != cacheDataMap_.end()) {
209         MEDIA_LOG_D("PullDataWithoutCache, cacheDataMap_ exist streamID , do nothing.");
210         ret = ProcInnerDash(streamID, offset, bufferPtr);
211         if (ret != Status::OK) {
212             MEDIA_LOG_E("ProcInnerDash error " PUBLIC_LOG_D32, static_cast<int32_t>(ret));
213             return ret;
214         }
215     } else {
216         CacheData cacheTmp;
217         cacheDataMap_[streamID] = cacheTmp;
218     }
219     if (cacheDataMap_[streamID].GetData() == nullptr || cacheDataMap_[streamID].GetData()->GetMemory() == nullptr) {
220         MEDIA_LOG_D("PullDataWithoutCache, write cache data.");
221         if (bufferPtr->GetMemory() == nullptr) {
222             MEDIA_LOG_W("PullDataWithoutCache, write cache data error. memory is nullptr!");
223         } else {
224             auto buffer = Buffer::CreateDefaultBuffer(bufferPtr->GetMemory()->GetSize());
225             if (buffer != nullptr && buffer->GetMemory() != nullptr) {
226                 buffer->GetMemory()->Write(bufferPtr->GetMemory()->GetReadOnlyData(),
227                     bufferPtr->GetMemory()->GetSize(), 0);
228                 cacheDataMap_[streamID].Init(buffer, offset);
229                 MEDIA_LOG_D("PullDataWithoutCache, write cache data success. offset=" PUBLIC_LOG_U64, offset);
230             } else {
231                 MEDIA_LOG_W("PullDataWithoutCache, write cache data failed. memory is nullptr!");
232             }
233         }
234     }
235     return ret;
236 }
237 
ReadRetry(int32_t streamID,uint64_t offset,size_t size,std::shared_ptr<Plugins::Buffer> & data)238 Status StreamDemuxer::ReadRetry(int32_t streamID, uint64_t offset, size_t size,
239     std::shared_ptr<Plugins::Buffer>& data)
240 {
241     FALSE_RETURN_V_MSG_E(data->GetMemory() != nullptr, Status::ERROR_UNKNOWN, "getmemory invalid");
242     Status err = Status::OK;
243     int32_t retryTimes = 0;
244     while (true && !isInterruptNeeded_.load()) {
245         err = source_->Read(streamID, data, offset, size);
246         if (IsDash() && streamID != data->streamID) {
247             break;
248         }
249         FALSE_RETURN_V_MSG_E(err != Status::ERROR_UNKNOWN, Status::ERROR_UNKNOWN, "error unknown");
250         if (err != Status::END_OF_STREAM && data->GetMemory()->GetSize() == 0) {
251             OSAL::SleepFor(TRY_READ_SLEEP_TIME);
252             retryTimes++;
253             if (retryTimes > TRY_READ_TIMES) {
254                 break;
255             }
256             continue;
257         }
258         break;
259     }
260     FALSE_LOG_MSG(!isInterruptNeeded_.load(), "ReadRetry interrupted");
261     return err;
262 }
263 
PullData(int32_t streamID,uint64_t offset,size_t size,std::shared_ptr<Plugins::Buffer> & data)264 Status StreamDemuxer::PullData(int32_t streamID, uint64_t offset, size_t size,
265     std::shared_ptr<Plugins::Buffer>& data)
266 {
267     MEDIA_LOG_DD("IN, offset: " PUBLIC_LOG_U64 ", size: " PUBLIC_LOG_ZU
268         ", position: " PUBLIC_LOG_U64, offset, size, position_);
269     if (!source_) {
270         return Status::ERROR_INVALID_OPERATION;
271     }
272     Status err;
273     auto readSize = size;
274     if (source_->IsSeekToTimeSupported() || source_->GetSeekable() == Plugins::Seekable::UNSEEKABLE) {
275         err = ReadRetry(streamID, offset, readSize, data);
276         FALSE_LOG_MSG(err == Status::OK, "hls, plugin read failed.");
277         return err;
278     }
279 
280     uint64_t totalSize = 0;
281     if ((source_->GetSize(totalSize) == Status::OK) && (totalSize != 0)) {
282         if (offset >= totalSize) {
283             MEDIA_LOG_D("Offset: " PUBLIC_LOG_U64 " is larger than totalSize: " PUBLIC_LOG_U64, offset, totalSize);
284             return Status::END_OF_STREAM;
285         }
286         if ((offset + readSize) > totalSize) {
287             readSize = totalSize - offset;
288         }
289         if (data->GetMemory() != nullptr) {
290             auto realSize = data->GetMemory()->GetCapacity();
291             readSize = (readSize > realSize) ? realSize : readSize;
292         }
293         MEDIA_LOG_DD("TotalSize_: " PUBLIC_LOG_U64, totalSize);
294     }
295     if (position_ != offset) {
296         err = source_->SeekTo(offset);
297         FALSE_RETURN_V_MSG_E(err == Status::OK, err, "Seek to " PUBLIC_LOG_U64 " fail", offset);
298         position_ = offset;
299     }
300 
301     err = ReadRetry(streamID, offset, readSize, data);
302     if (err == Status::OK) {
303         FALSE_RETURN_V_MSG_E(data->GetMemory() != nullptr, Status::ERROR_UNKNOWN, "data->GetMemory invalid");
304         position_ += data->GetMemory()->GetSize();
305     }
306     return err;
307 }
308 
ResetCache(int32_t streamID)309 Status StreamDemuxer::ResetCache(int32_t streamID)
310 {
311     if (cacheDataMap_.find(streamID) != cacheDataMap_.end()) {
312         cacheDataMap_[streamID].Reset();
313         cacheDataMap_.erase(streamID);
314     }
315     return Status::OK;
316 }
317 
ResetAllCache()318 Status StreamDemuxer::ResetAllCache()
319 {
320     for (auto& iter : cacheDataMap_) {
321         iter.second.Reset();
322     }
323     cacheDataMap_.clear();
324     return Status::OK;
325 }
326 
Start()327 Status StreamDemuxer::Start()
328 {
329     return Status::OK;
330 }
331 
332 
Stop()333 Status StreamDemuxer::Stop()
334 {
335     return Status::OK;
336 }
337 
338 
Resume()339 Status StreamDemuxer::Resume()
340 {
341     return Status::OK;
342 }
343 
344 
Pause()345 Status StreamDemuxer::Pause()
346 {
347     return Status::OK;
348 }
349 
Flush()350 Status StreamDemuxer::Flush()
351 {
352     return Status::OK;
353 }
354 
HandleReadHeader(int32_t streamID,int64_t offset,std::shared_ptr<Buffer> & buffer,size_t expectedLen)355 Status StreamDemuxer::HandleReadHeader(int32_t streamID, int64_t offset, std::shared_ptr<Buffer>& buffer,
356     size_t expectedLen)
357 {
358     MEDIA_LOG_D("Demuxer parse DEMUXER_STATE_PARSE_HEADER, offset: " PUBLIC_LOG_D64
359         ", expectedLen: " PUBLIC_LOG_ZU, offset, expectedLen);
360     if (expectedLen == 0) {
361         return Status::END_OF_STREAM;
362     }
363     Status ret = getRange_(streamID, static_cast<uint64_t>(offset), expectedLen, buffer);
364     if (ret == Status::OK) {
365         DUMP_BUFFER2FILE(DEMUXER_INPUT_PEEK, buffer);
366         return ret;
367     }
368     // Under the current specifications, change buffer->streamID only in the scenario of switching tracks.
369     FALSE_RETURN_V_NOLOG(!IsDash() || buffer == nullptr || buffer->streamID == streamID, Status::END_OF_STREAM);
370 
371     if (mediaDataSize_ == LIVE_CONTENT_LENGTH) {
372         return Status::OK;
373     }
374     MEDIA_LOG_W("Demuxer parse DEMUXER_STATE_PARSE_HEADER, getRange_ failed, ret = " PUBLIC_LOG_D32, ret);
375     return ret;
376 }
377 
CheckChangeStreamID(int32_t streamID,std::shared_ptr<Buffer> & buffer)378 Status StreamDemuxer::CheckChangeStreamID(int32_t streamID, std::shared_ptr<Buffer>& buffer)
379 {
380     if (IsDash()) {
381         if (buffer != nullptr && buffer->streamID != streamID) {
382             if (GetNewVideoStreamID() == streamID) {
383                 SetNewVideoStreamID(buffer->streamID);
384             } else if (GetNewAudioStreamID() == streamID) {
385                 SetNewAudioStreamID(buffer->streamID);
386             } else if (GetNewSubtitleStreamID() == streamID) {
387                 SetNewSubtitleStreamID(buffer->streamID);
388             } else {}
389             MEDIA_LOG_I("Demuxer parse dash change, oldStreamID = " PUBLIC_LOG_D32
390                 ", newStreamID = " PUBLIC_LOG_D32, streamID, buffer->streamID);
391             return Status::END_OF_STREAM;
392         }
393     }
394     return Status::OK;
395 }
396 
HandleReadPacket(int32_t streamID,int64_t offset,std::shared_ptr<Buffer> & buffer,size_t expectedLen)397 Status StreamDemuxer::HandleReadPacket(int32_t streamID, int64_t offset, std::shared_ptr<Buffer>& buffer,
398     size_t expectedLen)
399 {
400     MEDIA_LOG_D("Demuxer parse DEMUXER_STATE_PARSE_FRAME");
401     Status ret = getRange_(streamID, static_cast<uint64_t>(offset), expectedLen, buffer);
402     if (ret == Status::OK) {
403         DUMP_BUFFER2LOG("Demuxer GetRange", buffer, offset);
404         DUMP_BUFFER2FILE(DEMUXER_INPUT_GET, buffer);
405         if (buffer != nullptr && buffer->GetMemory() != nullptr &&
406             buffer->GetMemory()->GetSize() == 0) {
407             MEDIA_LOG_I("Demuxer parse DEMUXER_STATE_PARSE_FRAME in pausing(isIgnoreParse),"
408                         " Read fail and try again");
409             return Status::ERROR_AGAIN;
410         }
411         return ret;
412     }
413     MEDIA_LOG_W("Demuxer parse DEMUXER_STATE_PARSE_FRAME, getRange_ failed, ret = " PUBLIC_LOG_D32, ret);
414     return ret;
415 }
416 
CallbackReadAt(int32_t streamID,int64_t offset,std::shared_ptr<Buffer> & buffer,size_t expectedLen)417 Status StreamDemuxer::CallbackReadAt(int32_t streamID, int64_t offset, std::shared_ptr<Buffer>& buffer,
418     size_t expectedLen)
419 {
420     FALSE_RETURN_V(!isInterruptNeeded_.load(), Status::ERROR_WRONG_STATE);
421     switch (pluginStateMap_[streamID]) {
422         case DemuxerState::DEMUXER_STATE_NULL:
423             return Status::ERROR_WRONG_STATE;
424         case DemuxerState::DEMUXER_STATE_PARSE_HEADER: {
425             auto ret = HandleReadHeader(streamID, offset, buffer, expectedLen);
426             if (ret != Status::OK) {
427                 return ret;
428             }
429             break;
430         }
431         case DemuxerState::DEMUXER_STATE_PARSE_FIRST_FRAME:
432         case DemuxerState::DEMUXER_STATE_PARSE_FRAME: {
433             auto ret = HandleReadPacket(streamID, offset, buffer, expectedLen);
434             if (ret == Status::END_OF_STREAM &&
435                 pluginStateMap_[streamID] == DemuxerState::DEMUXER_STATE_PARSE_FIRST_FRAME) {
436                 SetDemuxerState(streamID, DemuxerState::DEMUXER_STATE_PARSE_FRAME);
437                 return ret;
438             }
439             if (ret != Status::OK) {
440                 return ret;
441             }
442             if (pluginStateMap_[streamID] == DemuxerState::DEMUXER_STATE_PARSE_FIRST_FRAME) {
443                 SetDemuxerState(streamID, DemuxerState::DEMUXER_STATE_PARSE_FRAME);
444             }
445             break;
446         }
447         default:
448             break;
449     }
450     return Status::OK;
451 }
452 
453 } // namespace Media
454 } // namespace OHOS