try to get ALSA device corresponding to V4L2

pull/74/merge
mpromonet 7 years ago
parent 87b4d5b541
commit 9d81304778

@ -18,6 +18,7 @@
#include <errno.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <sstream>
@ -104,15 +105,15 @@ RTSPServer* createRTSPServer(UsageEnvironment& env, unsigned short rtspPort, uns
// -----------------------------------------
// create FramedSource server
// -----------------------------------------
FramedSource* createFramedSource(UsageEnvironment* env, int format, DeviceInterface* videoCapture, int outfd, int queueSize, bool useThread, bool repeatConfig, bool muxTS)
FramedSource* createFramedSource(UsageEnvironment* env, int format, DeviceInterface* videoCapture, int outfd, int queueSize, bool useThread, bool repeatConfig, MPEG2TransportStreamFromESSource* muxer)
{
bool muxTS = (muxer != NULL);
FramedSource* source = NULL;
if (format == V4L2_PIX_FMT_H264)
{
source = H264_V4L2DeviceSource::createNew(*env, videoCapture, outfd, queueSize, useThread, repeatConfig, muxTS);
if (muxTS)
{
MPEG2TransportStreamFromESSource* muxer = MPEG2TransportStreamFromESSource::createNew(*env);
muxer->addNewVideoSource(source, 5);
source = muxer;
}
@ -122,7 +123,6 @@ FramedSource* createFramedSource(UsageEnvironment* env, int format, DeviceInterf
source = H265_V4L2DeviceSource::createNew(*env, videoCapture, outfd, queueSize, useThread, repeatConfig, muxTS);
if (muxTS)
{
MPEG2TransportStreamFromESSource* muxer = MPEG2TransportStreamFromESSource::createNew(*env);
muxer->addNewVideoSource(source, 6);
source = muxer;
}
@ -221,6 +221,10 @@ snd_pcm_format_t decodeAudioFormat(const std::string& fmt)
audioFmt = SND_PCM_FORMAT_S32_BE;
} else if (fmt == "S32_LE") {
audioFmt = SND_PCM_FORMAT_S32_LE;
} else if (fmt == "U8") {
audioFmt = SND_PCM_FORMAT_U8;
} else if (fmt == "S8") {
audioFmt = SND_PCM_FORMAT_S8;
}
return audioFmt;
}
@ -259,6 +263,95 @@ void decodeDevice(const std::string & device, std::string & videoDev, std::strin
getline(is, audioDev);
}
/* ---------------------------------------------------------------------------
** get a "deviceid" from uevent sys file
** -------------------------------------------------------------------------*/
#ifdef HAVE_ALSA
std::string getDeviceId(const std::string& evt) {
std::string deviceid;
std::istringstream f(evt);
std::string key;
while (getline(f, key, '=')) {
std::string value;
if (getline(f, value)) {
if ( (key =="PRODUCT") || (key == "PCI_SUBSYS_ID") ) {
deviceid = value;
break;
}
}
}
return deviceid;
}
std::string getV4l2Alsa(const std::string& v4l2device) {
std::string audioDevice(v4l2device);
std::map<std::string,std::string> videodevices;
std::string video4linuxPath("/sys/class/video4linux");
DIR *dp = opendir(video4linuxPath.c_str());
if (dp != NULL) {
struct dirent *entry = NULL;
while((entry = readdir(dp))) {
std::string devicename;
std::string deviceid;
if (strstr(entry->d_name,"video") == entry->d_name) {
std::string ueventPath(video4linuxPath);
ueventPath.append("/").append(entry->d_name).append("/device/uevent");
std::ifstream ifsd(ueventPath.c_str());
deviceid = std::string(std::istreambuf_iterator<char>{ifsd}, {});
deviceid.erase(deviceid.find_last_not_of("\n")+1);
}
if (!deviceid.empty()) {
videodevices[entry->d_name] = getDeviceId(deviceid);
}
}
closedir(dp);
}
std::map<std::string,std::string> audiodevices;
int rcard = -1;
while ( (snd_card_next(&rcard) == 0) && (rcard>=0) ) {
void **hints = NULL;
if (snd_device_name_hint(rcard, "pcm", &hints) >= 0) {
void **str = hints;
while (*str) {
std::ostringstream os;
os << "/sys/class/sound/card" << rcard << "/device/uevent";
std::ifstream ifs(os.str().c_str());
std::string deviceid = std::string(std::istreambuf_iterator<char>{ifs}, {});
deviceid.erase(deviceid.find_last_not_of("\n")+1);
deviceid = getDeviceId(deviceid);
if (!deviceid.empty()) {
if (audiodevices.find(deviceid) == audiodevices.end()) {
std::string audioname = snd_device_name_get_hint(*str, "NAME");
audiodevices[deviceid] = audioname;
}
}
str++;
}
snd_device_name_free_hint(hints);
}
}
auto deviceId = videodevices.find(basename(v4l2device.c_str()));
if (deviceId != videodevices.end()) {
auto audioDeviceIt = audiodevices.find(deviceId->second);
if (audioDeviceIt != audiodevices.end()) {
audioDevice = audioDeviceIt->second;
std::cout << v4l2device << "=>" << audioDevice << std::endl;
}
}
return audioDevice;
}
#endif
// -----------------------------------------
// entry point
@ -266,7 +359,7 @@ void decodeDevice(const std::string & device, std::string & videoDev, std::strin
int main(int argc, char** argv)
{
// default parameters
const char *dev_name = "/dev/video0,default";
const char *dev_name = "/dev/video0";
int format = V4L2_PIX_FMT_H264;
int width = 640;
int height = 480;
@ -441,8 +534,12 @@ int main(int argc, char** argv)
{
baseUrl = basename(videoDev.c_str());
baseUrl.append("/");
}
}
MPEG2TransportStreamFromESSource* muxer = NULL;
if (muxTS)
{
muxer = MPEG2TransportStreamFromESSource::createNew(*env);
}
StreamReplicator* videoReplicator = NULL;
std::string rtpFormat;
if (!videoDev.empty())
@ -468,7 +565,7 @@ int main(int argc, char** argv)
LOG(NOTICE) << "Create Source ..." << videoDev;
rtpFormat.assign(getRtpFormat(videoCapture->getFormat(), muxTS));
FramedSource* videoSource = createFramedSource(env, videoCapture->getFormat(), new DeviceCaptureAccess<V4l2Capture>(videoCapture), outfd, queueSize, useThread, repeatConfig, muxTS);
FramedSource* videoSource = createFramedSource(env, videoCapture->getFormat(), new DeviceCaptureAccess<V4l2Capture>(videoCapture), outfd, queueSize, useThread, repeatConfig, muxer);
if (videoSource == NULL)
{
LOG(FATAL) << "Unable to create source for device " << videoDev;
@ -492,6 +589,9 @@ int main(int argc, char** argv)
#ifdef HAVE_ALSA
if (!audioDev.empty())
{
// find the ALSA device associated with the V4L2 device
audioDev = getV4l2Alsa(audioDev);
// Init audio capture
LOG(NOTICE) << "Create ALSA Source..." << audioDev;

Loading…
Cancel
Save