gstreamer pipeline updates, pi bt updates. (#29)

* new services being added to openauto

* cmake for new services

* MediaStatusService, transitioning away from qt gstreamer

* Reverting change to qmlglsink as it's not functional on raspbian as of this moment

* Multitouch support within android auto

* add night mode toggle to aainterface

* Dot dump debug functionality

* NavigationStatusService, MediaStatusService, AAInterface, Hotkey migration

* Add a delay to dot dumping because caps aren't selected until data is streaming, so we can't rely on just a PLAYING status

* Update btservice connection method for pi4

* Update for pi4 compiling

* missing brace

* Yet another new bt connect process

* oops bad merge

* bad merge

* Remove pi specific bt connection

* Try to play nice with bullseye

* Select decoder automatically based on priority list

* Quick cleanup
This commit is contained in:
Cole Brinsfield 2022-07-12 22:46:00 -07:00 committed by GitHub
parent 8fa72b4f43
commit 6496f8e360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 36 deletions

View File

@ -43,20 +43,33 @@ btservice::btservice(openauto::configuration::IConfiguration::Pointer config)
void btservice::connectToBluetooth(QBluetoothAddress addr, QBluetoothAddress controller)
{
// Update 07-12-22, with bluez update and krnbt, raspberry pi is behaving as expected. For this reason
// the RPI specific code has been commented out. The commented out code (and comments below this one)
// exist as legacy now - in case there's a scenario where someone cannot update to krnbt or newer bluez.
// The raspberry pi has a really tough time using bluetoothctl (or really anything) to connect to an Android phone
// even though phone connecting to the pi is fine.
// I found a workaround where you can make the pi attempt an rfcomm connection to the phone, and it connects immediately
// This might require setting u+s on rfcomm though
// Other computers with more sane bluetooth shouldn't have an issue using bluetoothctl
// Update 01-10-21, latest firmware/package updates seem to have made bluetoothctl more stable
// and it won't drop a connection anymore. Only issue, is that the connection will fail
// if the desired target hasn't been "seen" yet
// we can use hcitool to force the pi to recognize that we're trying to connect to a valid device.
// this causes the target device to be "seen"
// bluetoothctl can then connect as normal.
// Why don't we just use rfcomm (as we had previously on pis)? Because an rfcomm initiated connection doesn't connect HFP, which breaks the use of
// pi mic/speakers for android auto phone calls. bluetoothctl will connect all profiles.
#ifdef RPI
// tries to open an rfcomm serial on channel 2
// channel doesn't really matter here, 2 is just "somewhat standard"
QString program = QString::fromStdString("sudo stdbuf -oL rfcomm connect hci0 ")+addr.toString()+QString::fromStdString(" 2");
btConnectProcess = new QProcess();
OPENAUTO_LOG(info)<<"[btservice] Attempting to connect to last bluetooth device, "<<addr.toString().toStdString()<<" with `"<<program.toStdString();
btConnectProcess->start(program, QProcess::Unbuffered | QProcess::ReadWrite);
#else
// QString program = QString::fromStdString("sudo hcitool cc ")+addr.toString();
// btConnectProcess = new QProcess();
// OPENAUTO_LOG(info)<<"[btservice] Attempting to connect to last bluetooth device, "<<addr.toString().toStdString()<<" using hcitool/bluetoothctl hybrid";
// btConnectProcess->start(program, QProcess::Unbuffered | QProcess::ReadWrite);
// btConnectProcess->waitForFinished();
#endif
btConnectProcess = new QProcess();
btConnectProcess->setProcessChannelMode(QProcess::SeparateChannels);
OPENAUTO_LOG(info)<<"[btservice] Attempting to connect to last bluetooth device, "<<addr.toString().toStdString()<<" with bluetoothctl";
@ -66,9 +79,6 @@ void btservice::connectToBluetooth(QBluetoothAddress addr, QBluetoothAddress con
btConnectProcess->write(QString("connect %1\n").arg(addr.toString()).toUtf8());
btConnectProcess->closeWriteChannel();
btConnectProcess->waitForFinished();
#endif
}
}
}
}

View File

@ -51,6 +51,46 @@ namespace openauto
namespace projection
{
// enum of possible h264 decoders dash will attempt to use
enum H264_Decoder {
nvcodec,
v4l2,
omx,
vaapi,
libav,
unknown
};
// order of priority for decoders - dash will use the first decoder it can find in this list
// for sake of the code, don't include "unknown" as a decoder to search for - this is the default case.
const H264_Decoder H264_Decoder_Priority_List[] = { nvcodec, v4l2, omx, libav };
// A map of enum to actual pad name we want to use
inline const char* ToString(H264_Decoder v)
{
switch (v)
{
case nvcodec: return "nvh264dec";
case v4l2: return "v4l2h264dec";
case omx: return "omxh264dec";
case libav: return "avdec_h264";
default: return "unknown";
}
}
// A map of enum to pipeline steps to insert (because for some we need some video converting)
inline const char* ToPipeline(H264_Decoder v)
{
switch (v)
{
// we're going to assume that any machine with an nvidia card has a cpu powerful enough for video convert.
case nvcodec: return "nvh264dec ! videoconvert";
case v4l2: return "v4l2h264dec";
case omx: return "omxh264dec";
case libav: return "avdec_h264";
default: return "unknown";
}
}
class GSTVideoOutput: public QObject, public VideoOutput, boost::noncopyable
{
Q_OBJECT
@ -77,6 +117,7 @@ public slots:
private:
static GstPadProbeReturn convertProbe(GstPad* pad, GstPadProbeInfo* info, void*);
static gboolean busCallback(GstBus*, GstMessage* message, gpointer*);
H264_Decoder findPreferredVideoDecoder();
bool firstHeaderParsed = false;

View File

@ -33,7 +33,6 @@ namespace openauto
namespace projection
{
GSTVideoOutput::GSTVideoOutput(configuration::IConfiguration::Pointer configuration, QWidget* videoContainer, std::function<void(bool)> activeCallback)
: VideoOutput(std::move(configuration))
, videoContainer_(videoContainer)
@ -49,28 +48,13 @@ GSTVideoOutput::GSTVideoOutput(configuration::IConfiguration::Pointer configurat
videoSink_ = surface_->videoSink();
GError* error = nullptr;
const char* vidLaunchStr = "appsrc name=mysrc is-live=true block=false max-latency=100 do-timestamp=true stream-type=stream ! queue ! h264parse ! "
#ifdef RPI
#ifdef PI4
"v4l2h264dec ! "
#else
"omxh264dec ! "
#endif
#else
"avdec_h264 ! "
#endif
"videocrop top=0 bottom=0 name=videocropper ! capsfilter caps=video/x-raw name=mycapsfilter";
#ifdef RPI
OPENAUTO_LOG(info) << "[GSTVideoOutput] RPI Build, running with " <<
#ifdef PI4
"v4l2h264dec";
#else
"omxh264dec";
#endif
#endif
vidPipeline_ = gst_parse_launch(vidLaunchStr, &error);
GError* error = nullptr;
std::string vidLaunchStr = "appsrc name=mysrc is-live=true block=false max-latency=100 do-timestamp=true stream-type=stream ! queue ! h264parse ! capssetter caps=\"video/x-h264,colorimetry=bt709\" ! ";
vidLaunchStr += ToPipeline(findPreferredVideoDecoder());
vidLaunchStr += " ! videocrop top=0 bottom=0 name=videocropper ! capsfilter caps=video/x-raw name=mycapsfilter";
vidPipeline_ = gst_parse_launch(vidLaunchStr.c_str(), &error);
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(vidPipeline_));
gst_bus_add_watch(bus, (GstBusFunc)&GSTVideoOutput::busCallback, this);
gst_object_unref(bus);
@ -99,11 +83,25 @@ GSTVideoOutput::~GSTVideoOutput()
gst_object_unref(vidSrc_);
}
void GSTVideoOutput::dumpDot(){
H264_Decoder GSTVideoOutput::findPreferredVideoDecoder()
{
for (H264_Decoder decoder : H264_Decoder_Priority_List) {
GstElementFactory *decoder_factory = gst_element_factory_find (ToString(decoder));
if(decoder_factory != nullptr){
gst_object_unref(decoder_factory);
OPENAUTO_LOG(info) << "[GSTVideoOutput] Selecting the " << ToString(decoder) << " h264 decoder";
return decoder;
}
}
OPENAUTO_LOG(error) << "[GSTVideoOutput] Couldn't find a decoder to use!";
return H264_Decoder::unknown;
}
void GSTVideoOutput::dumpDot()
{
gst_debug_bin_to_dot_file(GST_BIN(vidPipeline_), GST_DEBUG_GRAPH_SHOW_VERBOSE, "pipeline");
OPENAUTO_LOG(info) << "[GSTVideoOutput] Dumped dot debug info";
}
gboolean GSTVideoOutput::busCallback(GstBus*, GstMessage* message, gpointer*)