Skip to content

Commit faa1e93

Browse files
committed
video_decoder: support reconnect with video format change.
1 parent 5cf7b92 commit faa1e93

18 files changed

+607
-111
lines changed

src/drivers/devices/ascend/flowunit/video_decoder/ascend_video_decode.cc

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ void AscendVideoDecoder::Callback(acldvppStreamDesc *input,
205205

206206
auto *ctx = (DvppVideoDecodeContext *)userData;
207207
auto queue = ctx->GetCacheQueue();
208+
if (queue == nullptr) {
209+
acldvppFree(vdecOutBufferDev);
210+
MBLOG_ERROR << "get cache queue failed.";
211+
return;
212+
}
208213
auto res = queue->Push(dvpp_frame);
209214
if (!res) {
210215
acldvppFree(vdecOutBufferDev);
@@ -214,6 +219,7 @@ void AscendVideoDecoder::Callback(acldvppStreamDesc *input,
214219

215220
modelbox::Status AscendVideoDecoder::Init(
216221
const std::shared_ptr<modelbox::DataContext> &data_ctx) {
222+
vdecChannelDesc_ = nullptr;
217223
aclError ret = aclrtSetDevice(device_id_);
218224
if (ret != ACL_ERROR_NONE) {
219225
auto errMsg = "acl set device " + std::to_string(device_id_) +
@@ -304,22 +310,17 @@ modelbox::Status AscendVideoDecoder::Init(
304310

305311
auto device_id = device_id_;
306312
vdecChannelDesc_.reset(
307-
vdecChannelDescPtr, [device_id](aclvdecChannelDesc *p) {
308-
auto ret = aclrtSetDevice(device_id);
309-
if (ret != ACL_ERROR_NONE) {
310-
MBLOG_ERROR << "Set device to " << device_id
311-
<< " failed, err: " << ret;
312-
}
313-
314-
ret = aclvdecDestroyChannel(p);
313+
vdecChannelDescPtr, [this, device_id](aclvdecChannelDesc *p) {
314+
auto ret = aclvdecDestroyChannel(p);
315315
if (ret != ACL_ERROR_NONE) {
316316
MBLOG_ERROR << "fail to destroy vdec channel, err: " << ret;
317317
}
318-
319318
ret = aclvdecDestroyChannelDesc(p);
320319
if (ret != ACL_ERROR_NONE) {
321320
MBLOG_ERROR << "fail to destroy vdec channel desc, err: " << ret;
322321
}
322+
323+
this->thread_handler_ = nullptr;
323324
});
324325

325326
setup_result = true;

src/drivers/devices/ascend/flowunit/video_decoder/video_decoder_flowunit.cc

Lines changed: 172 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,90 @@ modelbox::Status VideoDecodeFlowUnit::Open(
147147
return modelbox::STATUS_OK;
148148
}
149149

150-
modelbox::Status VideoDecodeFlowUnit::DataPre(
151-
std::shared_ptr<modelbox::DataContext> data_ctx) {
150+
modelbox::Status VideoDecodeFlowUnit::ReopenDecoder(
151+
std::shared_ptr<modelbox::DataContext> &data_ctx,
152+
const std::shared_ptr<modelbox::Buffer> &flag_buffer) {
153+
auto old_source_url =
154+
std::static_pointer_cast<std::string>(data_ctx->GetPrivate(SOURCE_URL_META));
155+
auto old_codec_id =
156+
std::static_pointer_cast<AVCodecID>(data_ctx->GetPrivate(CODEC_ID_META));
157+
158+
if (old_source_url == nullptr || old_codec_id == nullptr) {
159+
MBLOG_ERROR << "Reopen decoder failed, source url or codec id is null";
160+
return modelbox::STATUS_FAULT;
161+
}
162+
163+
std::string source_url;
164+
AVCodecID codec_id;
165+
if (flag_buffer->Get(SOURCE_URL_META, source_url) == false) {
166+
return modelbox::STATUS_SUCCESS;
167+
}
168+
169+
if (flag_buffer->Get(CODEC_ID_META, codec_id) == false) {
170+
return modelbox::STATUS_SUCCESS;
171+
}
172+
173+
if (source_url == *old_source_url && codec_id == *old_codec_id) {
174+
return modelbox::STATUS_SUCCESS;
175+
}
176+
177+
MBLOG_WARN << "Reopen decoder, source url or codec id changed";
178+
auto ret = CloseDecoder(data_ctx);
179+
if (ret != modelbox::STATUS_SUCCESS) {
180+
MBLOG_ERROR << "Close decoder failed";
181+
return modelbox::STATUS_FAULT;
182+
}
183+
184+
int32_t rate_num;
185+
int32_t rate_den;
186+
int32_t encode_type;
187+
188+
auto res = flag_buffer->Get("rate_num", rate_num);
189+
if (!res) {
190+
return {modelbox::STATUS_FAULT, "get rate_num failed."};
191+
}
192+
193+
res = flag_buffer->Get("rate_den", rate_den);
194+
if (!res) {
195+
return {modelbox::STATUS_FAULT, "get rate_den failed."};
196+
}
197+
198+
auto in_meta = data_ctx->GetInputMeta(VIDEO_PACKET_INPUT);
199+
auto profile_id =
200+
std::static_pointer_cast<int32_t>(in_meta->GetMeta(PROFILE_META));
201+
if (profile_id == nullptr) {
202+
return {modelbox::STATUS_FAULT, "get profile id failed."};
203+
}
204+
205+
encode_type = GetDvppEncodeType(codec_id, *profile_id);
206+
if (encode_type == -1) {
207+
return {modelbox::STATUS_FAULT, "get dvpp encode type failed."};
208+
}
209+
210+
return NewDecoder(data_ctx, source_url, codec_id, rate_num, rate_den,
211+
encode_type);
212+
}
213+
214+
modelbox::Status VideoDecodeFlowUnit::CloseDecoder(
215+
std::shared_ptr<modelbox::DataContext> &data_ctx) {
216+
auto instance_id =
217+
std::static_pointer_cast<int32_t>(data_ctx->GetPrivate(INSTANCE_ID));
218+
if (instance_id != nullptr) {
219+
RestoreInstanceId(*instance_id);
220+
}
221+
data_ctx->SetPrivate(DVPP_DECODER, nullptr);
222+
data_ctx->SetPrivate(DVPP_DECODER_CTX, nullptr);
223+
data_ctx->SetPrivate(FRAME_INDEX_CTX, nullptr);
224+
data_ctx->SetPrivate(INSTANCE_ID, nullptr);
225+
data_ctx->SetPrivate(SOURCE_URL_META, nullptr);
226+
data_ctx->SetPrivate(CODEC_ID_META, nullptr);
227+
return modelbox::STATUS_SUCCESS;
228+
}
229+
230+
modelbox::Status VideoDecodeFlowUnit::NewDecoder(
231+
std::shared_ptr<modelbox::DataContext> &data_ctx,
232+
const std::string &source_url, AVCodecID codec_id, int32_t rate_num,
233+
int32_t rate_den, int32_t encode_type) {
152234
int32_t instance_id = 0;
153235
instance_id = FindTheMinimumAvailableId();
154236
modelbox::Status ret = modelbox::STATUS_SUCCESS;
@@ -162,17 +244,6 @@ modelbox::Status VideoDecodeFlowUnit::DataPre(
162244

163245
DeferCondAdd { RestoreInstanceId(instance_id); };
164246

165-
int32_t rate_num;
166-
int32_t rate_den;
167-
int32_t encode_type;
168-
auto res = GetDecoderParam(data_ctx, rate_num, rate_den, encode_type);
169-
if (!res) {
170-
auto errMsg = "get decoder param failed, detail: " + res.ToString();
171-
MBLOG_ERROR << errMsg;
172-
ret = {modelbox::STATUS_FAULT, errMsg};
173-
return ret;
174-
}
175-
176247
auto video_decoder = std::make_shared<AscendVideoDecoder>(
177248
instance_id, dev_id_, rate_num, rate_den, format_, encode_type);
178249
ret = video_decoder->Init(data_ctx);
@@ -192,24 +263,67 @@ modelbox::Status VideoDecodeFlowUnit::DataPre(
192263
data_ctx->SetPrivate(DVPP_DECODER, video_decoder);
193264
data_ctx->SetPrivate(FRAME_INDEX_CTX, frame_index);
194265
data_ctx->SetPrivate(INSTANCE_ID, instance_id_ptr);
195-
MBLOG_INFO << "acl video decode data pre success.";
266+
data_ctx->SetPrivate(SOURCE_URL_META, std::make_shared<std::string>(source_url));
267+
data_ctx->SetPrivate(CODEC_ID_META, std::make_shared<AVCodecID>(codec_id));
268+
MBLOG_INFO << "open video decode data success.";
196269

197270
return ret;
271+
}
272+
273+
modelbox::Status VideoDecodeFlowUnit::DataPre(
274+
std::shared_ptr<modelbox::DataContext> data_ctx) {
275+
auto input_packet = data_ctx->Input(VIDEO_PACKET_INPUT);
276+
if (input_packet == nullptr) {
277+
return {modelbox::STATUS_FAULT, "get input failed."};
278+
}
279+
280+
int32_t rate_num;
281+
int32_t rate_den;
282+
int32_t encode_type;
283+
284+
auto buffer = input_packet->At(0);
285+
auto res = buffer->Get("rate_num", rate_num);
286+
if (!res) {
287+
return {modelbox::STATUS_FAULT, "get rate_num failed."};
288+
}
289+
290+
res = buffer->Get("rate_den", rate_den);
291+
if (!res) {
292+
return {modelbox::STATUS_FAULT, "get rate_den failed."};
293+
}
294+
295+
auto in_meta = data_ctx->GetInputMeta(VIDEO_PACKET_INPUT);
296+
auto codec_id =
297+
std::static_pointer_cast<AVCodecID>(in_meta->GetMeta(CODEC_META));
298+
if (codec_id == nullptr) {
299+
return {modelbox::STATUS_FAULT, "get codec id failed."};
300+
}
301+
302+
auto source_url =
303+
std::static_pointer_cast<std::string>(in_meta->GetMeta(SOURCE_URL_META));
304+
if (source_url == nullptr) {
305+
MBLOG_ERROR << "Stream source url is null, init decoder failed";
306+
return modelbox::STATUS_FAULT;
307+
}
308+
309+
auto profile_id =
310+
std::static_pointer_cast<int32_t>(in_meta->GetMeta(PROFILE_META));
311+
if (profile_id == nullptr) {
312+
return {modelbox::STATUS_FAULT, "get profile id failed."};
313+
}
314+
315+
encode_type = GetDvppEncodeType(*codec_id, *profile_id);
316+
if (encode_type == -1) {
317+
return {modelbox::STATUS_FAULT, "get dvpp encode type failed."};
318+
}
319+
320+
return NewDecoder(data_ctx, *source_url, *codec_id, rate_num, rate_den,
321+
encode_type);
198322
};
199323

200324
modelbox::Status VideoDecodeFlowUnit::DataPost(
201325
std::shared_ptr<modelbox::DataContext> data_ctx) {
202-
MBLOG_DEBUG << "videodecoder data post.";
203-
// Destroy decoder first
204-
data_ctx->SetPrivate(DVPP_DECODER, nullptr);
205-
// Ctx must destroy after decoder destroy
206-
data_ctx->SetPrivate(DVPP_DECODER_CTX, nullptr);
207-
// Restore id
208-
auto instance_id =
209-
std::static_pointer_cast<int32_t>(data_ctx->GetPrivate(INSTANCE_ID));
210-
RestoreInstanceId(*instance_id);
211-
212-
return modelbox::STATUS_SUCCESS;
326+
return CloseDecoder(data_ctx);
213327
}
214328

215329
modelbox::Status VideoDecodeFlowUnit::Close() {
@@ -219,7 +333,9 @@ modelbox::Status VideoDecodeFlowUnit::Close() {
219333

220334
modelbox::Status VideoDecodeFlowUnit::ReadData(
221335
const std::shared_ptr<modelbox::DataContext> &data_ctx,
222-
std::vector<std::shared_ptr<DvppPacket>> &dvpp_packet_list) {
336+
std::vector<std::shared_ptr<DvppPacket>> &dvpp_packet_list,
337+
std::shared_ptr<modelbox::Buffer> &flag_buffer) {
338+
auto reset_flag = false;
223339
auto video_packet_input = data_ctx->Input(VIDEO_PACKET_INPUT);
224340
if (video_packet_input == nullptr) {
225341
MBLOG_ERROR << "video packet input is null";
@@ -233,6 +349,14 @@ modelbox::Status VideoDecodeFlowUnit::ReadData(
233349

234350
for (size_t i = 0; i < video_packet_input->Size(); ++i) {
235351
auto packet_buffer = video_packet_input->At(i);
352+
353+
if (reset_flag == false) {
354+
packet_buffer->Get("reset_flag", reset_flag);
355+
if (reset_flag == true) {
356+
flag_buffer = packet_buffer;
357+
}
358+
}
359+
236360
std::shared_ptr<DvppPacket> dvpp_packet;
237361
auto ret = ReadDvppStreamDesc(packet_buffer, dvpp_packet);
238362
if (ret != modelbox::STATUS_SUCCESS) {
@@ -462,6 +586,8 @@ modelbox::Status VideoDecodeFlowUnit::WriteData(
462586

463587
modelbox::Status VideoDecodeFlowUnit::Process(
464588
std::shared_ptr<modelbox::DataContext> data_ctx) {
589+
std::shared_ptr<modelbox::Buffer> flag_buffer = nullptr;
590+
465591
auto acl_ret = aclrtSetDevice(dev_id_);
466592
if (acl_ret != ACL_SUCCESS) {
467593
MBLOG_ERROR << "set acl device to " << dev_id_ << " failed, err "
@@ -473,7 +599,7 @@ modelbox::Status VideoDecodeFlowUnit::Process(
473599
data_ctx->GetPrivate(DVPP_DECODER_CTX));
474600
auto video_decoder = std::static_pointer_cast<AscendVideoDecoder>(
475601
data_ctx->GetPrivate(DVPP_DECODER));
476-
if (video_decoder == nullptr) {
602+
if (video_decoder == nullptr || video_decoder_ctx == nullptr) {
477603
MBLOG_ERROR << "Video decoder is not init";
478604
return modelbox::STATUS_FAULT;
479605
}
@@ -489,12 +615,30 @@ modelbox::Status VideoDecodeFlowUnit::Process(
489615
}
490616

491617
std::vector<std::shared_ptr<DvppPacket>> dvpp_packet_list;
492-
ret = ReadData(data_ctx, dvpp_packet_list);
618+
ret = ReadData(data_ctx, dvpp_packet_list, flag_buffer);
493619
if (ret != modelbox::STATUS_SUCCESS) {
494620
MBLOG_ERROR << "Read av_packet input failed, err code " + ret.ToString();
495621
return modelbox::STATUS_FAULT;
496622
}
497623

624+
if (flag_buffer) {
625+
video_decoder_ctx = nullptr;
626+
video_decoder = nullptr;
627+
if (ReopenDecoder(data_ctx, flag_buffer) != modelbox::STATUS_SUCCESS) {
628+
MBLOG_ERROR << "Reopen decoder failed";
629+
return modelbox::STATUS_FAULT;
630+
}
631+
632+
video_decoder_ctx = std::static_pointer_cast<DvppVideoDecodeContext>(
633+
data_ctx->GetPrivate(DVPP_DECODER_CTX));
634+
video_decoder = std::static_pointer_cast<AscendVideoDecoder>(
635+
data_ctx->GetPrivate(DVPP_DECODER));
636+
if (video_decoder == nullptr || video_decoder_ctx == nullptr) {
637+
MBLOG_ERROR << "Video decoder is not init";
638+
return modelbox::STATUS_FAULT;
639+
}
640+
}
641+
498642
size_t err_num = 0;
499643
modelbox::Status decode_ret = modelbox::STATUS_SUCCESS;
500644
for (auto &dvpp_pkt : dvpp_packet_list) {

src/drivers/devices/ascend/flowunit/video_decoder/video_decoder_flowunit.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ constexpr const char *DVPP_DECODER = "dvpp_decode";
7373
constexpr const char *VIDEO_PACKET_INPUT = "in_video_packet";
7474
constexpr const char *FRAME_INFO_OUTPUT = "out_video_frame";
7575
constexpr const char *CODEC_META = "codec_meta";
76+
constexpr const char *SOURCE_URL_META = "source_url";
77+
constexpr const char *CODEC_ID_META = "codec_id";
7678
constexpr const char *PROFILE_META = "profile_meta";
7779
constexpr const char *DVPP_DECODER_CTX = "dvpp_decode_context";
7880
constexpr const char *DVPP_DECODE_FLOWUNIT_DESC =
@@ -121,7 +123,8 @@ class VideoDecodeFlowUnit : public modelbox::FlowUnit {
121123
int32_t &rate_den, int32_t &encode_type);
122124
modelbox::Status ReadData(
123125
const std::shared_ptr<modelbox::DataContext> &data_ctx,
124-
std::vector<std::shared_ptr<DvppPacket>> &dvpp_packet_list);
126+
std::vector<std::shared_ptr<DvppPacket>> &dvpp_packet_list,
127+
std::shared_ptr<modelbox::Buffer> &flag_buffer);
125128
modelbox::Status ReadDvppStreamDesc(
126129
const std::shared_ptr<modelbox::Buffer> &packet_buffer,
127130
std::shared_ptr<DvppPacket> &dvpp_packet);
@@ -134,6 +137,16 @@ class VideoDecodeFlowUnit : public modelbox::FlowUnit {
134137
int32_t FindTheMinimumAvailableId();
135138
void RestoreInstanceId(int32_t instance_id);
136139

140+
modelbox::Status CloseDecoder(
141+
std::shared_ptr<modelbox::DataContext> &data_ctx);
142+
modelbox::Status NewDecoder(std::shared_ptr<modelbox::DataContext> &data_ctx,
143+
const std::string &source_url, AVCodecID codec_id,
144+
int32_t rate_num, int32_t rate_den,
145+
int32_t encode_type);
146+
modelbox::Status ReopenDecoder(
147+
std::shared_ptr<modelbox::DataContext> &data_ctx,
148+
const std::shared_ptr<modelbox::Buffer> &flag_buffer);
149+
137150
uint32_t dest_width_{224};
138151
uint32_t dest_height_{224};
139152
// 1: YUV420 semi-planner(nv12), 2: YVU420 semi-planner(nv21)

0 commit comments

Comments
 (0)