summaryrefslogtreecommitdiff
path: root/src/gstreamer
AgeCommit message (Expand)Author
2021-08-05gstreamer: Update format specifier in Request Pad templateVedant Paranjape
2021-07-28gstreamer: Store group_id in GstLibcameraSrcStateVedant Paranjape
2021-06-25libcamera: rename public libcamera dependencyKieran Bingham
2021-06-25gstreamer: Added virtual functions needed to support request padsVedant Paranjape
2021-06-07gstreamer: Add error checking in gst_libcamera_src_task_enter()Vedant Paranjape
2021-05-31gst: Fix compilation warning with GLib >= 2.62Laurent Pinchart
2021-03-28meson: Summarize which applications and adaptation layers are builtLaurent Pinchart
2021-03-23meson: Use subdir_done() to reduce indentationLaurent Pinchart
2021-03-15gst: Use the streams of CameraConfiguration when allocating buffersDafna Hirschfeld
2021-03-12libcamera: gst: Fix double-free when acquire_buffer failsMarian Cichy
2021-03-12gst: pool: Fix GstBuffer leak on errorNicolas Dufresne
2021-03-12gst: provider: Fix crash in finalizeNicolas Dufresne
2021-02-11meson: Fix coding style when declaring arraysLaurent Pinchart
2020-11-07gstreamer: libcamerasrc: Delete configuration before stopping camera managerLaurent Pinchart
2020-10-20gstreamer: Omit extra semicolonsHirokazu Honda
2020-10-12libcamera, android, cam, gstreamer, qcam, v4l2: Reuse RequestPaul Elder
2020-08-25meson: Remove -Wno-unused-parameterLaurent Pinchart
2020-08-25libcamera: Remove void specifier for functions that take no argumentsLaurent Pinchart
2020-08-05libcamera: camera: Rename name() to id()Niklas Söderlund
2020-06-18gst: Replace explicit DRM FourCCs with libcamera formatsLaurent Pinchart
2020-05-13licenses: License all meson files under CC0-1.0Laurent Pinchart
2020-03-18libcamera: framebuffer_allocator: Lift camera restrictions on allocatorLaurent Pinchart
2020-03-18libcamera: PixelFormat: Make constructor explicitLaurent Pinchart
2020-03-18libcamera: Use PixelFormat instead of unsigned int where appropriateNiklas Söderlund
2020-03-07gst: Fix GLib detectionLaurent Pinchart
2020-03-07gst: Turn the top-level plugin file gstlibcamera.c into a C++ fileLaurent Pinchart
2020-03-07gst: libcamerasrc: Prevent src task deadlock on exhausted buffer poolJakub Adam
2020-03-07gst: utils: Factor-out the task resume helperJakub Adam
2020-03-07gst: libcamerasrc: Add a TODO commentNicolas Dufresne
2020-03-07gst: libcamerasrc: Implement timestamp supportNicolas Dufresne
2020-03-07gst: libcamerasrc: Implement initial streamingNicolas Dufresne
2020-03-07gst: pad: Add method to store retrieve pending buffersNicolas Dufresne
2020-03-07gst: Add getters for Stream and FrameBufferNicolas Dufresne
2020-03-07gst: libcamerasrc: Allocate and release buffersNicolas Dufresne
2020-03-07gst: libcamerapad: Allow storing a poolNicolas Dufresne
2020-03-07gst: Add a pool and an allocator implementationNicolas Dufresne
2020-03-07gst: libcamerasrc: Push segment eventNicolas Dufresne
2020-03-07gst: libcamerasrc: Implement minimal caps negotiationNicolas Dufresne
2020-03-07gst: utils: Add StreamConfiguration helpersNicolas Dufresne
2020-03-07gst: libcamerasrc: Send stream start eventNicolas Dufresne
2020-03-07gst: libcamerasrc: Store the srcpad in a vectorNicolas Dufresne
2020-03-07gst: libcamerapad: Add a method to access the roleNicolas Dufresne
2020-03-07gst: libcamerasrc: Add a task for the streaming threadNicolas Dufresne
2020-03-07gst: libcamerasrc: Implement selection and acquisitionNicolas Dufresne
2020-03-07gst: libcamerasrc: Add a debug categoryNicolas Dufresne
2020-03-07gst: libcamerasrc: Add camera-name propertyNicolas Dufresne
2020-03-07gst: libcamerasrc: Allocate and add static padNicolas Dufresne
2020-03-07gst: Add pads to the sourceNicolas Dufresne
2020-03-07gst: utils: Add simple scoped lockers for GMutex and GRectMutexNicolas Dufresne
2020-03-07gst: Add initial device providerNicolas Dufresne
s="hl ppc">#include "../common/event_loop.h" #include "../common/options.h" #include "../common/stream_options.h" #include "camera_session.h" #include "main.h" using namespace libcamera; class CamApp { public: CamApp(); static CamApp *instance(); int init(int argc, char **argv); void cleanup(); int exec(); void quit(); private: void cameraAdded(std::shared_ptr<Camera> cam); void cameraRemoved(std::shared_ptr<Camera> cam); void captureDone(); int parseOptions(int argc, char *argv[]); int run(); static std::string cameraName(const Camera *camera); static CamApp *app_; OptionsParser::Options options_; std::unique_ptr<CameraManager> cm_; std::atomic_uint loopUsers_; EventLoop loop_; }; CamApp *CamApp::app_ = nullptr; CamApp::CamApp() : loopUsers_(0) { CamApp::app_ = this; } CamApp *CamApp::instance() { return CamApp::app_; } int CamApp::init(int argc, char **argv) { int ret; ret = parseOptions(argc, argv); if (ret < 0) return ret; cm_ = std::make_unique<CameraManager>(); ret = cm_->start(); if (ret) { std::cout << "Failed to start camera manager: " << strerror(-ret) << std::endl; return ret; } return 0; } void CamApp::cleanup() { cm_->stop(); } int CamApp::exec() { int ret; ret = run(); cleanup(); return ret; } void CamApp::quit() { loop_.exit(); } int CamApp::parseOptions(int argc, char *argv[]) { StreamKeyValueParser streamKeyValue; OptionsParser parser; parser.addOption(OptCamera, OptionString, "Specify which camera to operate on, by id or by index", "camera", ArgumentRequired, "camera", true); parser.addOption(OptHelp, OptionNone, "Display this help message", "help"); parser.addOption(OptInfo, OptionNone, "Display information about stream(s)", "info"); parser.addOption(OptList, OptionNone, "List all cameras", "list"); parser.addOption(OptListControls, OptionNone, "List cameras controls", "list-controls"); parser.addOption(OptListProperties, OptionNone, "List cameras properties", "list-properties"); parser.addOption(OptMonitor, OptionNone, "Monitor for hotplug and unplug camera events", "monitor"); /* Sub-options of OptCamera: */ parser.addOption(OptCapture, OptionInteger, "Capture until interrupted by user or until <count> frames captured", "capture", ArgumentOptional, "count", false, OptCamera); parser.addOption(OptOrientation, OptionString, "Desired image orientation (rot0, rot180, mirror, flip)", "orientation", ArgumentRequired, "orientation", false, OptCamera); #ifdef HAVE_KMS parser.addOption(OptDisplay, OptionString, "Display viewfinder through DRM/KMS on specified connector", "display", ArgumentOptional, "connector", false, OptCamera); #endif parser.addOption(OptFile, OptionString, "Write captured frames to disk\n" "If the file name ends with a '/', it sets the directory in which\n" "to write files, using the default file name. Otherwise it sets the\n" "full file path and name. The first '#' character in the file name\n" "is expanded to the camera index, stream name and frame sequence number.\n" #ifdef HAVE_TIFF "If the file name ends with '.dng', then the frame will be written to\n" "the output file(s) in DNG format.\n" #endif "The default file name is 'frame-#.bin'.", "file", ArgumentOptional, "filename", false, OptCamera); #ifdef HAVE_SDL parser.addOption(OptSDL, OptionNone, "Display viewfinder through SDL", "sdl", ArgumentNone, "", false, OptCamera); #endif parser.addOption(OptStream, &streamKeyValue, "Set configuration of a camera stream", "stream", true, OptCamera); parser.addOption(OptStrictFormats, OptionNone, "Do not allow requested stream format(s) to be adjusted", "strict-formats", ArgumentNone, nullptr, false, OptCamera); parser.addOption(OptMetadata, OptionNone, "Print the metadata for completed requests", "metadata", ArgumentNone, nullptr, false, OptCamera); parser.addOption(OptCaptureScript, OptionString, "Load a capture session configuration script from a file", "script", ArgumentRequired, "script", false, OptCamera); options_ = parser.parse(argc, argv); if (!options_.valid()) return -EINVAL; if (options_.empty() || options_.isSet(OptHelp)) { parser.usage(); return options_.empty() ? -EINVAL : -EINTR; } return 0; } void CamApp::cameraAdded(std::shared_ptr<Camera> cam) { std::cout << "Camera Added: " << cam->id() << std::endl; } void CamApp::cameraRemoved(std::shared_ptr<Camera> cam) { std::cout << "Camera Removed: " << cam->id() << std::endl; } void CamApp::captureDone() { if (--loopUsers_ == 0) EventLoop::instance()->exit(0); } int CamApp::run() { int ret; /* 1. List all cameras. */ if (options_.isSet(OptList)) { std::cout << "Available cameras:" << std::endl; unsigned int index = 1; for (const std::shared_ptr<Camera> &cam : cm_->cameras()) { std::cout << index << ": " << cameraName(cam.get()) << std::endl; index++; } } /* 2. Create the camera sessions. */ std::vector<std::unique_ptr<CameraSession>> sessions; if (options_.isSet(OptCamera)) { unsigned int index = 0; for (const OptionValue &camera : options_[OptCamera].toArray()) { std::unique_ptr<CameraSession> session = std::make_unique<CameraSession>(cm_.get(), camera.toString(), index, camera.children()); if (!session->isValid()) { std::cout << "Failed to create camera session" << std::endl; return -EINVAL; } std::cout << "Using camera " << session->camera()->id() << " as cam" << index << std::endl; session->captureDone.connect(this, &CamApp::captureDone); sessions.push_back(std::move(session)); index++; } } /* 3. Print camera information. */ if (options_.isSet(OptListControls) || options_.isSet(OptListProperties) || options_.isSet(OptInfo)) { for (const auto &session : sessions) { if (options_.isSet(OptListControls)) session->listControls(); if (options_.isSet(OptListProperties)) session->listProperties(); if (options_.isSet(OptInfo)) session->infoConfiguration(); } } /* 4. Start capture. */ for (const auto &session : sessions) { if (!session->options().isSet(OptCapture)) continue; ret = session->start(); if (ret) { std::cout << "Failed to start camera session" << std::endl; return ret; } loopUsers_++; } /* 5. Enable hotplug monitoring. */ if (options_.isSet(OptMonitor)) { std::cout << "Monitoring new hotplug and unplug events" << std::endl; std::cout << "Press Ctrl-C to interrupt" << std::endl; cm_->cameraAdded.connect(this, &CamApp::cameraAdded); cm_->cameraRemoved.connect(this, &CamApp::cameraRemoved); loopUsers_++; } if (loopUsers_) loop_.exec(); /* 6. Stop capture. */ for (const auto &session : sessions) { if (!session->options().isSet(OptCapture)) continue; session->stop(); } return 0; } std::string CamApp::cameraName(const Camera *camera) { const ControlList &props = camera->properties(); bool addModel = true; std::string name; /* * Construct the name from the camera location, model and ID. The model * is only used if the location isn't present or is set to External. */ const auto &location = props.get(properties::Location); if (location) { switch (*location) { case properties::CameraLocationFront: addModel = false; name = "Internal front camera "; break; case properties::CameraLocationBack: addModel = false; name = "Internal back camera "; break; case properties::CameraLocationExternal: name = "External camera "; break; } } if (addModel) { /* * If the camera location is not availble use the camera model * to build the camera name. */ const auto &model = props.get(properties::Model); if (model) name = "'" + *model + "' "; } name += "(" + camera->id() + ")"; return name; } void signalHandler([[maybe_unused]] int signal) { std::cout << "Exiting" << std::endl; CamApp::instance()->quit(); } int main(int argc, char **argv) { CamApp app; int ret; ret = app.init(argc, argv); if (ret) return ret == -EINTR ? 0 : EXIT_FAILURE; struct sigaction sa = {}; sa.sa_handler = &signalHandler; sigaction(SIGINT, &sa, nullptr); if (app.exec()) return EXIT_FAILURE; return 0; }