ogg_saver.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 
00003 #include <theora_image_transport/Packet.h>
00004 
00005 #include <theora/codec.h>
00006 #include <theora/theoraenc.h>
00007 #include <theora/theoradec.h>
00008 #include <ogg/ogg.h>
00009 
00010 #include <fstream>
00011 #include <vector>
00012 #include <boost/scoped_array.hpp>
00013 
00014 using namespace std;
00015 
00016 class OggSaver
00017 {
00018 public:
00019   OggSaver(const char* filename)
00020    : fout_(filename, std::ios::out|std::ios::binary)
00021   {
00022     if (ogg_stream_init(&stream_state_, 0) == -1) {
00023       ROS_FATAL("Unable to initialize ogg_stream_state structure");
00024       exit(1);
00025     }
00026 
00027     sub_ = nh_.subscribe("stream", 10, &OggSaver::processMsg, this);
00028   }
00029 
00030   ~OggSaver()
00031   {
00032     ogg_page page;
00033     if (ogg_stream_flush(&stream_state_, &page) != 0)
00034       writePage(page);
00035     fout_.close();
00036     ogg_stream_clear(&stream_state_);
00037   }
00038 
00039 private:
00040 
00041   ros::NodeHandle nh_;
00042   ogg_stream_state stream_state_;
00043   ofstream fout_;
00044   ros::Subscriber sub_;
00045 
00046   // When using this caller is responsible for deleting oggpacket.packet!!
00047   void msgToOggPacket(const theora_image_transport::Packet &msg, ogg_packet &oggpacket)
00048   {
00049     oggpacket.bytes = msg.data.size();
00050     oggpacket.b_o_s = msg.b_o_s;
00051     oggpacket.e_o_s = msg.e_o_s;
00052     oggpacket.granulepos = msg.granulepos;
00053     oggpacket.packetno = msg.packetno;
00054     oggpacket.packet = new unsigned char[oggpacket.bytes];
00055     memcpy(oggpacket.packet, &msg.data[0], oggpacket.bytes);
00056   }
00057 
00058   void writePage(ogg_page& page)
00059   {
00060     fout_.write((char*)page.header, page.header_len);
00061     fout_.write((char*)page.body,   page.body_len);
00062   }
00063 
00064   void processMsg(const theora_image_transport::PacketConstPtr& message)
00065   {
00071     ogg_packet oggpacket;
00072     msgToOggPacket(*message, oggpacket);
00073     boost::scoped_array<unsigned char> packet_guard(oggpacket.packet); // Make sure packet memory gets deleted
00074 
00075     if (ogg_stream_packetin(&stream_state_, &oggpacket)) {
00076       ROS_ERROR("Error while adding packet to stream.");
00077       exit(2);
00078     }
00079 
00080     ogg_page page;
00081     if (ogg_stream_pageout(&stream_state_, &page) != 0)
00082       writePage(page);
00083   }
00084 };
00085 
00086 int main(int argc, char** argv)
00087 {
00090   ros::init(argc, argv, "OggSaver", ros::init_options::AnonymousName);
00091 
00092   if(argc < 2) {
00093     cerr << "Usage: " << argv[0] << " stream:=/theora/image/stream outputFile" << endl;
00094     exit(3);
00095   }
00096   if (ros::names::remap("stream") == "stream") {
00097       ROS_WARN("ogg_saver: stream has not been remapped! Typical command-line usage:\n"
00098                "\t$ ./ogg_saver stream:=<theora stream topic> outputFile");
00099   }
00100   
00101   OggSaver saver(argv[1]);
00102   
00103   ros::spin();
00104   return 0;
00105 }


theora_image_transport
Author(s): Patrick Mihelich, Ethan Dreyfuss
autogenerated on Sat Dec 28 2013 17:06:15