Advertisement
Guest User

sony remote camera with c++

a guest
Jul 9th, 2014
1,806
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.29 KB | None | 0 0
  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4. #include <thread>
  5. #include <chrono>
  6. #include <boost/asio.hpp>
  7. #include <boost/bind.hpp>
  8. #include <boost/date_time/posix_time/posix_time_types.hpp>
  9. #include <boost/property_tree/ptree.hpp>
  10. #include <boost/property_tree/xml_parser.hpp>
  11. #include <boost/property_tree/json_parser.hpp>
  12. #include <opencv2/opencv.hpp>
  13.  
  14.  
  15. using namespace std;
  16. using namespace boost;
  17.  
  18.  
  19. class multicast_manager
  20. {
  21. public:
  22.     multicast_manager(boost::asio::io_service& io_service,
  23.         const boost::asio::ip::address& multicast_address)
  24.         :endpoint_(multicast_address, 1900),
  25.         socket_(io_service, endpoint_.protocol()),
  26.         tcp_socket_(io_service),
  27.         tcp_resolver_(io_service),
  28.         liveview_socket_(io_service)
  29.     {
  30.         stringstream os;
  31.         os << "M-SEARCH * HTTP/1.1\r\n";
  32.         os << "HOST: 239.255.255.250:1900\r\n";
  33.         os << "MAN: \"ssdp:discover\"\r\n";
  34.         os << "MX: 4\r\n";
  35.         os << "ST: urn:schemas-sony-com:service:ScalarWebAPI:1\r\n";
  36.         os << "\r\n";
  37.         message_ = os.str();
  38.         socket_.set_option(asio::ip::multicast::outbound_interface(asio::ip::address_v4::from_string("10.0.1.1")));
  39.         socket_.async_send_to(
  40.             boost::asio::buffer(message_), endpoint_,
  41.             boost::bind(&multicast_manager::handle_send_to, this,
  42.             boost::asio::placeholders::error));    
  43.     }
  44.  
  45.     void handle_send_to(const boost::system::error_code& error) {
  46.         if (!error) {
  47.             socket_.async_receive(asio::buffer(data_),// "\r\n",
  48.                 boost::bind(&multicast_manager::handle_read_header, this,
  49.                 boost::asio::placeholders::error,
  50.                 boost::asio::placeholders::bytes_transferred));
  51.         }
  52.     }
  53.  
  54.     void handle_read_header(const boost::system::error_code& err, size_t bytes_recvd) {
  55.         if (!err) {
  56.             // Check that response is OK.
  57.             http_response = stringstream(data_);
  58.             string http_version;
  59.             http_response >> http_version;
  60.             unsigned int status_code;
  61.             http_response >> status_code;
  62.             string status_message;
  63.             getline(http_response, status_message);
  64.             if (!http_response || http_version.substr(0, 5) != "HTTP/") {
  65.                 std::cout << "Invalid response\n";
  66.                 return;
  67.             }
  68.             if (status_code != 200) {
  69.                 std::cout << "Response returned with status code ";
  70.                 std::cout << status_code << "\n";
  71.                 return;
  72.             }
  73.             string header;
  74.             string description_url;
  75.             while (getline(http_response, header) && header != "\r") {
  76.                 if (header.substr(0, 9) == "LOCATION:") {
  77.                     description_url = header.substr(10, header.length()-11);
  78.                 }
  79.                 cout << header << "\n";
  80.             }
  81.             cout << "\n";
  82.             LaunchConnection(description_url);
  83.         } else {
  84.             std::cout << "Error: " << err << "\n";
  85.         }
  86.     }
  87.  
  88.     void LaunchConnection(string description_url){
  89.         size_t last_slash = description_url.rfind('/');
  90.         size_t colon = description_url.rfind(':');
  91.         string server = description_url.substr(7, colon-7);
  92.         string port = description_url.substr(colon+1, last_slash - colon -1);
  93.         //server = "10.0.0.1";
  94.         string path = description_url.substr(last_slash);
  95.         ostream request_stream(&tcp_request_);
  96.         request_stream << "GET " << path << " HTTP/1.1\r\n";
  97.         request_stream << "Host: " << server << "\r\n";
  98.         request_stream << "Accept: */*\r\n";
  99.         request_stream << "Connection: close\r\n\r\n";
  100.         asio::ip::tcp::resolver::query query(server, port);
  101.         tcp_resolver_.async_resolve(query,
  102.             boost::bind(&multicast_manager::handle_resolve, this,
  103.             boost::asio::placeholders::error,
  104.             boost::asio::placeholders::iterator));
  105.     }
  106.  
  107.     void handle_resolve(const boost::system::error_code& err,
  108.         asio::ip::tcp::resolver::iterator endpoint_iterator)    {
  109.         if (!err) {
  110.             // Attempt a connection to each endpoint in the list until we
  111.             // successfully establish a connection.
  112.             boost::asio::async_connect(tcp_socket_, endpoint_iterator,
  113.                 boost::bind(&multicast_manager::handle_connect, this,
  114.                 boost::asio::placeholders::error));
  115.         } else {
  116.             cout << "Error: " << err.message() << "\n";
  117.         }
  118.     }
  119.  
  120.     void handle_connect(const boost::system::error_code& err) {
  121.         if (!err) {
  122.             // The connection was successful. Send the request.
  123.             boost::asio::async_write(tcp_socket_, tcp_request_,
  124.                 boost::bind(&multicast_manager::handle_write_request, this,
  125.                 boost::asio::placeholders::error));
  126.         } else {
  127.             std::cout << "Error: " << err.message() << "\n";
  128.         }
  129.     }
  130.  
  131.  
  132.     void handle_write_request(const boost::system::error_code& err) {
  133.         if (!err) {
  134.             // Read the response status line. The response_ streambuf will
  135.             // automatically grow to accommodate the entire line. The growth may be
  136.             // limited by passing a maximum size to the streambuf constructor.
  137.             boost::asio::async_read_until(tcp_socket_, tcp_response_, "\r\n",
  138.                 boost::bind(&multicast_manager::handle_read_status_line, this,
  139.                 boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
  140.         } else {
  141.             std::cout << "Error: " << err.message() << "\n";
  142.         }
  143.     }
  144.  
  145.     void handle_read_status_line(const boost::system::error_code& err, const size_t bytes_transferred) {
  146.         if (!err) {
  147.             // Check that response is OK.
  148.             std::istream response_stream(&tcp_response_);
  149.             std::string http_version;
  150.             response_stream >> http_version;
  151.             unsigned int status_code;
  152.             response_stream >> status_code;
  153.             std::string status_message;
  154.             std::getline(response_stream, status_message);
  155.             if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
  156.                 std::cout << "Invalid response\n";
  157.                 return;
  158.             }
  159.             if (status_code != 200) {
  160.                 std::cout << "Response returned with status code ";
  161.                 std::cout << status_code << "\n";
  162.                 return;
  163.             }
  164.             // Read the response headers, which are terminated by a blank line.
  165.             boost::asio::async_read_until(tcp_socket_, tcp_response_, "\r\n\r\n",
  166.                 boost::bind(&multicast_manager::handle_read_headers, this,
  167.                 boost::asio::placeholders::error));
  168.         } else {
  169.             std::cout << "Error: " << err << "\n";
  170.             cout << err.message();
  171.         }
  172.     }
  173.  
  174.     void handle_read_headers(const boost::system::error_code& err) {
  175.         if (!err) {
  176.             // Process the response headers.
  177.             std::istream response_stream(&tcp_response_);
  178.             std::string header;
  179.             while (std::getline(response_stream, header) && header != "\r")
  180.                 std::cout << header << "\n";
  181.             std::cout << "\n";
  182.  
  183.            
  184.             if (reading_image) {
  185.                 size_t n = tcp_response_.size();
  186.                 vector<uint8_t> v;
  187.                 if (n < 12) {
  188.                     tcp_response_.sgetn((char *)liveview_common_header, n);
  189.                     boost::asio::async_read(liveview_socket_, asio::buffer(liveview_common_header+n, 12-n),
  190.                         boost::bind(&multicast_manager::handle_read_common_header, this,
  191.                         boost::asio::placeholders::error));
  192.                 }
  193.                 else if (n < 12 + 128) {
  194.                     n -= 12;
  195.                     tcp_response_.sgetn((char *)liveview_common_header, 12);
  196.                     tcp_response_.sgetn((char *)liveview_payload_header, n);
  197.                     boost::asio::async_read(liveview_socket_, asio::buffer(liveview_payload_header + n, 128 - n),
  198.                         boost::bind(&multicast_manager::handle_read_payload_header, this,
  199.                         boost::asio::placeholders::error));
  200.                 } else {
  201.                     tcp_response_.sgetn((char *)liveview_common_header, 12);
  202.                     tcp_response_.sgetn((char *)liveview_payload_header, 128);
  203.                     n -= (128 + 12);
  204.                     tcp_response_.sgetn((char *)&image[0], n);
  205.                     size_t size = 256 * 256 * liveview_payload_header[4]
  206.                         + 256 * liveview_payload_header[5]
  207.                         + liveview_payload_header[6];
  208.                     boost::asio::async_read(liveview_socket_, asio::buffer(&image[0] + n, size - n),
  209.                         boost::bind(&multicast_manager::handle_read_image, this,
  210.                         boost::asio::placeholders::error));
  211.                 }
  212.                
  213.                
  214.             } else {
  215.                 // Write whatever content we already have to output.
  216.                 if (tcp_response_.size() > 0) {
  217.                     //std::cout << &tcp_response_;
  218.                     content << &tcp_response_;
  219.                 }
  220.                 // Start reading remaining data until EOF.
  221.                 boost::asio::async_read(tcp_socket_, tcp_response_,
  222.                     boost::asio::transfer_at_least(1),
  223.                     boost::bind(&multicast_manager::handle_read_content, this,
  224.                     boost::asio::placeholders::error));
  225.             }
  226.         } else {
  227.             std::cout << "Error: " << err << "\n";
  228.         }
  229.     }
  230.  
  231.     void handle_read_content(const boost::system::error_code& err) {
  232.         if (!err) {
  233.             // Write all of the data that has been read so far.
  234.             content << &tcp_response_;
  235.             // Continue reading remaining data until EOF.
  236.             boost::asio::async_read(tcp_socket_, tcp_response_,
  237.                 boost::asio::transfer_at_least(1),
  238.                 boost::bind(&multicast_manager::handle_read_content, this,
  239.                 boost::asio::placeholders::error));
  240.         } else if (err != boost::asio::error::eof) {
  241.             std::cout << "Error: " << err << "\n";
  242.         }
  243.     }
  244.    
  245.     void parse_description() {
  246.         //tcp_socket_.close();
  247.         using boost::property_tree::ptree;
  248.         ptree pt;
  249.         read_xml(content, pt);
  250.         liveview_url = pt.get<string>("root.device.av:X_ScalarWebAPI_DeviceInfo.av:X_ScalarWebAPI_ImagingDevice.av:X_ScalarWebAPI_LiveView_URL");
  251.         for (ptree::value_type &v : pt.get_child("root.device.av:X_ScalarWebAPI_DeviceInfo.av:X_ScalarWebAPI_ServiceList")){
  252.             string service = v.second.get<string>("av:X_ScalarWebAPI_ServiceType");
  253.             if (service == "camera")
  254.                 camera_service_url = v.second.get<string>("av:X_ScalarWebAPI_ActionList_URL");
  255.         }
  256.     }
  257.  
  258.     void start_liveview() {
  259.         ostream request_stream(&tcp_request_);
  260.         size_t last_slash = camera_service_url.rfind('/');
  261.         size_t colon = camera_service_url.rfind(':');
  262.         string server = camera_service_url.substr(7, colon - 7);
  263.         string port = camera_service_url.substr(colon + 1, last_slash - colon - 1);
  264.         string path = camera_service_url.substr(last_slash);
  265.         string json_request("{\"method\": \"startLiveview\",\"params\" : [],\"id\" : 1,\"version\" : \"1.0\"}\r\n");
  266.         request_stream << "POST " << path << "/camera HTTP/1.1\r\n";
  267.         request_stream << "Accept: application/json-rpc\r\n";
  268.         request_stream << "Content-Length: " << json_request.length() << "\r\n";
  269.         request_stream << "Content-Type: application/json-rpc\r\n";
  270.         request_stream << "Host:" << camera_service_url<<"\r\n";
  271.         request_stream << "\r\n";
  272.         request_stream << json_request;
  273.         asio::ip::tcp::resolver::query query(server, port);
  274.         content.clear();
  275.         content.str("");
  276.         tcp_resolver_.async_resolve(query,
  277.             boost::bind(&multicast_manager::handle_resolve, this,
  278.             boost::asio::placeholders::error,
  279.             boost::asio::placeholders::iterator));
  280.  
  281.     }
  282.  
  283.     void get_live_image() {
  284.         using boost::property_tree::ptree;
  285.         ptree pt;
  286.         string c = content.str();
  287.         read_json(content, pt);
  288.         auto v = pt.get_child("result").begin();
  289.         liveview_url = v->second.data();       
  290.         ostream request_stream(&tcp_request_);
  291.         size_t last_slash = liveview_url.rfind('/');
  292.         size_t colon = liveview_url.rfind(':');
  293.         string server = liveview_url.substr(7, colon - 7);
  294.         string port = liveview_url.substr(colon + 1, last_slash - colon - 1);
  295.         string path = liveview_url.substr(last_slash);
  296.         request_stream << "GET "<< path << " HTTP/1.1\r\n";
  297.         request_stream << "Accept: image/jpeg\r\n";
  298.         //request_stream << "Content-Length: " << json_request.length() << "\r\n";
  299.         //request_stream << "Content-Type: application/json-rpc\r\n";
  300.         request_stream << "Host: " << server << "\r\n";
  301.         request_stream << "\r\n";
  302.         asio::ip::tcp::resolver::query query(server, port);
  303.         asio::ip::tcp::resolver::iterator endpoint_iterator = tcp_resolver_.resolve(query);
  304.         asio::connect(liveview_socket_,endpoint_iterator);
  305.         reading_image = true;
  306.         boost::asio::async_write(liveview_socket_, tcp_request_,
  307.             boost::bind(&multicast_manager::handle_write_request_liveview, this,
  308.             boost::asio::placeholders::error));
  309.     }
  310.  
  311.     void handle_write_request_liveview(const boost::system::error_code& err) {
  312.  
  313.         boost::asio::async_read_until(liveview_socket_, tcp_response_, "\r\n",
  314.             boost::bind(&multicast_manager::handle_read_status_line, this,
  315.             boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));      
  316.     }
  317.  
  318.     void handle_read_common_header(const boost::system::error_code& err) {
  319.  
  320.         boost::asio::async_read(liveview_socket_, asio::buffer(liveview_payload_header, 128),
  321.             boost::bind(&multicast_manager::handle_read_payload_header, this,
  322.             boost::asio::placeholders::error));
  323.  
  324.     }
  325.     void handle_read_payload_header(const boost::system::error_code& err) {
  326.         size_t size = liveview_payload_header[6]<<0 | liveview_payload_header[5]<<8 | liveview_payload_header[4]<<24;
  327.         size += 10;
  328.         image.resize(size);
  329.         boost::asio::async_read(liveview_socket_, asio::buffer(&image[0], size),
  330.             boost::bind(&multicast_manager::handle_read_image, this,
  331.             boost::asio::placeholders::error));
  332.     }
  333.     void handle_read_image(const boost::system::error_code& err) {
  334.         cv::Mat imgbuf(image,false);
  335.         cv::Mat m(cv::imdecode(imgbuf, cv::IMREAD_COLOR));
  336.         vector<uint8_t> start_marker = { 0xff, 0xd8 };
  337.         vector<uint8_t> end_marker = { 0xff, 0xd9 };
  338.         auto start = search(image.begin(), image.end(), start_marker.begin(), start_marker.end());
  339.         auto end = search(image.begin(), image.end(), end_marker.begin(), end_marker.end());
  340.         int a = start - image.begin();
  341.         int b = end - image.begin();
  342.         ofstream image_file("image.jpg", ios::out | ios::binary | ios::trunc);
  343.         image_file.write((char*)&(*start), image.end()-start);
  344.         image_file.close();
  345.         boost::asio::async_read(liveview_socket_, asio::buffer(liveview_common_header, 12),
  346.             boost::bind(&multicast_manager::handle_read_common_header, this,
  347.             boost::asio::placeholders::error));
  348.     }
  349.  
  350.  
  351.  
  352. private:
  353.     boost::asio::ip::udp::endpoint endpoint_;
  354.     boost::asio::ip::udp::socket socket_;
  355.     boost::asio::ip::tcp::socket tcp_socket_;
  356.     boost::asio::ip::tcp::socket liveview_socket_;
  357.     int message_count_;
  358.     std::string message_;
  359.     enum { max_length = 1024 };
  360.     char data_[max_length];
  361.     stringstream http_response;
  362.     stringstream content;
  363.     asio::ip::tcp::resolver tcp_resolver_;
  364.     boost::asio::streambuf tcp_request_;
  365.     boost::asio::streambuf tcp_response_;
  366.     //iostream image;
  367.     string liveview_url;
  368.     string camera_service_url;
  369.     uint8_t liveview_common_header[12];
  370.     uint8_t liveview_payload_header[128];
  371.     vector<uint8_t> image;
  372.     bool reading_image;
  373. };
  374.  
  375. int main(int argc, char* argv[])
  376. {
  377.     try
  378.     {
  379.         boost::asio::io_service io_service;
  380.         multicast_manager m(io_service, boost::asio::ip::address::from_string("239.255.255.250"));
  381.         io_service.run();
  382.         m.parse_description();
  383.         m.start_liveview();
  384.         io_service.reset();
  385.         io_service.run();
  386.         m.get_live_image();
  387.         io_service.reset();
  388.         io_service.run();
  389.            
  390.     } catch (std::exception& e) {
  391.         std::cerr << "Exception: " << e.what() << "\n";
  392.     }
  393.     return 0;
  394. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement