00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #include "libavcodec/bytestream.h"
00023 #include "libavcodec/mjpeg.h"
00024 #include "libavutil/intreadwrite.h"
00025 #include "rtpenc.h"
00026 
00027 void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size)
00028 {
00029     RTPMuxContext *s = s1->priv_data;
00030     const uint8_t *qtables = NULL;
00031     int nb_qtables = 0;
00032     uint8_t type = 1; 
00033     uint8_t w, h;
00034     uint8_t *p;
00035     int off = 0; 
00036     int len;
00037     int i;
00038 
00039     s->buf_ptr   = s->buf;
00040     s->timestamp = s->cur_timestamp;
00041 
00042     
00043     w = s1->streams[0]->codec->width  >> 3;
00044     h = s1->streams[0]->codec->height >> 3;
00045 
00046     
00047     if (s1->streams[0]->codec->pix_fmt == PIX_FMT_YUVJ422P) {
00048         type = 0;
00049     } else if (s1->streams[0]->codec->pix_fmt == PIX_FMT_YUVJ420P) {
00050         type = 1;
00051     } else {
00052         av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n");
00053         return;
00054     }
00055 
00056     
00057     for (i = 0; i < size; i++) {
00058         if (buf[i] != 0xff)
00059             continue;
00060 
00061         if (buf[i + 1] == DQT) {
00062             if (buf[i + 4])
00063                 av_log(s1, AV_LOG_WARNING,
00064                        "Only 8-bit precision is supported.\n");
00065 
00066             
00067             nb_qtables = AV_RB16(&buf[i + 2]) / 65;
00068             if (i + 4 + nb_qtables * 65 > size) {
00069                 av_log(s1, AV_LOG_ERROR, "Too short JPEG header. Aborted!\n");
00070                 return;
00071             }
00072 
00073             qtables = &buf[i + 4];
00074         } else if (buf[i + 1] == SOF0) {
00075             if (buf[i + 14] != 17 || buf[i + 17] != 17) {
00076                 av_log(s1, AV_LOG_ERROR,
00077                        "Only 1x1 chroma blocks are supported. Aborted!\n");
00078                 return;
00079             }
00080         } else if (buf[i + 1] == SOS) {
00081             
00082             i += AV_RB16(&buf[i + 2]) + 2;
00083             break;
00084         }
00085     }
00086 
00087     
00088     buf  += i;
00089     size -= i;
00090 
00091     for (i = size - 2; i >= 0; i--) {
00092         if (buf[i] == 0xff && buf[i + 1] == EOI) {
00093             
00094             size = i;
00095             break;
00096         }
00097     }
00098 
00099     p = s->buf_ptr;
00100     while (size > 0) {
00101         int hdr_size = 8;
00102 
00103         if (off == 0 && nb_qtables)
00104             hdr_size += 4 + 64 * nb_qtables;
00105 
00106         
00107         len = FFMIN(size, s->max_payload_size - hdr_size);
00108 
00109         
00110         bytestream_put_byte(&p, 0);
00111         bytestream_put_be24(&p, off);
00112         bytestream_put_byte(&p, type);
00113         bytestream_put_byte(&p, 255);
00114         bytestream_put_byte(&p, w);
00115         bytestream_put_byte(&p, h);
00116 
00117         if (off == 0 && nb_qtables) {
00118             
00119             bytestream_put_byte(&p, 0);
00120             bytestream_put_byte(&p, 0);
00121             bytestream_put_be16(&p, 64 * nb_qtables);
00122 
00123             for (i = 0; i < nb_qtables; i++)
00124                 bytestream_put_buffer(&p, &qtables[65 * i + 1], 64);
00125         }
00126 
00127         
00128         memcpy(p, buf, len);
00129 
00130         
00131         ff_rtp_send_data(s1, s->buf, len + hdr_size, size == len);
00132 
00133         buf  += len;
00134         size -= len;
00135         off  += len;
00136         p     = s->buf;
00137     }
00138 }