00001 #include "theora_imagem_transport/theora_subscriber.h"
00002 #include <sensor_msgs/image_encodings.h>
00003 #include <opencv/cvwimage.h>
00004 #include <opencv/highgui.h>
00005
00006 #include <vector>
00007
00008 #define null 0
00009
00010 using namespace std;
00011
00012 namespace theora_imagem_transport {
00013
00014 TheoraSubscriber::TheoraSubscriber()
00015 {
00016 decoding_context_ = null;
00017 received_header_ = false;
00018 setup_info_ = null;
00019 th_info_init(&header_info_);
00020 }
00021
00022 TheoraSubscriber::~TheoraSubscriber()
00023 {
00024 }
00025
00026
00027 void TheoraSubscriber::msgToOggPacket(const theora_imagem_transport::packet &msg, ogg_packet &oggpacketOutput)
00028 {
00029 oggpacketOutput.bytes = msg.bytes;
00030 oggpacketOutput.b_o_s = msg.b_o_s;
00031 oggpacketOutput.e_o_s = msg.e_o_s;
00032 oggpacketOutput.granulepos = msg.granulepos;
00033 oggpacketOutput.packetno = msg.packetno;
00034 oggpacketOutput.packet = new unsigned char[msg.bytes];
00035 memcpy(oggpacketOutput.packet, &msg.blob[0], msg.bytes);
00036
00037
00038
00039
00040
00041
00042 }
00043
00044 void TheoraSubscriber::internalCallback(const theora_imagem_transport::packetConstPtr& message,
00045 const message_transport::SimpleSubscriberPlugin<sensor_msgs::Image,theora_imagem_transport::packet>::Callback& callback)
00046 {
00047 const theora_imagem_transport::packet &pkt = *message;
00048 ogg_packet oggpacket;
00049 msgToOggPacket(pkt, oggpacket);
00050 sensor_msgs::Image *rosMsg = null;
00051
00052 if (received_header_ == false)
00053 {
00054 if ((int)oggpacket.packetno == 999999)
00055 {
00056 ROS_DEBUG("Dropping flush packet.");
00057 return;
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067 ROS_DEBUG("Setup_info: %p", setup_info_);
00068 int rval = th_decode_headerin(&header_info_, &header_comment_, &setup_info_, &oggpacket);
00069 ROS_DEBUG("Setup_info: %p", setup_info_);
00070 if (rval == 0)
00071 {
00072 ROS_DEBUG("This should happen on correct receipt of a header packet but never seems to in practice");
00073
00074
00075 }
00076 else if (rval == TH_EFAULT)
00077 ROS_DEBUG("EFault when processing header.");
00078 else if (rval == TH_EBADHEADER)
00079 ROS_DEBUG("Bad header when processing header.");
00080 else if (rval == TH_EVERSION)
00081 ROS_DEBUG("Bad version when processing header.");
00082 else if (rval == TH_ENOTFORMAT)
00083 ROS_DEBUG("Received packet which was not a Theora header.");
00084 else if (rval < 0)
00085 ROS_DEBUG("Error code when processing header: %d.", rval);
00086
00087 if (setup_info_ != null)
00088 {
00089 received_header_ = true;
00090 decoding_context_ = th_decode_alloc(&header_info_, setup_info_);
00091 }
00092 }
00093
00094 if (received_header_ == true)
00095 {
00096 int rval = th_decode_packetin(decoding_context_, &oggpacket, null);
00097
00098 if (rval == 0)
00099 {
00100 th_ycbcr_buffer ycbcr_image;
00101 th_decode_ycbcr_out(decoding_context_, ycbcr_image);
00102
00103
00104 IplImage* img = cvCreateImage(cvSize(ycbcr_image[0].width, ycbcr_image[0].height), IPL_DEPTH_8U, 3);
00105
00106
00107 for (int planeIdx = 0; planeIdx < 3; planeIdx++)
00108 {
00109 int swappedIdx = planeIdx;
00110 if (planeIdx == 1)
00111 swappedIdx = 2;
00112 else if (planeIdx == 2)
00113 swappedIdx = 1;
00114 for (int i = 0; i < img->width; i++)
00115 for (int j = 0; j < img->height; j++)
00116 {
00117 int ci = planeIdx > 0 ? i / 2 : i;
00118 int cj = planeIdx > 0 ? j / 2 : j;
00119 ((uchar*)(img->imageData + img->widthStep * j))[i * 3 + planeIdx] = ycbcr_image[swappedIdx].data[ci + cj * ycbcr_image[swappedIdx].stride];
00120 }
00121 }
00122
00123 IplImage* img2 = cvCreateImage(cvGetSize(img), img->depth, img->nChannels);
00124 cvCvtColor(img, img2, CV_YCrCb2BGR);
00125
00126 rosMsg = new sensor_msgs::Image();
00127 img_bridge_.fromIpltoRosImage(img2, *rosMsg);
00128
00129 cvReleaseImage(&img);
00130 cvReleaseImage(&img2);
00131 }
00132 else if (rval == TH_DUPFRAME)
00133 ROS_DEBUG("Got a duplicate frame.");
00134 else
00135 ROS_DEBUG("Error code when decoding packet: %d.", rval);
00136 }
00137
00138 delete oggpacket.packet;
00139
00140 if(rosMsg != null)
00141 {
00142
00143 boost::shared_ptr<sensor_msgs::Image> image_ptr(rosMsg);
00144
00145
00146
00147
00148 image_ptr->encoding = sensor_msgs::image_encodings::BGR8;
00149 callback(image_ptr);
00150 }
00151 }
00152
00153 }