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 }