Advertisement
Guest User

camera.py

a guest
Mar 19th, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 18.43 KB | None | 0 0
  1. #!/system/bin/env python
  2.  
  3.  
  4. #############################################################################
  5. ##
  6. ## Copyright (C) 2013 Riverbank Computing Limited.
  7. ## Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  8. ## All rights reserved.
  9. ##
  10. ## This file is part of the examples of PyQt.
  11. ##
  12. ## $QT_BEGIN_LICENSE:BSD$
  13. ## You may use this file under the terms of the BSD license as follows:
  14. ##
  15. ## "Redistribution and use in source and binary forms, with or without
  16. ## modification, are permitted provided that the following conditions are
  17. ## met:
  18. ##   * Redistributions of source code must retain the above copyright
  19. ##     notice, this list of conditions and the following disclaimer.
  20. ##   * Redistributions in binary form must reproduce the above copyright
  21. ##     notice, this list of conditions and the following disclaimer in
  22. ##     the documentation and/or other materials provided with the
  23. ##     distribution.
  24. ##   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
  25. ##     the names of its contributors may be used to endorse or promote
  26. ##     products derived from this software without specific prior written
  27. ##     permission.
  28. ##
  29. ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  30. ## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  31. ## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  32. ## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  33. ## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34. ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  35. ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  36. ## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  37. ## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38. ## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  39. ## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  40. ## $QT_END_LICENSE$
  41. ##
  42. #############################################################################
  43.  
  44.  
  45. from PyQt5.QtCore import QByteArray, qFuzzyCompare, Qt, QTimer
  46. from PyQt5.QtGui import QPalette, QPixmap
  47. from PyQt5.QtMultimedia import (QAudioEncoderSettings, QCamera,
  48.         QCameraImageCapture, QImageEncoderSettings, QMediaMetaData,
  49.         QMediaRecorder, QMultimedia, QVideoEncoderSettings)
  50. from PyQt5.QtWidgets import (QAction, QActionGroup, QApplication, QDialog,
  51.         QMainWindow, QMessageBox)
  52.  
  53. from ui_camera import Ui_Camera
  54. from ui_imagesettings import Ui_ImageSettingsUi
  55. from ui_videosettings import Ui_VideoSettingsUi
  56.  
  57.  
  58. class ImageSettings(QDialog):
  59.  
  60.     def __init__(self, imageCapture, parent=None):
  61.         super(ImageSettings, self).__init__(parent)
  62.  
  63.         self.ui = Ui_ImageSettingsUi()
  64.         self.imagecapture = imageCapture
  65.  
  66.         self.ui.setupUi(self)
  67.  
  68.         self.ui.imageCodecBox.addItem("Default image format", "")
  69.         for codecName in self.imagecapture.supportedImageCodecs():
  70.             description = self.imagecapture.imageCodecDescription(codecName)
  71.             self.ui.imageCodecBox.addItem(codecName + ": " + description,
  72.                     codecName)
  73.  
  74.         self.ui.imageQualitySlider.setRange(0, QMultimedia.VeryHighQuality)
  75.  
  76.         self.ui.imageResolutionBox.addItem("Default resolution")
  77.         supportedResolutions, _ = self.imagecapture.supportedResolutions()
  78.         for resolution in supportedResolutions:
  79.             self.ui.imageResolutionBox.addItem(
  80.                     "%dx%d" % (resolution.width(), resolution.height()),
  81.                     resolution)
  82.  
  83.     def imageSettings(self):
  84.         settings = self.imagecapture.encodingSettings()
  85.         settings.setCodec(self.boxValue(self.ui.imageCodecBox))
  86.         settings.setQuality(
  87.                 QMultimedia.EncodingQuality(
  88.                         self.ui.imageQualitySlider.value()))
  89.         settings.setResolution(self.boxValue(self.ui.imageResolutionBox))
  90.  
  91.         return settings
  92.  
  93.     def setImageSettings(self, settings):
  94.         self.selectComboBoxItem(self.ui.imageCodecBox, settings.codec())
  95.         self.selectComboBoxItem(self.ui.imageResolutionBox,
  96.                 settings.resolution())
  97.         self.ui.imageQualitySlider.setValue(settings.quality())
  98.  
  99.     @staticmethod
  100.     def boxValue(box):
  101.         idx = box.currentIndex()
  102.         if idx == -1:
  103.             return None
  104.  
  105.         return box.itemData(idx)
  106.  
  107.     @staticmethod
  108.     def selectComboBoxItem(box, value):
  109.         for i in range(box.count()):
  110.             if box.itemData(i) == value:
  111.                 box.setCurrentIndex(i)
  112.                 break
  113.  
  114.  
  115. class VideoSettings(QDialog):
  116.  
  117.     def __init__(self, mediaRecorder, parent=None):
  118.         super(VideoSettings, self).__init__(parent)
  119.  
  120.         self.ui = Ui_VideoSettingsUi()
  121.         self.mediaRecorder = mediaRecorder
  122.  
  123.         self.ui.setupUi(self)
  124.  
  125.         self.ui.audioCodecBox.addItem("Default audio codec", "")
  126.         for codecName in self.mediaRecorder.supportedAudioCodecs():
  127.             description = self.mediaRecorder.audioCodecDescription(codecName)
  128.             self.ui.audioCodecBox.addItem(codecName + ": " + description,
  129.                     codecName)
  130.  
  131.         supportedSampleRates, _ = self.mediaRecorder.supportedAudioSampleRates()
  132.         for sampleRate in supportedSampleRates:
  133.             self.ui.audioSampleRateBox.addItem(str(sampleRate), sampleRate)
  134.  
  135.         self.ui.audioQualitySlider.setRange(0, QMultimedia.VeryHighQuality)
  136.  
  137.         self.ui.videoCodecBox.addItem("Default video codec", "")
  138.         for codecName in self.mediaRecorder.supportedVideoCodecs():
  139.             description = self.mediaRecorder.videoCodecDescription(codecName)
  140.             self.ui.videoCodecBox.addItem(codecName + ": " + description,
  141.                     codecName)
  142.  
  143.         self.ui.videoQualitySlider.setRange(0, QMultimedia.VeryHighQuality)
  144.  
  145.         self.ui.videoResolutionBox.addItem("Default")
  146.         supportedResolutions, _ = self.mediaRecorder.supportedResolutions()
  147.         for resolution in supportedResolutions:
  148.             self.ui.videoResolutionBox.addItem(
  149.                     "%dx%d" % (resolution.width(), resolution.height()),
  150.                     resolution)
  151.  
  152.         self.ui.videoFramerateBox.addItem("Default")
  153.         supportedFrameRates, _ = self.mediaRecorder.supportedFrameRates()
  154.         for rate in supportedFrameRates:
  155.             self.ui.videoFramerateBox.addItem("%0.2f" % rate, rate)
  156.  
  157.         self.ui.containerFormatBox.addItem("Default container", "")
  158.         for format in self.mediaRecorder.supportedContainers():
  159.             self.ui.containerFormatBox.addItem(
  160.                     format + ":" + self.mediaRecorder.containerDescription(
  161.                             format),
  162.                     format)
  163.  
  164.     def audioSettings(self):
  165.         settings = self.mediaRecorder.audioSettings()
  166.         settings.setCodec(self.boxValue(self.ui.audioCodecBox))
  167.         settings.setQuality(
  168.                 QMultimedia.EncodingQuality(
  169.                         self.ui.audioQualitySlider.value()))
  170.         settings.setSampleRate(self.boxValue(self.ui.audioSampleRateBox))
  171.  
  172.         return settings
  173.  
  174.     def setAudioSettings(self, settings):
  175.         self.selectComboBoxItem(self.ui.audioCodecBox, settings.codec())
  176.         self.selectComboBoxItem(self.ui.audioSampleRateBox,
  177.                 settings.sampleRate())
  178.         self.ui.audioQualitySlider.setValue(settings.quality())
  179.  
  180.     def videoSettings(self):
  181.         settings = self.mediaRecorder.videoSettings()
  182.         settings.setCodec(self.boxValue(self.ui.videoCodecBox))
  183.         settings.setQuality(
  184.                 QMultimedia.EncodingQuality(
  185.                         self.ui.videoQualitySlider.value()))
  186.         settings.setResolution(self.boxValue(self.ui.videoResolutionBox))
  187.         settings.setFrameRate(self.boxValue(self.ui.videoFramerateBox))
  188.  
  189.         return settings
  190.  
  191.     def setVideoSettings(self, settings):
  192.         self.selectComboBoxItem(self.ui.videoCodecBox, settings.codec())
  193.         self.selectComboBoxItem(self.ui.videoResolutionBox,
  194.                 settings.resolution())
  195.         self.ui.videoQualitySlider.setValue(settings.quality())
  196.  
  197.         for i in range(1, self.ui.videoFramerateBox.count()):
  198.             itemRate = self.ui.videoFramerateBox.itemData(i)
  199.             if qFuzzyCompare(itemRate, settings.frameRate()):
  200.                 self.ui.videoFramerateBox.setCurrentIndex(i)
  201.                 break
  202.  
  203.     def format(self):
  204.         return self.boxValue(self.ui.containerFormatBox)
  205.  
  206.     def setFormat(self, format):
  207.         self.selectComboBoxItem(self.ui.containerFormatBox, format)
  208.  
  209.     @staticmethod
  210.     def boxValue(box):
  211.         idx = box.currentIndex()
  212.         if idx == -1:
  213.             return None
  214.  
  215.         return box.itemData(idx)
  216.  
  217.     @staticmethod
  218.     def selectComboBoxItem(box, value):
  219.         for i in range(box.count()):
  220.             if box.itemData(i) == value:
  221.                 box.setCurrentIndex(i)
  222.                 break
  223.  
  224.  
  225. class Camera(QMainWindow):
  226.  
  227.     def __init__(self, parent=None):
  228.         super(Camera, self).__init__(parent)
  229.  
  230.         self.ui = Ui_Camera()
  231.         self.camera = None
  232.         self.imageCapture = None
  233.         self.mediaRecorder = None
  234.         self.isCapturingImage = False
  235.         self.applicationExiting = False
  236.  
  237.         self.imageSettings = QImageEncoderSettings()
  238.         self.audioSettings = QAudioEncoderSettings()
  239.         self.videoSettings = QVideoEncoderSettings()
  240.         self.videoContainerFormat = ''
  241.  
  242.         self.ui.setupUi(self)
  243.  
  244.         cameraDevice = QByteArray()
  245.  
  246.         videoDevicesGroup = QActionGroup(self)
  247.         videoDevicesGroup.setExclusive(True)
  248.  
  249.         for deviceName in QCamera.availableDevices():
  250.             description = QCamera.deviceDescription(deviceName)
  251.             videoDeviceAction = QAction(description, videoDevicesGroup)
  252.             videoDeviceAction.setCheckable(True)
  253.             videoDeviceAction.setData(deviceName)
  254.  
  255.             if cameraDevice.isEmpty():
  256.                 cameraDevice = deviceName
  257.                 videoDeviceAction.setChecked(True)
  258.  
  259.             self.ui.menuDevices.addAction(videoDeviceAction)
  260.  
  261.         videoDevicesGroup.triggered.connect(self.updateCameraDevice)
  262.         self.ui.captureWidget.currentChanged.connect(self.updateCaptureMode)
  263.  
  264.         self.ui.lockButton.hide()
  265.  
  266.         self.setCamera(cameraDevice)
  267.  
  268.     def setCamera(self, cameraDevice):
  269.         if cameraDevice.isEmpty():
  270.             self.camera = QCamera()
  271.         else:
  272.             self.camera = QCamera(cameraDevice)
  273.  
  274.         self.camera.stateChanged.connect(self.updateCameraState)
  275.         self.camera.error.connect(self.displayCameraError)
  276.  
  277.         self.mediaRecorder = QMediaRecorder(self.camera)
  278.         self.mediaRecorder.stateChanged.connect(self.updateRecorderState)
  279.  
  280.         self.imageCapture = QCameraImageCapture(self.camera)
  281.  
  282.         self.mediaRecorder.durationChanged.connect(self.updateRecordTime)
  283.         self.mediaRecorder.error.connect(self.displayRecorderError)
  284.  
  285.         self.mediaRecorder.setMetaData(QMediaMetaData.Title, "Test Title")
  286.  
  287.         self.ui.exposureCompensation.valueChanged.connect(
  288.                 self.setExposureCompensation)
  289.  
  290.         self.camera.setViewfinder(self.ui.viewfinder)
  291.  
  292.         self.updateCameraState(self.camera.state())
  293.         self.updateLockStatus(self.camera.lockStatus(), QCamera.UserRequest)
  294.         self.updateRecorderState(self.mediaRecorder.state())
  295.  
  296.         self.imageCapture.readyForCaptureChanged.connect(self.readyForCapture)
  297.         self.imageCapture.imageCaptured.connect(self.processCapturedImage)
  298.         self.imageCapture.imageSaved.connect(self.imageSaved)
  299.  
  300.         self.camera.lockStatusChanged.connect(self.updateLockStatus)
  301.  
  302.         self.ui.captureWidget.setTabEnabled(0,
  303.                 self.camera.isCaptureModeSupported(QCamera.CaptureStillImage))
  304.         self.ui.captureWidget.setTabEnabled(1,
  305.                 self.camera.isCaptureModeSupported(QCamera.CaptureVideo))
  306.  
  307.         self.updateCaptureMode()
  308.         self.camera.start()
  309.  
  310.     def keyPressEvent(self, event):
  311.         if event.isAutoRepeat():
  312.             return
  313.  
  314.         if event.key() == Qt.Key_CameraFocus:
  315.             self.displayViewfinder()
  316.             self.camera.searchAndLock()
  317.             event.accept()
  318.         elif event.key() == Qt.Key_Camera:
  319.             if self.camera.captureMode() == QCamera.CaptureStillImage:
  320.                 self.takeImage()
  321.             elif self.mediaRecorder.state() == QMediaRecorder.RecordingState:
  322.                 self.stop()
  323.             else:
  324.                 self.record()
  325.  
  326.             event.accept()
  327.         else:
  328.             super(Camera, self).keyPressEvent(event)
  329.  
  330.     def keyReleaseEvent(self, event):
  331.         if event.isAutoRepeat():
  332.             return
  333.  
  334.         if event.key() == Qt.Key_CameraFocus:
  335.             self.camera.unlock()
  336.         else:
  337.             super(Camera, self).keyReleaseEvent(event)
  338.  
  339.     def updateRecordTime(self):
  340.         msg = "Recorded %d sec" % (self.mediaRecorder.duration() // 1000)
  341.         self.ui.statusbar.showMessage(msg)
  342.  
  343.     def processCapturedImage(self, requestId, img):
  344.         scaledImage = img.scaled(self.ui.viewfinder.size(), Qt.KeepAspectRatio,
  345.                 Qt.SmoothTransformation)
  346.  
  347.         self.ui.lastImagePreviewLabel.setPixmap(QPixmap.fromImage(scaledImage))
  348.  
  349.         self.displayCapturedImage()
  350.         QTimer.singleShot(4000, self.displayViewfinder)
  351.  
  352.     def configureCaptureSettings(self):
  353.         if self.camera.captureMode() == QCamera.CaptureStillImage:
  354.             self.configureImageSettings()
  355.         elif self.camera.captureMode() == QCamera.CaptureVideo:
  356.             self.configureVideoSettings()
  357.  
  358.     def configureVideoSettings(self):
  359.         settingsDialog = VideoSettings(self.mediaRecorder)
  360.  
  361.         settingsDialog.setAudioSettings(self.audioSettings)
  362.         settingsDialog.setVideoSettings(self.videoSettings)
  363.         settingsDialog.setFormat(self.videoContainerFormat)
  364.  
  365.         if settingsDialog.exec_():
  366.             self.audioSettings = settingsDialog.audioSettings()
  367.             self.videoSettings = settingsDialog.videoSettings()
  368.             self.videoContainerFormat = settingsDialog.format()
  369.  
  370.             self.mediaRecorder.setEncodingSettings(self.audioSettings,
  371.                     self.videoSettings, self.videoContainerFormat)
  372.  
  373.     def configureImageSettings(self):
  374.         settingsDialog = ImageSettings(self.imageCapture)
  375.  
  376.         settingsDialog.setImageSettings(self.imageSettings)
  377.  
  378.         if settingsDialog.exec_():
  379.             self.imageSettings = settingsDialog.imageSettings()
  380.             self.imageCapture.setEncodingSettings(self.imageSettings)
  381.  
  382.     def record(self):
  383.         self.mediaRecorder.record()
  384.         self.updateRecordTime()
  385.  
  386.     def pause(self):
  387.         self.mediaRecorder.pause()
  388.  
  389.     def stop(self):
  390.         self.mediaRecorder.stop()
  391.  
  392.     def setMuted(self, muted):
  393.         self.mediaRecorder.setMuted(muted)
  394.  
  395.     def toggleLock(self):
  396.         if self.camera.lockStatus() in (QCamera.Searching, QCamera.Locked):
  397.             self.camera.unlock()
  398.         elif self.camera.lockStatus() == QCamera.Unlocked:
  399.             self.camera.searchAndLock()
  400.  
  401.     def updateLockStatus(self, status, reason):
  402.         indicationColor = Qt.black
  403.  
  404.         if status == QCamera.Searching:
  405.             self.ui.statusbar.showMessage("Focusing...")
  406.             self.ui.lockButton.setText("Focusing...")
  407.             indicationColor = Qt.yellow
  408.         elif status == QCamera.Locked:
  409.             self.ui.lockButton.setText("Unlock")
  410.             self.ui.statusbar.showMessage("Focused", 2000)
  411.             indicationColor = Qt.darkGreen
  412.         elif status == QCamera.Unlocked:
  413.             self.ui.lockButton.setText("Focus")
  414.  
  415.             if reason == QCamera.LockFailed:
  416.                 self.ui.statusbar.showMessage("Focus Failed", 2000)
  417.                 indicationColor = Qt.red
  418.  
  419.         palette = self.ui.lockButton.palette()
  420.         palette.setColor(QPalette.ButtonText, indicationColor)
  421.         self.ui.lockButton.setPalette(palette)
  422.  
  423.     def takeImage(self):
  424.         self.isCapturingImage = True
  425.         self.imageCapture.capture()
  426.  
  427.     def startCamera(self):
  428.         self.camera.start()
  429.  
  430.     def stopCamera(self):
  431.         self.camera.stop()
  432.  
  433.     def updateCaptureMode(self):
  434.         tabIndex = self.ui.captureWidget.currentIndex()
  435.         captureMode = QCamera.CaptureStillImage if tabIndex == 0 else QCamera.CaptureVideo
  436.  
  437.         if self.camera.isCaptureModeSupported(captureMode):
  438.             self.camera.setCaptureMode(captureMode)
  439.  
  440.     def updateCameraState(self, state):
  441.         if state == QCamera.ActiveState:
  442.             self.ui.actionStartCamera.setEnabled(False)
  443.             self.ui.actionStopCamera.setEnabled(True)
  444.             self.ui.captureWidget.setEnabled(True)
  445.             self.ui.actionSettings.setEnabled(True)
  446.         elif state in (QCamera.UnloadedState, QCamera.LoadedState):
  447.             self.ui.actionStartCamera.setEnabled(True)
  448.             self.ui.actionStopCamera.setEnabled(False)
  449.             self.ui.captureWidget.setEnabled(False)
  450.             self.ui.actionSettings.setEnabled(False)
  451.  
  452.     def updateRecorderState(self, state):
  453.         if state == QMediaRecorder.StoppedState:
  454.             self.ui.recordButton.setEnabled(True)
  455.             self.ui.pauseButton.setEnabled(True)
  456.             self.ui.stopButton.setEnabled(False)
  457.         elif state == QMediaRecorder.PausedState:
  458.             self.ui.recordButton.setEnabled(True)
  459.             self.ui.pauseButton.setEnabled(False)
  460.             self.ui.stopButton.setEnabled(True)
  461.         elif state == QMediaRecorder.RecordingState:
  462.             self.ui.recordButton.setEnabled(False)
  463.             self.ui.pauseButton.setEnabled(True)
  464.             self.ui.stopButton.setEnabled(True)
  465.  
  466.     def setExposureCompensation(self, index):
  467.         self.camera.exposure().setExposureCompensation(index * 0.5)
  468.  
  469.     def displayRecorderError(self):
  470.         QMessageBox.warning(self, "Capture error",
  471.                 self.mediaRecorder.errorString())
  472.  
  473.     def displayCameraError(self):
  474.         QMessageBox.warning(self, "Camera error", self.camera.errorString())
  475.  
  476.     def updateCameraDevice(self, action):
  477.         self.setCamera(action.data())
  478.  
  479.     def displayViewfinder(self):
  480.         self.ui.stackedWidget.setCurrentIndex(0)
  481.  
  482.     def displayCapturedImage(self):
  483.         self.ui.stackedWidget.setCurrentIndex(1)
  484.  
  485.     def readyForCapture(self, ready):
  486.         self.ui.takeImageButton.setEnabled(ready)
  487.  
  488.     def imageSaved(self, id, fileName):
  489.         self.isCapturingImage = False
  490.  
  491.         if self.applicationExiting:
  492.             self.close()
  493.  
  494.     def closeEvent(self, event):
  495.         if self.isCapturingImage:
  496.             self.setEnabled(False)
  497.             self.applicationExiting = True
  498.             event.ignore()
  499.         else:
  500.             event.accept()
  501.  
  502.  
  503. if __name__ == '__main__':
  504.  
  505.     import sys
  506.  
  507.     app = QApplication(sys.argv)
  508.  
  509.     camera = Camera()
  510.     camera.show()
  511.  
  512.     sys.exit(app.exec_())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement