diff --git a/src/projects/base/ovlibrary/future.h b/src/projects/base/ovlibrary/future.h new file mode 100644 index 000000000..bd280e32e --- /dev/null +++ b/src/projects/base/ovlibrary/future.h @@ -0,0 +1,84 @@ +//============================================================================== +// +// OvenMediaEngine +// +// Created by getroot +// Copyright (c) 2018 AirenSoft. All rights reserved. +// +//============================================================================== +#pragma once + +#include +#include + +namespace ov +{ + + class Future + { + public: + void Stop() + { + std::unique_lock lock(_mutex); + + _stop_flag = true; + + _condition.notify_all(); + } + + // template + bool Submit(bool result) + { + std::unique_lock lock(_mutex); + + _result = result; + _condition.notify_all(); + + return _result; + } + + // template + bool Get() + { + std::unique_lock lock(_mutex); + + _condition.wait(lock); + + if (_stop_flag) + { + return false; + } + + return _result; + } + + // return false : timed out, return true : signalled + // template + bool GetFor(uint32_t timeout_delta_msec) + { + std::unique_lock lock(_mutex); + + while (!_stop_flag) + { + auto result = _condition.wait_for(lock, std::chrono::milliseconds(timeout_delta_msec)); + if (result == std::cv_status::timeout) + { + return false; + } + } + + if (_stop_flag) + { + return false; + } + + return _result; + } + + private: + std::mutex _mutex; + std::condition_variable _condition; + bool _stop_flag = false; + bool _result = false; + }; +} \ No newline at end of file diff --git a/src/projects/base/ovlibrary/ovlibrary.h b/src/projects/base/ovlibrary/ovlibrary.h index 7870325a8..f46180b48 100644 --- a/src/projects/base/ovlibrary/ovlibrary.h +++ b/src/projects/base/ovlibrary/ovlibrary.h @@ -33,6 +33,7 @@ #include "./random.h" #include "./regex.h" #include "./semaphore.h" +#include "./future.h" #include "./singleton.h" #include "./stack_trace.h" #include "./stop_watch.h" diff --git a/src/projects/transcoder/codec/decoder/decoder_aac.cpp b/src/projects/transcoder/codec/decoder/decoder_aac.cpp index d89dcdbba..a2b2146f2 100644 --- a/src/projects/transcoder/codec/decoder/decoder_aac.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_aac.cpp @@ -11,13 +11,8 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderAAC::Configure(std::shared_ptr context) +bool DecoderAAC::InitCodec() { - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - const AVCodec *_codec = ::avcodec_find_decoder(GetCodecID()); if (_codec == nullptr) { @@ -40,7 +35,6 @@ bool DecoderAAC::Configure(std::shared_ptr context) return false; } - // Create packet parser _parser = ::av_parser_init(GetCodecID()); if (_parser == nullptr) { @@ -49,27 +43,17 @@ bool DecoderAAC::Configure(std::shared_ptr context) } _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%s", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - return true; } void DecoderAAC::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + bool no_data_to_encode = false; while (!_kill_flag) @@ -104,7 +88,7 @@ void DecoderAAC::CodecThread() if (_pkt_offset < _cur_data->GetLength()) { _pkt->size = 0; - + int32_t parsed_size = ::av_parser_parse2( _parser, _context, @@ -143,7 +127,6 @@ void DecoderAAC::CodecThread() int ret = ::avcodec_send_packet(_context, _pkt); if (ret == AVERROR(EAGAIN)) { - } else if (ret == AVERROR_EOF) { @@ -220,9 +203,8 @@ void DecoderAAC::CodecThread() _frame->pkt_duration = ffmpeg::Conv::GetDurationPerFrame(cmn::MediaType::Audio, GetRefTrack(), _frame); } - // If the decoded audio frame does not have a PTS, Increase frame duration time in PTS of previous frame - if(_frame->pts == AV_NOPTS_VALUE) + if (_frame->pts == AV_NOPTS_VALUE) { _frame->pts = _last_pkt_pts + _frame->pkt_duration; } diff --git a/src/projects/transcoder/codec/decoder/decoder_aac.h b/src/projects/transcoder/codec/decoder/decoder_aac.h index acd567214..bb0a2cf71 100644 --- a/src/projects/transcoder/codec/decoder/decoder_aac.h +++ b/src/projects/transcoder/codec/decoder/decoder_aac.h @@ -29,7 +29,7 @@ class DecoderAAC : public TranscodeDecoder int64_t _last_pkt_pts = 0; - bool Configure(std::shared_ptr context) override; + bool InitCodec(); void CodecThread() override; diff --git a/src/projects/transcoder/codec/decoder/decoder_avc.cpp b/src/projects/transcoder/codec/decoder/decoder_avc.cpp index 9549c45ef..14342f930 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_avc.cpp @@ -11,45 +11,6 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderAVC::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Create packet parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - // Initialize codec - if (InitCodec() == false) - { - return false; - } - - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%s", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - - return true; -} - bool DecoderAVC::InitCodec() { @@ -84,6 +45,14 @@ bool DecoderAVC::InitCodec() return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; @@ -92,10 +61,17 @@ bool DecoderAVC::InitCodec() void DecoderAVC::UninitCodec() { - ::avcodec_close(_context); - ::avcodec_free_context(&_context); - + if (_context != nullptr) + { + ::avcodec_free_context(&_context); + } _context = nullptr; + + if (_parser != nullptr) + { + ::av_parser_close(_parser); + } + _parser = nullptr; } bool DecoderAVC::ReinitCodecIfNeed() @@ -117,6 +93,12 @@ bool DecoderAVC::ReinitCodecIfNeed() void DecoderAVC::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); diff --git a/src/projects/transcoder/codec/decoder/decoder_avc.h b/src/projects/transcoder/codec/decoder/decoder_avc.h index 8b9df2af2..3649bb2b9 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc.h +++ b/src/projects/transcoder/codec/decoder/decoder_avc.h @@ -23,8 +23,6 @@ class DecoderAVC : public TranscodeDecoder return AV_CODEC_ID_H264; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); void UninitCodec(); bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.cpp b/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.cpp index fcecf3210..ec86b2805 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.cpp @@ -8,51 +8,12 @@ //============================================================================== #include "decoder_avc_nilogan.h" -#include "../../transcoder_gpu.h" -#include "../../transcoder_private.h" -#include "base/info/application.h" - #include #include -bool DecoderAVCxNILOGAN::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Create packet parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - if (InitCodec() == false) - { - return false; - } - - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sNilogan", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - - return true; -} +#include "../../transcoder_gpu.h" +#include "../../transcoder_private.h" +#include "base/info/application.h" bool DecoderAVCxNILOGAN::InitCodec() { @@ -71,43 +32,50 @@ bool DecoderAVCxNILOGAN::InitCodec() } _context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NILOGAN, _track->GetCodecDeviceId())); - if(_context->hw_device_ctx == nullptr) + if (_context->hw_device_ctx == nullptr) { logte("Could not allocate hw device context for %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); return false; } - - _context->time_base = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); _context->pkt_timebase = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); _context->flags |= AV_CODEC_FLAG_LOW_DELAY; - + auto decoder_config = std::static_pointer_cast(GetRefTrack()->GetDecoderConfigurationRecord()); - - if(decoder_config->ChromaFormat() > 1) { + + if (decoder_config->ChromaFormat() > 1) + { logte("Could not initialize codec because nilogan decoder support only AV_PIX_FMT_YUV420P pixel format: %d", decoder_config->ChromaFormat()); return false; } if (decoder_config != nullptr) - { - _context->pix_fmt = AV_PIX_FMT_YUV420P; //Forced here nilogan decoder support only AV_PIX_FMT_YUV420P pixel format + { + _context->pix_fmt = AV_PIX_FMT_YUV420P; //Forced here nilogan decoder support only AV_PIX_FMT_YUV420P pixel format _context->width = decoder_config->GetWidth(); _context->height = decoder_config->GetHeight(); } - + //dec_options ::av_opt_set(_context->priv_data, "xcoder-params", "out=sw:lowDelayMode=1:lowDelay=100", 0); //::av_opt_set(_context->priv_data, "xcoder-params", "out=hw:lowDelayMode=1:lowDelay=100", 0); //::av_opt_set(_context->priv_data, "dec", 0, 0); - + if (::avcodec_open2(_context, _codec, nullptr) < 0) { logte("Could not open codec: %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); return false; } - + + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; return true; @@ -145,6 +113,12 @@ bool DecoderAVCxNILOGAN::ReinitCodecIfNeed() void DecoderAVCxNILOGAN::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -177,13 +151,13 @@ void DecoderAVCxNILOGAN::CodecThread() logte("An error occurred while parsing: %d", parsed_size); break; } - + // if activated, I got Warning: time out on receiving a decoded framefrom the decoder, assume dropped, received frame_num: 0, sent pkt_num: 1, pkt_num-frame_num: 1, sending another packet. // if(ReinitCodecIfNeed() == false) // { // break; // } - + if (_pkt->size > 0) { _pkt->pts = _parser->pts; @@ -292,9 +266,9 @@ void DecoderAVCxNILOGAN::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / ((double) GetRefTrack()->GetTimeBase().GetNum() / (double) GetRefTrack()->GetTimeBase().GetDen()) ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / ((double)GetRefTrack()->GetTimeBase().GetNum() / (double)GetRefTrack()->GetTimeBase().GetDen())); } auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.h b/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.h index 32ec2a917..5070a9e3c 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.h +++ b/src/projects/transcoder/codec/decoder/decoder_avc_nilogan.h @@ -23,8 +23,6 @@ class DecoderAVCxNILOGAN : public TranscodeDecoder return AV_CODEC_ID_H264; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); //void UninitCodec(); //bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_nv.cpp b/src/projects/transcoder/codec/decoder/decoder_avc_nv.cpp index 18db558c2..30d876f59 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_nv.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_avc_nv.cpp @@ -12,45 +12,6 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderAVCxNV::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Initialize H.264 stream parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - if (InitCodec() == false) - { - return false; - } - - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sNV", ffmpeg::Conv::GetCodecName(GetCodecID()).CStr()).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - - return false; - } - - return true; -} - bool DecoderAVCxNV::InitCodec() { const AVCodec *_codec = ::avcodec_find_decoder_by_name("h264_cuvid"); @@ -73,36 +34,51 @@ bool DecoderAVCxNV::InitCodec() // Get hardware device context auto hw_device_ctx = TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NVENC, GetRefTrack()->GetCodecDeviceId()); - if(hw_device_ctx == nullptr) + if (hw_device_ctx == nullptr) { logte("Could not get hw device context for %s", ffmpeg::Conv::GetCodecName(GetCodecID()).CStr()); return false; } // Assign HW device context to decoder - if(ffmpeg::Conv::SetHwDeviceCtxOfAVCodecContext(_context, hw_device_ctx) == false) + if (ffmpeg::Conv::SetHwDeviceCtxOfAVCodecContext(_context, hw_device_ctx) == false) { logte("Could not set hw device context for %s", ffmpeg::Conv::GetCodecName(GetCodecID()).CStr()); return false; } - + if (::avcodec_open2(_context, _codec, nullptr) < 0) { logte("Could not open codec: %s", ffmpeg::Conv::GetCodecName(GetCodecID()).CStr()); return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; - + return true; } void DecoderAVCxNV::UninitCodec() { - ::avcodec_close(_context); - ::avcodec_free_context(&_context); - + if (_context != nullptr) + { + ::avcodec_free_context(&_context); + } _context = nullptr; + + if (_parser != nullptr) + { + ::av_parser_close(_parser); + } + _parser = nullptr; } bool DecoderAVCxNV::ReinitCodecIfNeed() @@ -121,11 +97,17 @@ bool DecoderAVCxNV::ReinitCodecIfNeed() } } - return true; + return true; } void DecoderAVCxNV::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -157,7 +139,7 @@ void DecoderAVCxNV::CodecThread() break; } - if(ReinitCodecIfNeed() == false) + if (ReinitCodecIfNeed() == false) { break; } @@ -271,9 +253,9 @@ void DecoderAVCxNV::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / (double) GetRefTrack()->GetTimeBase().GetExpr() ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / (double)GetRefTrack()->GetTimeBase().GetExpr()); } auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_nv.h b/src/projects/transcoder/codec/decoder/decoder_avc_nv.h index 6dfc0eb9c..aa8fcf50f 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_nv.h +++ b/src/projects/transcoder/codec/decoder/decoder_avc_nv.h @@ -23,8 +23,6 @@ class DecoderAVCxNV : public TranscodeDecoder return AV_CODEC_ID_H264; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); void UninitCodec(); bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp b/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp index 8b762ef73..54e83b8da 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp @@ -12,13 +12,8 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderAVCxQSV::Configure(std::shared_ptr context) +bool DecoderAVCxQSV::InitCodec() { - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - const AVCodec *_codec = ::avcodec_find_decoder_by_name("h264_qsv"); if (_codec == nullptr) { @@ -43,7 +38,6 @@ bool DecoderAVCxQSV::Configure(std::shared_ptr context) return false; } - // Create packet parser _parser = ::av_parser_init(GetCodecID()); if (_parser == nullptr) { @@ -52,26 +46,17 @@ bool DecoderAVCxQSV::Configure(std::shared_ptr context) } _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sQsv", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - return true; } void DecoderAVCxQSV::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -210,11 +195,11 @@ void DecoderAVCxQSV::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / ((double) GetRefTrack()->GetTimeBase().GetNum() / (double) GetRefTrack()->GetTimeBase().GetDen()) ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / ((double)GetRefTrack()->GetTimeBase().GetNum() / (double)GetRefTrack()->GetTimeBase().GetDen())); } - + auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); ::av_frame_unref(_frame); if (decoded_frame == nullptr) diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_qsv.h b/src/projects/transcoder/codec/decoder/decoder_avc_qsv.h index d42186257..81fb5914a 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_qsv.h +++ b/src/projects/transcoder/codec/decoder/decoder_avc_qsv.h @@ -23,7 +23,7 @@ class DecoderAVCxQSV : public TranscodeDecoder return AV_CODEC_ID_H264; } - bool Configure(std::shared_ptr context) override; + bool InitCodec(); void CodecThread() override; }; diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_xma.cpp b/src/projects/transcoder/codec/decoder/decoder_avc_xma.cpp index 4890d57c5..76e4dd772 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_xma.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_avc_xma.cpp @@ -8,51 +8,12 @@ //============================================================================== #include "decoder_avc_xma.h" -#include "../../transcoder_gpu.h" -#include "../../transcoder_private.h" -#include "base/info/application.h" - #include #include -bool DecoderAVCxXMA::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Initialize H.264 stream parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - if (InitCodec() == false) - { - return false; - } - - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sXMA", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - - return false; - } - - return true; -} +#include "../../transcoder_gpu.h" +#include "../../transcoder_private.h" +#include "base/info/application.h" bool DecoderAVCxXMA::InitCodec() { @@ -73,7 +34,7 @@ bool DecoderAVCxXMA::InitCodec() _context->codec_type = AVMEDIA_TYPE_VIDEO; _context->time_base = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); _context->pkt_timebase = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); - + auto decoder_config = std::static_pointer_cast(GetRefTrack()->GetDecoderConfigurationRecord()); if (decoder_config != nullptr) @@ -90,20 +51,27 @@ bool DecoderAVCxXMA::InitCodec() if (extra_data != nullptr) { _context->extradata_size = extra_data->GetLength(); - _context->extradata = (uint8_t*)::av_malloc(_context->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + _context->extradata = (uint8_t *)::av_malloc(_context->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); ::memset(_context->extradata, 0, _context->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - ::memcpy(_context->extradata, reinterpret_cast(extra_data->GetData()), _context->extradata_size); + ::memcpy(_context->extradata, reinterpret_cast(extra_data->GetData()), _context->extradata_size); } ::av_opt_set_int(_context->priv_data, "lxlnx_hwdev", _track->GetCodecDeviceId(), 0); - if (::avcodec_open2(_context, _codec, nullptr) < 0) { logte("Could not open codec: %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; return true; @@ -111,10 +79,17 @@ bool DecoderAVCxXMA::InitCodec() void DecoderAVCxXMA::UninitCodec() { - ::avcodec_close(_context); - ::avcodec_free_context(&_context); - + if (_context != nullptr) + { + ::avcodec_free_context(&_context); + } _context = nullptr; + + if (_parser != nullptr) + { + ::av_parser_close(_parser); + } + _parser = nullptr; } bool DecoderAVCxXMA::ReinitCodecIfNeed() @@ -136,9 +111,14 @@ bool DecoderAVCxXMA::ReinitCodecIfNeed() return true; } - void DecoderAVCxXMA::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -156,7 +136,7 @@ void DecoderAVCxXMA::CodecThread() logtw("An error occurred while converting annexb to xvcc"); continue; } - + off_t offset = 0LL; int64_t remained = packet_data->GetLength(); @@ -164,7 +144,6 @@ void DecoderAVCxXMA::CodecThread() int64_t dts = (buffer->GetDts() == -1LL) ? AV_NOPTS_VALUE : buffer->GetDts(); [[maybe_unused]] int64_t duration = (buffer->GetDuration() == -1LL) ? AV_NOPTS_VALUE : buffer->GetDuration(); auto data = packet_data->GetDataAs(); - while (remained > 0) { @@ -177,7 +156,7 @@ void DecoderAVCxXMA::CodecThread() break; } - if(ReinitCodecIfNeed() == false) + if (ReinitCodecIfNeed() == false) { logte("An error occurred while reinit codec"); break; @@ -243,7 +222,6 @@ void DecoderAVCxXMA::CodecThread() offset += parsed_size; remained -= parsed_size; - } while (!_kill_flag) @@ -295,9 +273,9 @@ void DecoderAVCxXMA::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / ((double) GetRefTrack()->GetTimeBase().GetNum() / (double) GetRefTrack()->GetTimeBase().GetDen()) ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / ((double)GetRefTrack()->GetTimeBase().GetNum() / (double)GetRefTrack()->GetTimeBase().GetDen())); } auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); @@ -305,14 +283,10 @@ void DecoderAVCxXMA::CodecThread() { continue; } - - // logtd("%d / %d / fmt(%d)", decoded_frame->GetWidth(), decoded_frame->GetHeight(), decoded_frame->GetFormat()); - ::av_frame_unref(_frame); Complete(need_to_change_notify ? TranscodeResult::FormatChanged : TranscodeResult::DataReady, std::move(decoded_frame)); } - } } } diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_xma.h b/src/projects/transcoder/codec/decoder/decoder_avc_xma.h index b246f0af0..b650ae41a 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_xma.h +++ b/src/projects/transcoder/codec/decoder/decoder_avc_xma.h @@ -23,8 +23,6 @@ class DecoderAVCxXMA : public TranscodeDecoder return AV_CODEC_ID_H264; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); void UninitCodec(); bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc.cpp b/src/projects/transcoder/codec/decoder/decoder_hevc.cpp index 35cf46078..adfd8fdd7 100755 --- a/src/projects/transcoder/codec/decoder/decoder_hevc.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_hevc.cpp @@ -11,46 +11,6 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderHEVC::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Create packet parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - if (InitCodec() == false) - { - return false; - } - - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%s", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - - return true; -} - bool DecoderHEVC::InitCodec() { const AVCodec *_codec = ::avcodec_find_decoder(GetCodecID()); @@ -77,17 +37,32 @@ bool DecoderHEVC::InitCodec() return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; - + return true; } void DecoderHEVC::UninitCodec() { - ::avcodec_close(_context); - ::avcodec_free_context(&_context); - + if (_context != nullptr) + { + ::avcodec_free_context(&_context); + } _context = nullptr; + + if (_parser != nullptr) + { + ::av_parser_close(_parser); + } + _parser = nullptr; } bool DecoderHEVC::ReinitCodecIfNeed() @@ -106,11 +81,17 @@ bool DecoderHEVC::ReinitCodecIfNeed() } } - return true; + return true; } void DecoderHEVC::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -145,7 +126,7 @@ void DecoderHEVC::CodecThread() break; } - if(ReinitCodecIfNeed() == false) + if (ReinitCodecIfNeed() == false) { break; } @@ -261,11 +242,11 @@ void DecoderHEVC::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / ((double) GetRefTrack()->GetTimeBase().GetNum() / (double) GetRefTrack()->GetTimeBase().GetDen()) ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / ((double)GetRefTrack()->GetTimeBase().GetNum() / (double)GetRefTrack()->GetTimeBase().GetDen())); } - + auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); ::av_frame_unref(_frame); if (decoded_frame == nullptr) diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc.h b/src/projects/transcoder/codec/decoder/decoder_hevc.h index 60a91c40d..124270797 100755 --- a/src/projects/transcoder/codec/decoder/decoder_hevc.h +++ b/src/projects/transcoder/codec/decoder/decoder_hevc.h @@ -24,8 +24,6 @@ class DecoderHEVC : public TranscodeDecoder return AV_CODEC_ID_H265; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); void UninitCodec(); bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.cpp b/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.cpp index 4a6fa44cf..179a4f8d3 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.cpp @@ -15,46 +15,6 @@ #include #include -bool DecoderHEVCxNILOGAN::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - - // Create packet parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - if (InitCodec() == false) - { - return false; - } - - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sNilogan", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - - return true; -} - bool DecoderHEVCxNILOGAN::InitCodec() { const AVCodec *_codec = ::avcodec_find_decoder_by_name("h265_ni_logan_dec"); @@ -78,8 +38,6 @@ bool DecoderHEVCxNILOGAN::InitCodec() return false; } - - _context->time_base = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); _context->pkt_timebase = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); _context->flags |= AV_CODEC_FLAG_LOW_DELAY; @@ -108,11 +66,25 @@ bool DecoderHEVCxNILOGAN::InitCodec() return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + return true; } void DecoderHEVCxNILOGAN::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -267,9 +239,6 @@ void DecoderHEVCxNILOGAN::CodecThread() { continue; } - - // logtd("%d / %d / fmt(%d)", decoded_frame->GetWidth(), decoded_frame->GetHeight(), decoded_frame->GetFormat()); - ::av_frame_unref(_frame); Complete(need_to_change_notify ? TranscodeResult::FormatChanged : TranscodeResult::DataReady, std::move(decoded_frame)); diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.h b/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.h index d3a398303..377b60813 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.h +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_nilogan.h @@ -23,7 +23,6 @@ class DecoderHEVCxNILOGAN : public TranscodeDecoder return AV_CODEC_ID_HEVC; } - bool Configure(std::shared_ptr context) override; bool InitCodec(); void CodecThread() override; diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_nv.cpp b/src/projects/transcoder/codec/decoder/decoder_hevc_nv.cpp index c1f134667..0079fab27 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_nv.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_nv.cpp @@ -12,46 +12,6 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderHEVCxNV::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Initialize H.264 stream parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - if (InitCodec() == false) - { - return false; - } - - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sNV", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - - _kill_flag = true; - - return false; - } - - return true; -} - bool DecoderHEVCxNV::InitCodec() { const AVCodec *_codec = ::avcodec_find_decoder_by_name("hevc_cuvid"); @@ -69,7 +29,7 @@ bool DecoderHEVCxNV::InitCodec() } _context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NVENC, _track->GetCodecDeviceId())); - if(_context->hw_device_ctx == nullptr) + if (_context->hw_device_ctx == nullptr) { logte("Could not allocate hw device context for %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); return false; @@ -86,17 +46,32 @@ bool DecoderHEVCxNV::InitCodec() return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; - + return true; } void DecoderHEVCxNV::UninitCodec() { - ::avcodec_close(_context); - ::avcodec_free_context(&_context); - + if (_context != nullptr) + { + ::avcodec_free_context(&_context); + } _context = nullptr; + + if (_parser != nullptr) + { + ::av_parser_close(_parser); + } + _parser = nullptr; } bool DecoderHEVCxNV::ReinitCodecIfNeed() @@ -120,6 +95,12 @@ bool DecoderHEVCxNV::ReinitCodecIfNeed() void DecoderHEVCxNV::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -150,7 +131,7 @@ void DecoderHEVCxNV::CodecThread() break; } - if(ReinitCodecIfNeed() == false) + if (ReinitCodecIfNeed() == false) { break; } @@ -260,9 +241,9 @@ void DecoderHEVCxNV::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / ((double) GetRefTrack()->GetTimeBase().GetNum() / (double) GetRefTrack()->GetTimeBase().GetDen()) ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / ((double)GetRefTrack()->GetTimeBase().GetNum() / (double)GetRefTrack()->GetTimeBase().GetDen())); } auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); @@ -270,7 +251,6 @@ void DecoderHEVCxNV::CodecThread() { continue; } - ::av_frame_unref(_frame); Complete(need_to_change_notify ? TranscodeResult::FormatChanged : TranscodeResult::DataReady, std::move(decoded_frame)); diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_nv.h b/src/projects/transcoder/codec/decoder/decoder_hevc_nv.h index a875a90c2..d877da8f2 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_nv.h +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_nv.h @@ -23,8 +23,6 @@ class DecoderHEVCxNV : public TranscodeDecoder return AV_CODEC_ID_H265; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); void UninitCodec(); bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.cpp b/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.cpp index 626e2fc87..2a478e150 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.cpp @@ -11,13 +11,8 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderHEVCxQSV::Configure(std::shared_ptr context) +bool DecoderHEVCxQSV::InitCodec() { - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - const AVCodec *_codec = ::avcodec_find_decoder_by_name("hevc_qsv"); if (_codec == nullptr) { @@ -40,36 +35,25 @@ bool DecoderHEVCxQSV::Configure(std::shared_ptr context) return false; } - // Create packet parser _parser = ::av_parser_init(GetCodecID()); if (_parser == nullptr) { logte("Parser not found"); return false; } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sQsv", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - return true; } void DecoderHEVCxQSV::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -208,11 +192,11 @@ void DecoderHEVCxQSV::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / ((double) GetRefTrack()->GetTimeBase().GetNum() / (double) GetRefTrack()->GetTimeBase().GetDen()) ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / ((double)GetRefTrack()->GetTimeBase().GetNum() / (double)GetRefTrack()->GetTimeBase().GetDen())); } - + auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); ::av_frame_unref(_frame); if (decoded_frame == nullptr) diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.h b/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.h index 147726c0b..4cb17183f 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.h +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_qsv.h @@ -23,7 +23,7 @@ class DecoderHEVCxQSV : public TranscodeDecoder return AV_CODEC_ID_H265; } - bool Configure(std::shared_ptr context) override; - + bool InitCodec(); + void CodecThread() override; }; diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_xma.cpp b/src/projects/transcoder/codec/decoder/decoder_hevc_xma.cpp index 6f60b738f..8ba0bb28b 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_xma.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_xma.cpp @@ -16,45 +16,6 @@ #include #include -bool DecoderHEVCxXMA::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Initialize H.264 stream parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - if (InitCodec() == false) - { - return false; - } - - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%sXMA", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - - return false; - } - - return true; -} - bool DecoderHEVCxXMA::InitCodec() { const AVCodec *_codec = ::avcodec_find_decoder_by_name("mpsoc_vcu_hevc"); @@ -74,7 +35,7 @@ bool DecoderHEVCxXMA::InitCodec() _context->codec_type = AVMEDIA_TYPE_VIDEO; _context->time_base = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); _context->pkt_timebase = ffmpeg::Conv::TimebaseToAVRational(GetTimebase()); - + auto decoder_config = std::static_pointer_cast(GetRefTrack()->GetDecoderConfigurationRecord()); if (decoder_config != nullptr) @@ -91,9 +52,9 @@ bool DecoderHEVCxXMA::InitCodec() if (extra_data != nullptr) { _context->extradata_size = extra_data->GetLength(); - _context->extradata = (uint8_t*)::av_malloc(_context->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + _context->extradata = (uint8_t *)::av_malloc(_context->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); ::memset(_context->extradata, 0, _context->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); - ::memcpy(_context->extradata, reinterpret_cast(extra_data->GetData()), _context->extradata_size); + ::memcpy(_context->extradata, reinterpret_cast(extra_data->GetData()), _context->extradata_size); } ::av_opt_set_int(_context->priv_data, "lxlnx_hwdev", _track->GetCodecDeviceId(), 0); @@ -104,6 +65,14 @@ bool DecoderHEVCxXMA::InitCodec() return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; return true; @@ -111,10 +80,17 @@ bool DecoderHEVCxXMA::InitCodec() void DecoderHEVCxXMA::UninitCodec() { - ::avcodec_close(_context); - ::avcodec_free_context(&_context); - + if (_context != nullptr) + { + ::avcodec_free_context(&_context); + } _context = nullptr; + + if (_parser != nullptr) + { + ::av_parser_close(_parser); + } + _parser = nullptr; } bool DecoderHEVCxXMA::ReinitCodecIfNeed() @@ -136,9 +112,14 @@ bool DecoderHEVCxXMA::ReinitCodecIfNeed() return true; } - void DecoderHEVCxXMA::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -165,7 +146,6 @@ void DecoderHEVCxXMA::CodecThread() int64_t dts = (buffer->GetDts() == -1LL) ? AV_NOPTS_VALUE : buffer->GetDts(); [[maybe_unused]] int64_t duration = (buffer->GetDuration() == -1LL) ? AV_NOPTS_VALUE : buffer->GetDuration(); auto data = packet_data->GetDataAs(); - while (remained > 0) { @@ -178,7 +158,7 @@ void DecoderHEVCxXMA::CodecThread() break; } - if(ReinitCodecIfNeed() == false) + if (ReinitCodecIfNeed() == false) { break; } @@ -243,7 +223,6 @@ void DecoderHEVCxXMA::CodecThread() offset += parsed_size; remained -= parsed_size; - } while (!_kill_flag) @@ -295,9 +274,9 @@ void DecoderHEVCxXMA::CodecThread() } // If there is no duration, the duration is calculated by framerate and timebase. - if(_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) + if (_frame->pkt_duration <= 0LL && _context->framerate.num > 0 && _context->framerate.den > 0) { - _frame->pkt_duration = (int64_t)( ((double)_context->framerate.den / (double)_context->framerate.num) / ((double) GetRefTrack()->GetTimeBase().GetNum() / (double) GetRefTrack()->GetTimeBase().GetDen()) ); + _frame->pkt_duration = (int64_t)(((double)_context->framerate.den / (double)_context->framerate.num) / ((double)GetRefTrack()->GetTimeBase().GetNum() / (double)GetRefTrack()->GetTimeBase().GetDen())); } auto decoded_frame = ffmpeg::Conv::ToMediaFrame(cmn::MediaType::Video, _frame); @@ -305,16 +284,10 @@ void DecoderHEVCxXMA::CodecThread() { continue; } - - // logtd("%d / %d / fmt(%d)", decoded_frame->GetWidth(), decoded_frame->GetHeight(), decoded_frame->GetFormat()); - ::av_frame_unref(_frame); Complete(need_to_change_notify ? TranscodeResult::FormatChanged : TranscodeResult::DataReady, std::move(decoded_frame)); } - } - - } } diff --git a/src/projects/transcoder/codec/decoder/decoder_hevc_xma.h b/src/projects/transcoder/codec/decoder/decoder_hevc_xma.h index 20d3c7b81..09a8bdd42 100644 --- a/src/projects/transcoder/codec/decoder/decoder_hevc_xma.h +++ b/src/projects/transcoder/codec/decoder/decoder_hevc_xma.h @@ -23,8 +23,6 @@ class DecoderHEVCxXMA : public TranscodeDecoder return AV_CODEC_ID_H265; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); void UninitCodec(); bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/decoder/decoder_mp3.cpp b/src/projects/transcoder/codec/decoder/decoder_mp3.cpp index 2366ae9e4..a81b10bc9 100644 --- a/src/projects/transcoder/codec/decoder/decoder_mp3.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_mp3.cpp @@ -11,13 +11,8 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderMP3::Configure(std::shared_ptr context) +bool DecoderMP3::InitCodec() { - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - const AVCodec *_codec = ::avcodec_find_decoder(GetCodecID()); if (_codec == nullptr) { @@ -40,36 +35,24 @@ bool DecoderMP3::Configure(std::shared_ptr context) return false; } - // Create packet parser _parser = ::av_parser_init(GetCodecID()); if (_parser == nullptr) { logte("Parser not found"); return false; } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%s", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - return true; } void DecoderMP3::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } bool no_data_to_encode = false; while (!_kill_flag) @@ -104,7 +87,7 @@ void DecoderMP3::CodecThread() if (_pkt_offset < _cur_data->GetLength()) { _pkt->size = 0; - + int32_t parsed_size = ::av_parser_parse2( _parser, _context, @@ -143,7 +126,6 @@ void DecoderMP3::CodecThread() int ret = ::avcodec_send_packet(_context, _pkt); if (ret == AVERROR(EAGAIN)) { - } else if (ret == AVERROR_EOF) { @@ -220,9 +202,8 @@ void DecoderMP3::CodecThread() _frame->pkt_duration = ffmpeg::Conv::GetDurationPerFrame(cmn::MediaType::Audio, GetRefTrack(), _frame); } - // If the decoded audio frame does not have a PTS, Increase frame duration time in PTS of previous frame - if(_frame->pts == AV_NOPTS_VALUE) + if (_frame->pts == AV_NOPTS_VALUE) { _frame->pts = _last_pkt_pts + _frame->pkt_duration; } diff --git a/src/projects/transcoder/codec/decoder/decoder_mp3.h b/src/projects/transcoder/codec/decoder/decoder_mp3.h index 0e6264b2b..4f62c6498 100644 --- a/src/projects/transcoder/codec/decoder/decoder_mp3.h +++ b/src/projects/transcoder/codec/decoder/decoder_mp3.h @@ -29,7 +29,7 @@ class DecoderMP3 : public TranscodeDecoder int64_t _last_pkt_pts = 0; - bool Configure(std::shared_ptr context) override; + bool InitCodec(); void CodecThread() override; diff --git a/src/projects/transcoder/codec/decoder/decoder_opus.cpp b/src/projects/transcoder/codec/decoder/decoder_opus.cpp index 859469757..5b62fcaac 100644 --- a/src/projects/transcoder/codec/decoder/decoder_opus.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_opus.cpp @@ -11,13 +11,8 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderOPUS::Configure(std::shared_ptr context) +bool DecoderOPUS::InitCodec() { - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - const AVCodec *_codec = ::avcodec_find_decoder(GetCodecID()); if (_codec == nullptr) { @@ -40,36 +35,25 @@ bool DecoderOPUS::Configure(std::shared_ptr context) return false; } - // Create packet parser _parser = ::av_parser_init(GetCodecID()); if (_parser == nullptr) { logte("Parser not found"); return false; } - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%s", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - return true; } void DecoderOPUS::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + bool no_data_to_encode = false; while (!_kill_flag) @@ -104,7 +88,7 @@ void DecoderOPUS::CodecThread() if (_pkt_offset < _cur_data->GetLength()) { _pkt->size = 0; - + int32_t parsed_size = ::av_parser_parse2( _parser, _context, @@ -143,7 +127,6 @@ void DecoderOPUS::CodecThread() int ret = ::avcodec_send_packet(_context, _pkt); if (ret == AVERROR(EAGAIN)) { - } else if (ret == AVERROR_EOF) { @@ -220,9 +203,8 @@ void DecoderOPUS::CodecThread() _frame->pkt_duration = ffmpeg::Conv::GetDurationPerFrame(cmn::MediaType::Audio, GetRefTrack(), _frame); } - // If the decoded audio frame does not have a PTS, Increase frame duration time in PTS of previous frame - if(_frame->pts == AV_NOPTS_VALUE) + if (_frame->pts == AV_NOPTS_VALUE) { _frame->pts = _last_pkt_pts + _frame->pkt_duration; } diff --git a/src/projects/transcoder/codec/decoder/decoder_opus.h b/src/projects/transcoder/codec/decoder/decoder_opus.h index 1e1e5dc72..96455b760 100644 --- a/src/projects/transcoder/codec/decoder/decoder_opus.h +++ b/src/projects/transcoder/codec/decoder/decoder_opus.h @@ -29,7 +29,7 @@ class DecoderOPUS : public TranscodeDecoder int64_t _last_pkt_pts = 0; - bool Configure(std::shared_ptr context) override; + bool InitCodec(); void CodecThread() override; diff --git a/src/projects/transcoder/codec/decoder/decoder_vp8.cpp b/src/projects/transcoder/codec/decoder/decoder_vp8.cpp index 09321b058..902883b82 100644 --- a/src/projects/transcoder/codec/decoder/decoder_vp8.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_vp8.cpp @@ -11,47 +11,6 @@ #include "../../transcoder_private.h" #include "base/info/application.h" -bool DecoderVP8::Configure(std::shared_ptr context) -{ - if (TranscodeDecoder::Configure(context) == false) - { - return false; - } - - // Create packet parser - _parser = ::av_parser_init(GetCodecID()); - if (_parser == nullptr) - { - logte("Parser not found"); - return false; - } - - _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - - // Initialize codec - if (InitCodec() == false) - { - return false; - } - - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. - try - { - _kill_flag = false; - - _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Dec%s", avcodec_get_name(GetCodecID())).CStr()); - } - catch (const std::system_error &e) - { - logte("Failed to start decoder thread"); - _kill_flag = true; - return false; - } - - return true; -} - bool DecoderVP8::InitCodec() { const AVCodec *_codec = ::avcodec_find_decoder(GetCodecID()); @@ -76,6 +35,14 @@ bool DecoderVP8::InitCodec() return false; } + _parser = ::av_parser_init(GetCodecID()); + if (_parser == nullptr) + { + logte("Parser not found"); + return false; + } + _parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + _change_format = false; return true; @@ -83,10 +50,17 @@ bool DecoderVP8::InitCodec() void DecoderVP8::UninitCodec() { - ::avcodec_close(_context); - ::avcodec_free_context(&_context); - + if (_context != nullptr) + { + ::avcodec_free_context(&_context); + } _context = nullptr; + + if (_parser != nullptr) + { + ::av_parser_close(_parser); + } + _parser = nullptr; } bool DecoderVP8::ReinitCodecIfNeed() @@ -108,6 +82,12 @@ bool DecoderVP8::ReinitCodecIfNeed() void DecoderVP8::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); @@ -144,7 +124,7 @@ void DecoderVP8::CodecThread() break; } - if(ReinitCodecIfNeed() == false) + if (ReinitCodecIfNeed() == false) { break; } diff --git a/src/projects/transcoder/codec/decoder/decoder_vp8.h b/src/projects/transcoder/codec/decoder/decoder_vp8.h index 8a6f98332..56aed7655 100644 --- a/src/projects/transcoder/codec/decoder/decoder_vp8.h +++ b/src/projects/transcoder/codec/decoder/decoder_vp8.h @@ -23,8 +23,6 @@ class DecoderVP8 : public TranscodeDecoder return AV_CODEC_ID_VP8; } - bool Configure(std::shared_ptr context) override; - bool InitCodec(); void UninitCodec(); bool ReinitCodecIfNeed(); diff --git a/src/projects/transcoder/codec/encoder/encoder_aac.cpp b/src/projects/transcoder/codec/encoder/encoder_aac.cpp index 238de1541..20ff7de9d 100644 --- a/src/projects/transcoder/codec/encoder/encoder_aac.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_aac.cpp @@ -25,13 +25,9 @@ bool EncoderAAC::SetCodecParams() return true; } -bool EncoderAAC::Configure(std::shared_ptr context) -{ - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } +bool EncoderAAC::InitCodec() +{ auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder(codec_id); if (codec == nullptr) @@ -63,19 +59,33 @@ bool EncoderAAC::Configure(std::shared_ptr context) GetRefTrack()->SetAudioSamplesPerFrame(_codec_context->frame_size); - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderAAC::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderAAC::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_aac.h b/src/projects/transcoder/codec/encoder/encoder_aac.h index 13f16c4d9..ffe643beb 100644 --- a/src/projects/transcoder/codec/encoder/encoder_aac.h +++ b/src/projects/transcoder/codec/encoder/encoder_aac.h @@ -35,6 +35,8 @@ class EncoderAAC : public TranscodeEncoder bool Configure(std::shared_ptr output_context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp index 7992f3ad7..aaac8f1af 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp @@ -97,13 +97,8 @@ bool EncoderAVCxNILOGAN::SetCodecParams() // // - B-frame must be disabled. because, WEBRTC does not support B-Frame. // -bool EncoderAVCxNILOGAN::Configure(std::shared_ptr context) +bool EncoderAVCxNILOGAN::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("h264_ni_logan_enc"); @@ -120,7 +115,7 @@ bool EncoderAVCxNILOGAN::Configure(std::shared_ptr context) return false; } - _codec_context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NILOGAN, context->GetCodecDeviceId())); + _codec_context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NILOGAN, _track->GetCodecDeviceId())); if(_codec_context->hw_device_ctx == nullptr) { logte("Could not allocate hw device context for %s (%d)", ::avcodec_get_name(codec_id), codec_id); @@ -139,19 +134,33 @@ bool EncoderAVCxNILOGAN::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderAVCxNILOGAN::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderAVCxNILOGAN::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%sNilogan", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%sni-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.h b/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.h index 562fa82b3..25385350b 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.h +++ b/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.h @@ -35,6 +35,8 @@ class EncoderAVCxNILOGAN : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp index c0643a0b7..f3ab0ad50 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp @@ -109,13 +109,8 @@ bool EncoderAVCxNV::SetCodecParams() // Notes. // - B-frame must be disabled. because, WEBRTC does not support B-Frame. -bool EncoderAVCxNV::Configure(std::shared_ptr context) +bool EncoderAVCxNV::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("h264_nvenc"); @@ -166,19 +161,33 @@ bool EncoderAVCxNV::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderAVCxNV::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderAVCxNV::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%sNV", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%snv-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_nv.h b/src/projects/transcoder/codec/encoder/encoder_avc_nv.h index 8f79b369a..6b5e8d024 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_nv.h +++ b/src/projects/transcoder/codec/encoder/encoder_avc_nv.h @@ -35,6 +35,8 @@ class EncoderAVCxNV : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp index 4d2a6fe49..876b4d9eb 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp @@ -127,12 +127,8 @@ bool EncoderAVCxOpenH264::SetCodecParams() return true; } -bool EncoderAVCxOpenH264::Configure(std::shared_ptr context) +bool EncoderAVCxOpenH264::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("libopenh264"); @@ -161,19 +157,33 @@ bool EncoderAVCxOpenH264::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderAVCxOpenH264::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; - _codec_thread = std::thread(&TranscodeEncoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + _codec_thread = std::thread(&EncoderAVCxOpenH264::CodecThread, this); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_openh264.h b/src/projects/transcoder/codec/encoder/encoder_avc_openh264.h index 59d27995c..93801e0ff 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_openh264.h +++ b/src/projects/transcoder/codec/encoder/encoder_avc_openh264.h @@ -35,6 +35,8 @@ class EncoderAVCxOpenH264 : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp index 845c56cc5..878a3c770 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp @@ -81,13 +81,8 @@ bool EncoderAVCxQSV::SetCodecParams() // // - B-frame must be disabled. because, WEBRTC does not support B-Frame. // -bool EncoderAVCxQSV::Configure(std::shared_ptr context) +bool EncoderAVCxQSV::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("h264_qsv"); @@ -116,21 +111,37 @@ bool EncoderAVCxQSV::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + + +bool EncoderAVCxQSV::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderAVCxQSV::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%sQsv", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%sqv-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } + return true; } diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_qsv.h b/src/projects/transcoder/codec/encoder/encoder_avc_qsv.h index f9273007d..9c4349865 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_qsv.h +++ b/src/projects/transcoder/codec/encoder/encoder_avc_qsv.h @@ -35,6 +35,8 @@ class EncoderAVCxQSV : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp index 78f1254cf..e2a241496 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp @@ -108,13 +108,8 @@ bool EncoderAVCx264::SetCodecParams() // // - B-frame must be disabled. because, WEBRTC does not support B-Frame. // -bool EncoderAVCx264::Configure(std::shared_ptr context) +bool EncoderAVCx264::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("libx264"); @@ -136,25 +131,40 @@ bool EncoderAVCx264::Configure(std::shared_ptr context) logte("Could not set codec parameters for %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); return false; } + if (::avcodec_open2(_codec_context, _codec_context->codec, nullptr) < 0) { logte("Could not open codec: %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderAVCx264::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderAVCx264::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_x264.h b/src/projects/transcoder/codec/encoder/encoder_avc_x264.h index 19f325b68..fb64e7c99 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_x264.h +++ b/src/projects/transcoder/codec/encoder/encoder_avc_x264.h @@ -35,6 +35,8 @@ class EncoderAVCx264 : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp index 9ea5d0ac2..498040377 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp @@ -92,13 +92,8 @@ bool EncoderAVCxXMA::SetCodecParams() return true; } -bool EncoderAVCxXMA::Configure(std::shared_ptr context) +bool EncoderAVCxXMA::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - ov::String codec_name = "mpsoc_vcu_h264"; const AVCodec *codec = ::avcodec_find_encoder_by_name(codec_name.CStr()); @@ -127,19 +122,34 @@ bool EncoderAVCxXMA::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderAVCxXMA::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { + // Initialize the codec and wait for completion. _kill_flag = false; - _codec_thread = std::thread(&TranscodeEncoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + _codec_thread = std::thread(&EncoderAVCxXMA::CodecThread, this); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%sxa-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_xma.h b/src/projects/transcoder/codec/encoder/encoder_avc_xma.h index eca0bd5e3..c466bd582 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_xma.h +++ b/src/projects/transcoder/codec/encoder/encoder_avc_xma.h @@ -40,6 +40,8 @@ class EncoderAVCxXMA : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_ffopus.cpp b/src/projects/transcoder/codec/encoder/encoder_ffopus.cpp index c70021b18..8164bb5ad 100644 --- a/src/projects/transcoder/codec/encoder/encoder_ffopus.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_ffopus.cpp @@ -43,13 +43,8 @@ bool EncoderFFOPUS::SetCodecParams() return true; } -bool EncoderFFOPUS::Configure(std::shared_ptr output_context) +bool EncoderFFOPUS::InitCodec() { - if (TranscodeEncoder::Configure(output_context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder(codec_id); if (codec == nullptr) @@ -79,19 +74,33 @@ bool EncoderFFOPUS::Configure(std::shared_ptr output_context) GetRefTrack()->SetAudioSamplesPerFrame(_codec_context->frame_size); - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderFFOPUS::Configure(std::shared_ptr output_context) +{ + if (TranscodeEncoder::Configure(output_context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderFFOPUS::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_ffopus.h b/src/projects/transcoder/codec/encoder/encoder_ffopus.h index e088bebe3..da34cdb0b 100644 --- a/src/projects/transcoder/codec/encoder/encoder_ffopus.h +++ b/src/projects/transcoder/codec/encoder/encoder_ffopus.h @@ -35,6 +35,8 @@ class EncoderFFOPUS : public TranscodeEncoder bool Configure(std::shared_ptr output_context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp b/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp index 9fad75021..2cff1a0a8 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp @@ -61,17 +61,8 @@ bool EncoderHEVCxNILOGAN::SetCodecParams() return true; } -// Notes. -// -// - B-frame must be disabled. because, WEBRTC does not support B-Frame. -// -bool EncoderHEVCxNILOGAN::Configure(std::shared_ptr context) +bool EncoderHEVCxNILOGAN::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("h265_ni_logan_enc"); @@ -88,7 +79,7 @@ bool EncoderHEVCxNILOGAN::Configure(std::shared_ptr context) return false; } - _codec_context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NILOGAN, context->GetCodecDeviceId())); + _codec_context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NILOGAN, _track->GetCodecDeviceId())); if(_codec_context->hw_device_ctx == nullptr) { logte("Could not allocate hw device context for %s (%d)", ::avcodec_get_name(codec_id), codec_id); @@ -107,19 +98,34 @@ bool EncoderHEVCxNILOGAN::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderHEVCxNILOGAN::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderHEVCxNILOGAN::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%sNilogan", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { _kill_flag = true; - - logte("Failed to start transcode stream thread."); + return false; } return true; diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.h b/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.h index 032838742..b2bb8839e 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.h +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.h @@ -35,6 +35,8 @@ class EncoderHEVCxNILOGAN : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp b/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp index 8e115e37f..2bc064305 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp @@ -77,15 +77,8 @@ bool EncoderHEVCxNV::SetCodecParams() return true; } -// Notes. -// - B-frame must be disabled. because, WEBRTC does not support B-Frame. -bool EncoderHEVCxNV::Configure(std::shared_ptr context) +bool EncoderHEVCxNV::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("hevc_nvenc"); @@ -102,7 +95,7 @@ bool EncoderHEVCxNV::Configure(std::shared_ptr context) return false; } - _codec_context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NVENC, context->GetCodecDeviceId())); + _codec_context->hw_device_ctx = ::av_buffer_ref(TranscodeGPU::GetInstance()->GetDeviceContext(cmn::MediaCodecModuleId::NVENC, _track->GetCodecDeviceId())); if(_codec_context->hw_device_ctx == nullptr) { logte("Could not allocate hw device context for %s (%d)", ::avcodec_get_name(codec_id), codec_id); @@ -143,19 +136,33 @@ bool EncoderHEVCxNV::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderHEVCxNV::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderHEVCxNV::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%sNV", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%snv-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_nv.h b/src/projects/transcoder/codec/encoder/encoder_hevc_nv.h index 0ee7d1645..2d2d1c0e2 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_nv.h +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_nv.h @@ -34,6 +34,8 @@ class EncoderHEVCxNV : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.cpp b/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.cpp index 3e8a0967a..d54aafa18 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.cpp @@ -47,17 +47,8 @@ bool EncoderHEVCxQSV::SetCodecParams() return true; } -// Notes. -// -// - B-frame must be disabled. because, WEBRTC does not support B-Frame. -// -bool EncoderHEVCxQSV::Configure(std::shared_ptr context) +bool EncoderHEVCxQSV::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder_by_name("hevc_qsv"); @@ -86,20 +77,34 @@ bool EncoderHEVCxQSV::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderHEVCxQSV::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderHEVCxQSV::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%sQsv", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { _kill_flag = true; - - logte("Failed to start transcode stream thread."); + return false; } - return true; } diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.h b/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.h index 7af29beea..d54632b5e 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.h +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_qsv.h @@ -35,6 +35,8 @@ class EncoderHEVCxQSV : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp b/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp index 3345046f6..d47a8830d 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp @@ -80,13 +80,8 @@ bool EncoderHEVCxXMA::SetCodecParams() return true; } -bool EncoderHEVCxXMA::Configure(std::shared_ptr context) +bool EncoderHEVCxXMA::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - ov::String codec_name = "mpsoc_vcu_hevc"; const AVCodec *codec = ::avcodec_find_encoder_by_name(codec_name.CStr()); if (codec == nullptr) @@ -114,21 +109,36 @@ bool EncoderHEVCxXMA::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderHEVCxXMA::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; - _codec_thread = std::thread(&TranscodeEncoder::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + _codec_thread = std::thread(&EncoderHEVCxXMA::CodecThread, this); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%sxa-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } + return true; } diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_xma.h b/src/projects/transcoder/codec/encoder/encoder_hevc_xma.h index 7357fe0af..c4cdd3699 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_xma.h +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_xma.h @@ -41,6 +41,8 @@ class EncoderHEVCxXMA : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_jpeg.cpp b/src/projects/transcoder/codec/encoder/encoder_jpeg.cpp index 68369b0c6..64ac4224c 100755 --- a/src/projects/transcoder/codec/encoder/encoder_jpeg.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_jpeg.cpp @@ -36,13 +36,8 @@ bool EncoderJPEG::SetCodecParams() return true; } -bool EncoderJPEG::Configure(std::shared_ptr context) +bool EncoderJPEG::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder(codec_id); @@ -71,21 +66,34 @@ bool EncoderJPEG::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderJPEG::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderJPEG::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } - return true; } diff --git a/src/projects/transcoder/codec/encoder/encoder_jpeg.h b/src/projects/transcoder/codec/encoder/encoder_jpeg.h index 418a3ae76..c5ee961a6 100755 --- a/src/projects/transcoder/codec/encoder/encoder_jpeg.h +++ b/src/projects/transcoder/codec/encoder/encoder_jpeg.h @@ -35,6 +35,8 @@ class EncoderJPEG : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_opus.cpp b/src/projects/transcoder/codec/encoder/encoder_opus.cpp index 553dc81ba..3a05fcfe7 100644 --- a/src/projects/transcoder/codec/encoder/encoder_opus.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_opus.cpp @@ -38,13 +38,8 @@ bool EncoderOPUS::SetCodecParams() return true; } -bool EncoderOPUS::Configure(std::shared_ptr context) +bool EncoderOPUS::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - // Coding Mode // int application = OPUS_APPLICATION_VOIP; // int application = OPUS_APPLICATION_AUDIO; @@ -115,19 +110,33 @@ bool EncoderOPUS::Configure(std::shared_ptr context) _format = cmn::AudioSample::Format::None; _current_pts = -1; - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderOPUS::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderOPUS::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } @@ -136,6 +145,12 @@ bool EncoderOPUS::Configure(std::shared_ptr context) void EncoderOPUS::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + // Reference : https://opus-codec.org/docs/opus_api-1.1.3/group__opus__encoder.html#gad2d6bf6a9ffb6674879d7605ed073e25 // Number of samples per channel in the input signal. This must be an Opus frame size for the encoder's sampling rate. // For example, at 48 kHz the permitted values are 120, 240, 480, 960, 1920, and 2880. Passing in a duration of less than 10 ms (480 samples at 48 kHz) diff --git a/src/projects/transcoder/codec/encoder/encoder_opus.h b/src/projects/transcoder/codec/encoder/encoder_opus.h index a96a47744..ac6d7a1c1 100644 --- a/src/projects/transcoder/codec/encoder/encoder_opus.h +++ b/src/projects/transcoder/codec/encoder/encoder_opus.h @@ -39,6 +39,8 @@ class EncoderOPUS : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + // void SendBuffer(std::shared_ptr frame) override; void CodecThread() override; diff --git a/src/projects/transcoder/codec/encoder/encoder_png.cpp b/src/projects/transcoder/codec/encoder/encoder_png.cpp index b957e932b..f232ccadd 100755 --- a/src/projects/transcoder/codec/encoder/encoder_png.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_png.cpp @@ -30,13 +30,8 @@ bool EncoderPNG::SetCodecParams() return true; } -bool EncoderPNG::Configure(std::shared_ptr context) +bool EncoderPNG::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder(codec_id); @@ -66,19 +61,33 @@ bool EncoderPNG::Configure(std::shared_ptr context) return false; } - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. + return true; +} + +bool EncoderPNG::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderPNG::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } diff --git a/src/projects/transcoder/codec/encoder/encoder_png.h b/src/projects/transcoder/codec/encoder/encoder_png.h index d03bb00c3..7c8df972b 100755 --- a/src/projects/transcoder/codec/encoder/encoder_png.h +++ b/src/projects/transcoder/codec/encoder/encoder_png.h @@ -35,6 +35,8 @@ class EncoderPNG : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/codec/encoder/encoder_vp8.cpp b/src/projects/transcoder/codec/encoder/encoder_vp8.cpp index 5bdfbf697..062262438 100644 --- a/src/projects/transcoder/codec/encoder/encoder_vp8.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_vp8.cpp @@ -74,13 +74,8 @@ bool EncoderVP8::SetCodecParams() return true; } -bool EncoderVP8::Configure(std::shared_ptr context) +bool EncoderVP8::InitCodec() { - if (TranscodeEncoder::Configure(context) == false) - { - return false; - } - auto codec_id = GetCodecID(); const AVCodec *codec = ::avcodec_find_encoder(codec_id); @@ -109,21 +104,37 @@ bool EncoderVP8::Configure(std::shared_ptr context) return false; } + return true; +} + +bool EncoderVP8::Configure(std::shared_ptr context) +{ + if (TranscodeEncoder::Configure(context) == false) + { + return false; + } + try { _kill_flag = false; _codec_thread = std::thread(&EncoderVP8::CodecThread, this); - pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("ENC-%s-t%d", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); + + // Initialize the codec and wait for completion. + if(_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } } catch (const std::system_error &e) { - logte("Failed to start encoder thread."); _kill_flag = true; - return false; } + return true; } diff --git a/src/projects/transcoder/codec/encoder/encoder_vp8.h b/src/projects/transcoder/codec/encoder/encoder_vp8.h index 1f46ecf7e..9f26ea4f6 100644 --- a/src/projects/transcoder/codec/encoder/encoder_vp8.h +++ b/src/projects/transcoder/codec/encoder/encoder_vp8.h @@ -35,6 +35,8 @@ class EncoderVP8 : public TranscodeEncoder bool Configure(std::shared_ptr context) override; + bool InitCodec() override; + private: bool SetCodecParams() override; }; diff --git a/src/projects/transcoder/filter/filter_base.h b/src/projects/transcoder/filter/filter_base.h index 7d8821ba9..2335ac925 100644 --- a/src/projects/transcoder/filter/filter_base.h +++ b/src/projects/transcoder/filter/filter_base.h @@ -101,6 +101,16 @@ class FilterBase } } + void SetInputTrack(std::shared_ptr input_track) + { + _input_track = input_track; + } + + void SetOutputTrack(std::shared_ptr output_track) + { + _output_track = output_track; + } + protected: std::atomic _state = State::CREATED; @@ -125,8 +135,8 @@ class FilterBase const AVFilter *_buffersrc = nullptr; const AVFilter *_buffersink = nullptr; - - // double _scale = 0.0; + + ov::Future _codec_init_event; // resolution of the input video frame std::shared_ptr _input_track; diff --git a/src/projects/transcoder/filter/filter_fps.cpp b/src/projects/transcoder/filter/filter_fps.cpp index 559c1814e..321b0d82f 100644 --- a/src/projects/transcoder/filter/filter_fps.cpp +++ b/src/projects/transcoder/filter/filter_fps.cpp @@ -44,17 +44,16 @@ void FilterFps::SetOutputFrameRate(double framerate) if (_next_pts != AV_NOPTS_VALUE) { int64_t scaled_next_pts = av_rescale_q_rnd(_next_pts, - av_inv_q(av_d2q(_output_framerate, INT_MAX)), - av_inv_q(av_d2q(framerate, INT_MAX)), - (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); + av_inv_q(av_d2q(_output_framerate, INT_MAX)), + av_inv_q(av_d2q(framerate, INT_MAX)), + (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); // logtd("Change NextPTS : %lld -> %lld", _next_pts, scaled_next_pts); - _next_pts = scaled_next_pts; + _next_pts = scaled_next_pts; } _output_framerate = framerate; - } double FilterFps::GetOutputFrameRate() @@ -70,7 +69,7 @@ void FilterFps::SetSkipFrames(int32_t skip_frames) bool FilterFps::Push(std::shared_ptr media_frame) { stat_input_frame_count++; - + if (_frames.size() >= 2) { logtw("FPS filter is full"); @@ -121,17 +120,16 @@ std::shared_ptr FilterFps::Pop() // Changed from Framerate PTS to Timebase PTS int64_t curr_timebase_pts = av_rescale_q_rnd(_curr_pts, - av_inv_q(av_d2q(_output_framerate, INT_MAX)), - (AVRational){_input_timebase.GetNum(), _input_timebase.GetDen()}, - (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); + av_inv_q(av_d2q(_output_framerate, INT_MAX)), + (AVRational){_input_timebase.GetNum(), _input_timebase.GetDen()}, + (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); - // Calculate the PTS of the next frame considering the Skip Frame. + // Calculate the PTS of the next frame considering the Skip Frame. // Purpose of calculating the Duration of the current frame int64_t next_timebase_pts = av_rescale_q_rnd(_next_pts + _skip_frames, - av_inv_q(av_d2q(_output_framerate, INT_MAX)), - (AVRational){_input_timebase.GetNum(), _input_timebase.GetDen()}, - (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); - + av_inv_q(av_d2q(_output_framerate, INT_MAX)), + (AVRational){_input_timebase.GetNum(), _input_timebase.GetDen()}, + (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); auto pop_frame = _frames[0]->CloneFrame(); pop_frame->SetPts(curr_timebase_pts); diff --git a/src/projects/transcoder/filter/filter_resampler.cpp b/src/projects/transcoder/filter/filter_resampler.cpp index beda3b993..b46f7afe8 100644 --- a/src/projects/transcoder/filter/filter_resampler.cpp +++ b/src/projects/transcoder/filter/filter_resampler.cpp @@ -182,13 +182,18 @@ bool FilterResampler::Configure(const std::shared_ptr &input_track, bool FilterResampler::Start() { - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. try { _kill_flag = false; _thread_work = std::thread(&FilterResampler::WorkerThread, this); - pthread_setname_np(_thread_work.native_handle(), "Resampler"); + pthread_setname_np(_thread_work.native_handle(), ov::String::FormatString("FLT-rsmp-t%u", _output_track->GetId()).CStr()); + if (_codec_init_event.Get() == false) + { + _kill_flag = false; + + return false; + } } catch (const std::system_error &e) { @@ -222,8 +227,15 @@ void FilterResampler::Stop() void FilterResampler::WorkerThread() { + if(_codec_init_event.Submit(Configure(_input_track, _output_track)) == false) + { + return; + } + int ret; + SetState(State::STARTED); + while (!_kill_flag) { auto obj = _input_buffer.Dequeue(); diff --git a/src/projects/transcoder/filter/filter_rescaler.cpp b/src/projects/transcoder/filter/filter_rescaler.cpp index 8871093fb..8e75fb305 100644 --- a/src/projects/transcoder/filter/filter_rescaler.cpp +++ b/src/projects/transcoder/filter/filter_rescaler.cpp @@ -360,13 +360,19 @@ bool FilterRescaler::Configure(const std::shared_ptr &input_track, c bool FilterRescaler::Start() { - // Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. try { _kill_flag = false; _thread_work = std::thread(&FilterRescaler::WorkerThread, this); - pthread_setname_np(_thread_work.native_handle(), "Rescaler"); + pthread_setname_np(_thread_work.native_handle(), ov::String::FormatString("FLT-rscl-t%u", _output_track->GetId()).CStr()); + + if (_codec_init_event.Get() == false) + { + _kill_flag = false; + + return false; + } } catch (const std::system_error &e) { @@ -510,6 +516,11 @@ bool FilterRescaler::PopProcess() void FilterRescaler::WorkerThread() { + if(_codec_init_event.Submit(Configure(_input_track, _output_track)) == false) + { + return; + } + SetState(State::STARTED); #if _SKIP_FRAMES_ENABLED diff --git a/src/projects/transcoder/transcoder_context.h b/src/projects/transcoder/transcoder_context.h index a34a635a9..c5acdc61d 100644 --- a/src/projects/transcoder/transcoder_context.h +++ b/src/projects/transcoder/transcoder_context.h @@ -173,8 +173,6 @@ class MediaFrame return _flags; } - // 데이터를 빈값으로 채움 - // FillZero void FillZeroData() { if(!_priv_data) { diff --git a/src/projects/transcoder/transcoder_decoder.cpp b/src/projects/transcoder/transcoder_decoder.cpp index 7efbd2b95..157781bf1 100644 --- a/src/projects/transcoder/transcoder_decoder.cpp +++ b/src/projects/transcoder/transcoder_decoder.cpp @@ -9,17 +9,17 @@ #include "transcoder_decoder.h" #include "codec/decoder/decoder_aac.h" -#include "codec/decoder/decoder_mp3.h" #include "codec/decoder/decoder_avc.h" +#include "codec/decoder/decoder_avc_nilogan.h" #include "codec/decoder/decoder_avc_nv.h" #include "codec/decoder/decoder_avc_qsv.h" -#include "codec/decoder/decoder_avc_nilogan.h" #include "codec/decoder/decoder_avc_xma.h" #include "codec/decoder/decoder_hevc.h" +#include "codec/decoder/decoder_hevc_nilogan.h" #include "codec/decoder/decoder_hevc_nv.h" #include "codec/decoder/decoder_hevc_qsv.h" -#include "codec/decoder/decoder_hevc_nilogan.h" #include "codec/decoder/decoder_hevc_xma.h" +#include "codec/decoder/decoder_mp3.h" #include "codec/decoder/decoder_opus.h" #include "codec/decoder/decoder_vp8.h" #include "transcoder_gpu.h" @@ -31,12 +31,13 @@ std::shared_ptr>> TranscodeDecoder::GetCandidates(bool hwaccels_enable, ov::String hwaccles_modules, std::shared_ptr track) { - logtd("Codec(%s), HWAccels.Enable(%s), HWAccels.Modules(%s)", GetCodecIdToString(track->GetCodecId()).CStr(), hwaccels_enable?"true":"falase", hwaccles_modules.CStr()); + logtd("Codec(%s), HWAccels.Enable(%s), HWAccels.Modules(%s)", + GetCodecIdToString(track->GetCodecId()).CStr(), hwaccels_enable ? "true" : "falase", hwaccles_modules.CStr()); ov::String configuration = ""; std::shared_ptr>> candidate_modules = std::make_shared>>(); - if(hwaccels_enable == true) + if (hwaccels_enable == true) { configuration = hwaccles_modules.Trim(); } @@ -59,7 +60,7 @@ std::shared_ptr>> TranscodeDecoder:: if (desire_modules.size() == 0 || configuration.IsEmpty() == true) { desire_modules.clear(); - if( hwaccels_enable == true) + if (hwaccels_enable == true) { desire_modules.push_back(ov::String::FormatString("%s:%d", "XMA", ALL_GPU_ID)); desire_modules.push_back(ov::String::FormatString("%s:%d", "NV", ALL_GPU_ID)); @@ -70,33 +71,34 @@ std::shared_ptr>> TranscodeDecoder:: desire_modules.push_back(ov::String::FormatString("%s:%d", DEFAULT_MODULE_NAME, ALL_GPU_ID)); } - for(auto &desire_module : desire_modules) + for (auto &desire_module : desire_modules) { // Pattern : : or - ov::Regex pattern_regex = ov::Regex::CompiledRegex( "(?[^,:\\s]+[\\w]+):?(?[^,]*)"); + ov::Regex pattern_regex = ov::Regex::CompiledRegex("(?[^,:\\s]+[\\w]+):?(?[^,]*)"); auto matches = pattern_regex.Matches(desire_module.CStr()); if (matches.GetError() != nullptr || matches.IsMatched() == false) { logtw("Incorrect pattern in the Modules item. module(%s)", desire_module.CStr()); - - continue;; + + continue; + ; } - auto named_group = matches.GetNamedGroupList(); + auto named_group = matches.GetNamedGroupList(); - auto module_name = named_group["module_name"].GetValue(); - auto gpu_id = named_group["gpu_id"].GetValue().IsEmpty()?ALL_GPU_ID:ov::Converter::ToInt32(named_group["gpu_id"].GetValue()); + auto module_name = named_group["module_name"].GetValue(); + auto gpu_id = named_group["gpu_id"].GetValue().IsEmpty() ? ALL_GPU_ID : ov::Converter::ToInt32(named_group["gpu_id"].GetValue()); // If Unknown module name, skip. cmn::MediaCodecModuleId module_id = cmn::GetCodecModuleIdByName(module_name); - if(module_id == cmn::MediaCodecModuleId::None) + if (module_id == cmn::MediaCodecModuleId::None) { logtw("Unknown codec module. name(%s)", module_name.CStr()); continue; } // If hardware usage is enabled, check if the module is supported. - if(hwaccels_enable == true) + if (hwaccels_enable == true) { for (int i = 0; i < TranscodeGPU::GetInstance()->GetDeviceCount(module_id); i++) { @@ -107,17 +109,17 @@ std::shared_ptr>> TranscodeDecoder:: } } - // - if(module_id == cmn::MediaCodecModuleId::DEFAULT) + // + if (module_id == cmn::MediaCodecModuleId::DEFAULT) { candidate_modules->push_back(std::make_shared(track->GetCodecId(), module_id, 0)); - } + } } - + for (auto &candidate : *candidate_modules) { (void)(candidate); - + logtd("Candidate module: %s(%d), %s(%d):%d", cmn::GetCodecIdToString(candidate->GetCodecId()).CStr(), candidate->GetCodecId(), @@ -129,25 +131,28 @@ std::shared_ptr>> TranscodeDecoder:: return candidate_modules; } -#define CASE_CREATE_CODEC_IFNEED(MODULE_ID, CLS) \ - case cmn::MediaCodecModuleId::MODULE_ID: \ - decoder = std::make_shared(info); \ - if (decoder == nullptr) \ - { \ - break; \ - } \ +#define CASE_CREATE_CODEC_IFNEED(MODULE_ID, CLS) \ + case cmn::MediaCodecModuleId::MODULE_ID: \ + decoder = std::make_shared(*info); \ + if (decoder == nullptr) \ + { \ + break; \ + } \ track->SetCodecDeviceId(candidate->GetDeviceId()); \ - if (decoder->Configure(track) == true) \ - { \ - goto done; \ - } \ - if (decoder != nullptr) { decoder->Stop(); decoder = nullptr; } \ - break; \ - + if (decoder->Configure(track) == true) \ + { \ + goto done; \ + } \ + if (decoder != nullptr) \ + { \ + decoder->Stop(); \ + decoder = nullptr; \ + } \ + break; std::shared_ptr TranscodeDecoder::Create( int32_t decoder_id, - const info::Stream &info, + std::shared_ptr info, std::shared_ptr track, std::shared_ptr>> candidates, CompleteHandler complete_handler) @@ -191,9 +196,9 @@ std::shared_ptr TranscodeDecoder::Create( switch (candidate->GetModuleId()) { default: - CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderVP8) + CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderVP8) - break; + break; } } else if (candidate->GetCodecId() == cmn::MediaCodecId::Aac) @@ -201,7 +206,7 @@ std::shared_ptr TranscodeDecoder::Create( switch (candidate->GetModuleId()) { default: - CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderAAC) + CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderAAC) break; } } @@ -210,8 +215,8 @@ std::shared_ptr TranscodeDecoder::Create( switch (candidate->GetModuleId()) { default: - CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderOPUS) - break; + CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderOPUS) + break; } } else if (candidate->GetCodecId() == cmn::MediaCodecId::Mp3) @@ -219,10 +224,10 @@ std::shared_ptr TranscodeDecoder::Create( switch (candidate->GetModuleId()) { default: - CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderMP3) - break; + CASE_CREATE_CODEC_IFNEED(DEFAULT, DecoderMP3) + break; } - } + } else { OV_ASSERT(false, "Not supported codec: %d", track->GetCodecId()); @@ -240,10 +245,10 @@ std::shared_ptr TranscodeDecoder::Create( decoder->SetCompleteHandler(complete_handler); logti("The decoder has been created successfully. track(#%d) codec(%s), module(%s:%d)", - track->GetId(), - cmn::GetCodecIdToString(track->GetCodecId()).CStr(), - cmn::GetStringFromCodecModuleId(track->GetCodecModuleId()).CStr(), - track->GetCodecDeviceId()); + track->GetId(), + cmn::GetCodecIdToString(track->GetCodecId()).CStr(), + cmn::GetStringFromCodecModuleId(track->GetCodecModuleId()).CStr(), + track->GetCodecDeviceId()); } return decoder; @@ -312,9 +317,13 @@ void TranscodeDecoder::SetDecoderId(int32_t decoder_id) bool TranscodeDecoder::Configure(std::shared_ptr track) { + if (track == nullptr) + { + return false; + } _track = track; - auto name = ov::String::FormatString("decoder_%s_%d", ::avcodec_get_name(GetCodecID()), _track->GetId()); + auto name = ov::String::FormatString("dec_%s_%d", ::avcodec_get_name(GetCodecID()), _track->GetId()); auto urn = std::make_shared( _stream_info.GetApplicationInfo().GetVHostAppName(), _stream_info.GetName(), @@ -323,24 +332,27 @@ bool TranscodeDecoder::Configure(std::shared_ptr track) _input_buffer.SetUrn(urn); _input_buffer.SetThreshold(MAX_QUEUE_SIZE); + _kill_flag = false; + try + { + _codec_thread = std::thread(&TranscodeDecoder::CodecThread, this); + pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("DEC-%s-t%u", avcodec_get_name(GetCodecID()), _track->GetId()).CStr()); - return (_track != nullptr); -} - -void TranscodeDecoder::SendBuffer(std::shared_ptr packet) -{ - _input_buffer.Enqueue(std::move(packet)); -} - -void TranscodeDecoder::Complete(TranscodeResult result, std::shared_ptr frame) -{ - // Invoke callback function when encoding/decoding is completed. - if (_complete_handler) + // Initialize the codec and wait for completion. + if (_codec_init_event.Get() == false) + { + _kill_flag = true; + return false; + } + } + catch (const std::system_error &e) { - frame->SetTrackId(_decoder_id); - _complete_handler(result, _decoder_id, std::move(frame)); + _kill_flag = true; + return false; } + + return true; } void TranscodeDecoder::Stop() @@ -355,4 +367,24 @@ void TranscodeDecoder::Stop() logtd(ov::String::FormatString("decoder %s thread has ended", avcodec_get_name(GetCodecID())).CStr()); } -} \ No newline at end of file +} + +void TranscodeDecoder::SendBuffer(std::shared_ptr packet) +{ + _input_buffer.Enqueue(std::move(packet)); +} + +void TranscodeDecoder::SetCompleteHandler(CompleteHandler complete_handler) +{ + _complete_handler = move(complete_handler); +} + +void TranscodeDecoder::Complete(TranscodeResult result, std::shared_ptr frame) +{ + // Invoke callback function when encoding/decoding is completed. + if (_complete_handler) + { + frame->SetTrackId(_decoder_id); + _complete_handler(result, _decoder_id, std::move(frame)); + } +} diff --git a/src/projects/transcoder/transcoder_decoder.h b/src/projects/transcoder/transcoder_decoder.h index 13e717651..113ad0080 100644 --- a/src/projects/transcoder/transcoder_decoder.h +++ b/src/projects/transcoder/transcoder_decoder.h @@ -21,45 +21,38 @@ class TranscodeDecoder : public TranscodeBase ~TranscodeDecoder() override; static std::shared_ptr>> GetCandidates(bool hwaccels_enable, ov::String hwaccles_moduels, std::shared_ptr track); - static std::shared_ptr Create(int32_t decoder_id, const info::Stream &info, std::shared_ptr track, std::shared_ptr>> candidates, CompleteHandler complete_handler); + static std::shared_ptr Create(int32_t decoder_id, std::shared_ptr info, std::shared_ptr track, std::shared_ptr>> candidates, CompleteHandler complete_handler); void SetDecoderId(int32_t decoder_id); - - bool Configure(std::shared_ptr track) override; - - void SendBuffer(std::shared_ptr packet) override; - void Complete(TranscodeResult result, std::shared_ptr frame); - std::shared_ptr &GetRefTrack(); - cmn::Timebase GetTimebase(); + void SetCompleteHandler(CompleteHandler complete_handler); + void Complete(TranscodeResult result, std::shared_ptr frame); - virtual void CodecThread() = 0; + bool Configure(std::shared_ptr track) override; + void SendBuffer(std::shared_ptr packet) override; + virtual void CodecThread() = 0; virtual void Stop(); - void SetCompleteHandler(CompleteHandler complete_handler) - { - _complete_handler = move(complete_handler); - } - protected: int32_t _decoder_id; int32_t _gpu_id = -1; + info::Stream _stream_info; std::shared_ptr _track; AVCodecContext *_context = nullptr; AVCodecParserContext *_parser = nullptr; AVCodecParameters *_codec_par = nullptr; + ov::Future _codec_init_event; + bool _change_format = false; AVPacket *_pkt; AVFrame *_frame; - info::Stream _stream_info; - bool _kill_flag = false; std::thread _codec_thread; diff --git a/src/projects/transcoder/transcoder_encoder.cpp b/src/projects/transcoder/transcoder_encoder.cpp index 7b001abc7..79902aed8 100644 --- a/src/projects/transcoder/transcoder_encoder.cpp +++ b/src/projects/transcoder/transcoder_encoder.cpp @@ -153,7 +153,7 @@ std::shared_ptr>> TranscodeEncoder:: #define CASE_CREATE_CODEC_IFNEED(MODULE_ID, CLS) \ case cmn::MediaCodecModuleId::MODULE_ID: \ - encoder = std::make_shared(info); \ + encoder = std::make_shared(*info); \ if (encoder == nullptr) \ { \ break; \ @@ -168,7 +168,7 @@ std::shared_ptr>> TranscodeEncoder:: std::shared_ptr TranscodeEncoder::Create( int32_t encoder_id, - const info::Stream &info, + std::shared_ptr info, std::shared_ptr track, std::shared_ptr>> candidates, CompleteHandler complete_handler) @@ -338,7 +338,7 @@ bool TranscodeEncoder::Configure(std::shared_ptr output_track) _track = output_track; _track->SetOriginBitstream(GetBitstreamFormat()); - auto name = ov::String::FormatString("encoder_%s_%d", ::avcodec_get_name(GetCodecID()), _track->GetId()); + auto name = ov::String::FormatString("enc_%s_%d", ::avcodec_get_name(GetCodecID()), _track->GetId()); auto urn = std::make_shared( _stream_info.GetApplicationInfo().GetVHostAppName(), _stream_info.GetName(), @@ -362,6 +362,7 @@ bool TranscodeEncoder::Configure(std::shared_ptr output_track) return (_track != nullptr); } + std::shared_ptr &TranscodeEncoder::GetRefTrack() { return _track; @@ -407,6 +408,12 @@ void TranscodeEncoder::Stop() void TranscodeEncoder::CodecThread() { + // Initialize the codec and notify the main thread. + if(_codec_init_event.Submit(InitCodec()) == false) + { + return; + } + if ((GetRefTrack()->GetMediaType() == cmn::MediaType::Video) && (GetRefTrack()->GetKeyFrameIntervalTypeByConfig() == cmn::KeyFrameIntervalType::TIME)) { diff --git a/src/projects/transcoder/transcoder_encoder.h b/src/projects/transcoder/transcoder_encoder.h index ab899e81c..680f761f8 100644 --- a/src/projects/transcoder/transcoder_encoder.h +++ b/src/projects/transcoder/transcoder_encoder.h @@ -16,37 +16,40 @@ class TranscodeEncoder : public TranscodeBase public: typedef std::function)> CompleteHandler; static std::shared_ptr>> GetCandidates(bool hwaccels_enable, ov::String hwaccles_modules, std::shared_ptr track); - static std::shared_ptr Create(int32_t encoder_id, const info::Stream &info, std::shared_ptr output_track, std::shared_ptr>> candidates, CompleteHandler complete_handler); + static std::shared_ptr Create(int32_t encoder_id, std::shared_ptr info, std::shared_ptr output_track, std::shared_ptr>> candidates, CompleteHandler complete_handler); public: TranscodeEncoder(info::Stream stream_info); ~TranscodeEncoder() override; void SetEncoderId(int32_t encoder_id); + void SetCompleteHandler(CompleteHandler complete_handler); + void Complete(std::shared_ptr packet); + std::shared_ptr &GetRefTrack(); + cmn::Timebase GetTimebase() const; + virtual int GetSupportedFormat() const noexcept = 0; virtual cmn::BitstreamFormat GetBitstreamFormat() const noexcept = 0; - bool Configure(std::shared_ptr output_track) override; - void SendBuffer(std::shared_ptr frame) override; - void Complete(std::shared_ptr packet); + virtual bool InitCodec() = 0; virtual void CodecThread(); virtual void Stop(); - void SetCompleteHandler(CompleteHandler complete_handler); - - std::shared_ptr &GetRefTrack(); - cmn::Timebase GetTimebase() const; - -private: virtual bool SetCodecParams() = 0; + bool Configure(std::shared_ptr output_track) override; + void SendBuffer(std::shared_ptr frame) override; + protected: - std::shared_ptr _track = nullptr; - int32_t _encoder_id; + info::Stream _stream_info; + std::shared_ptr _track = nullptr; + AVCodecContext *_codec_context = nullptr; AVCodecParserContext *_parser = nullptr; AVCodecParameters *_codec_par = nullptr; + ov::Future _codec_init_event; + bool _change_format = false; AVPacket *_packet = nullptr; @@ -54,8 +57,6 @@ class TranscodeEncoder : public TranscodeBase cmn::BitstreamFormat _bitstream_format = cmn::BitstreamFormat::Unknown; cmn::PacketType _packet_type = cmn::PacketType::Unknown; - info::Stream _stream_info; - bool _kill_flag = false; std::thread _codec_thread; diff --git a/src/projects/transcoder/transcoder_filter.cpp b/src/projects/transcoder/transcoder_filter.cpp index 128f1b143..b64189b31 100644 --- a/src/projects/transcoder/transcoder_filter.cpp +++ b/src/projects/transcoder/transcoder_filter.cpp @@ -68,14 +68,8 @@ bool TranscodeFilter::Create() name.LowerCaseString()); _internal->SetQueueUrn(urn); _internal->SetCompleteHandler(bind(&TranscodeFilter::OnComplete, this, std::placeholders::_1)); - - bool success = _internal->Configure(_input_track, _output_track); - if (success == false) - { - logte("Could not create filter"); - - return false; - } + _internal->SetInputTrack(_input_track); + _internal->SetOutputTrack(_output_track); return _internal->Start(); } diff --git a/src/projects/transcoder/transcoder_stream.cpp b/src/projects/transcoder/transcoder_stream.cpp index 1bc272322..4fd11b40e 100644 --- a/src/projects/transcoder/transcoder_stream.cpp +++ b/src/projects/transcoder/transcoder_stream.cpp @@ -814,7 +814,7 @@ bool TranscoderStream::CreateDecoder(MediaTrackId decoder_id, std::shared_ptr