1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * RTP JPEG-compressed video Packetizer, RFC 2435 3cabdff1aSopenharmony_ci * Copyright (c) 2012 Samuel Pitoiset 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "libavcodec/bytestream.h" 23cabdff1aSopenharmony_ci#include "libavcodec/mjpeg.h" 24cabdff1aSopenharmony_ci#include "libavcodec/jpegtables.h" 25cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 26cabdff1aSopenharmony_ci#include "rtpenc.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_civoid ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) 29cabdff1aSopenharmony_ci{ 30cabdff1aSopenharmony_ci RTPMuxContext *s = s1->priv_data; 31cabdff1aSopenharmony_ci const uint8_t *qtables[4] = { NULL }; 32cabdff1aSopenharmony_ci int nb_qtables = 0; 33cabdff1aSopenharmony_ci uint8_t type; 34cabdff1aSopenharmony_ci uint8_t w, h; 35cabdff1aSopenharmony_ci uint8_t *p; 36cabdff1aSopenharmony_ci int off = 0; /* fragment offset of the current JPEG frame */ 37cabdff1aSopenharmony_ci int len; 38cabdff1aSopenharmony_ci int i; 39cabdff1aSopenharmony_ci int default_huffman_tables = 0; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci s->buf_ptr = s->buf; 42cabdff1aSopenharmony_ci s->timestamp = s->cur_timestamp; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci /* convert video pixel dimensions from pixels to blocks */ 45cabdff1aSopenharmony_ci w = AV_CEIL_RSHIFT(s1->streams[0]->codecpar->width, 3); 46cabdff1aSopenharmony_ci h = AV_CEIL_RSHIFT(s1->streams[0]->codecpar->height, 3); 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci /* get the pixel format type or fail */ 49cabdff1aSopenharmony_ci if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ422P || 50cabdff1aSopenharmony_ci (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG && 51cabdff1aSopenharmony_ci s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV422P)) { 52cabdff1aSopenharmony_ci type = 0; 53cabdff1aSopenharmony_ci } else if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ420P || 54cabdff1aSopenharmony_ci (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG && 55cabdff1aSopenharmony_ci s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV420P)) { 56cabdff1aSopenharmony_ci type = 1; 57cabdff1aSopenharmony_ci } else { 58cabdff1aSopenharmony_ci av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); 59cabdff1aSopenharmony_ci return; 60cabdff1aSopenharmony_ci } 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci /* preparse the header for getting some info */ 63cabdff1aSopenharmony_ci for (i = 0; i < size; i++) { 64cabdff1aSopenharmony_ci if (buf[i] != 0xff) 65cabdff1aSopenharmony_ci continue; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci if (buf[i + 1] == DQT) { 68cabdff1aSopenharmony_ci int tables, j; 69cabdff1aSopenharmony_ci if (buf[i + 4] & 0xF0) 70cabdff1aSopenharmony_ci av_log(s1, AV_LOG_WARNING, 71cabdff1aSopenharmony_ci "Only 8-bit precision is supported.\n"); 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci /* a quantization table is 64 bytes long */ 74cabdff1aSopenharmony_ci tables = AV_RB16(&buf[i + 2]) / 65; 75cabdff1aSopenharmony_ci if (i + 5 + tables * 65 > size) { 76cabdff1aSopenharmony_ci av_log(s1, AV_LOG_ERROR, "Too short JPEG header. Aborted!\n"); 77cabdff1aSopenharmony_ci return; 78cabdff1aSopenharmony_ci } 79cabdff1aSopenharmony_ci if (nb_qtables + tables > 4) { 80cabdff1aSopenharmony_ci av_log(s1, AV_LOG_ERROR, "Invalid number of quantisation tables\n"); 81cabdff1aSopenharmony_ci return; 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci for (j = 0; j < tables; j++) 85cabdff1aSopenharmony_ci qtables[nb_qtables + j] = buf + i + 5 + j * 65; 86cabdff1aSopenharmony_ci nb_qtables += tables; 87cabdff1aSopenharmony_ci } else if (buf[i + 1] == SOF0) { 88cabdff1aSopenharmony_ci if (buf[i + 14] != 17 || buf[i + 17] != 17) { 89cabdff1aSopenharmony_ci av_log(s1, AV_LOG_ERROR, 90cabdff1aSopenharmony_ci "Only 1x1 chroma blocks are supported. Aborted!\n"); 91cabdff1aSopenharmony_ci return; 92cabdff1aSopenharmony_ci } 93cabdff1aSopenharmony_ci } else if (buf[i + 1] == DHT) { 94cabdff1aSopenharmony_ci int dht_size = AV_RB16(&buf[i + 2]); 95cabdff1aSopenharmony_ci default_huffman_tables |= 1 << 4; 96cabdff1aSopenharmony_ci i += 3; 97cabdff1aSopenharmony_ci dht_size -= 2; 98cabdff1aSopenharmony_ci if (i + dht_size >= size) 99cabdff1aSopenharmony_ci continue; 100cabdff1aSopenharmony_ci while (dht_size > 0) 101cabdff1aSopenharmony_ci switch (buf[i + 1]) { 102cabdff1aSopenharmony_ci case 0x00: 103cabdff1aSopenharmony_ci if ( dht_size >= 29 104cabdff1aSopenharmony_ci && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_luminance + 1, 16) 105cabdff1aSopenharmony_ci && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { 106cabdff1aSopenharmony_ci default_huffman_tables |= 1; 107cabdff1aSopenharmony_ci i += 29; 108cabdff1aSopenharmony_ci dht_size -= 29; 109cabdff1aSopenharmony_ci } else { 110cabdff1aSopenharmony_ci i += dht_size; 111cabdff1aSopenharmony_ci dht_size = 0; 112cabdff1aSopenharmony_ci } 113cabdff1aSopenharmony_ci break; 114cabdff1aSopenharmony_ci case 0x01: 115cabdff1aSopenharmony_ci if ( dht_size >= 29 116cabdff1aSopenharmony_ci && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_chrominance + 1, 16) 117cabdff1aSopenharmony_ci && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { 118cabdff1aSopenharmony_ci default_huffman_tables |= 1 << 1; 119cabdff1aSopenharmony_ci i += 29; 120cabdff1aSopenharmony_ci dht_size -= 29; 121cabdff1aSopenharmony_ci } else { 122cabdff1aSopenharmony_ci i += dht_size; 123cabdff1aSopenharmony_ci dht_size = 0; 124cabdff1aSopenharmony_ci } 125cabdff1aSopenharmony_ci break; 126cabdff1aSopenharmony_ci case 0x10: 127cabdff1aSopenharmony_ci if ( dht_size >= 179 128cabdff1aSopenharmony_ci && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_luminance + 1, 16) 129cabdff1aSopenharmony_ci && !memcmp(buf + i + 18, ff_mjpeg_val_ac_luminance, 162)) { 130cabdff1aSopenharmony_ci default_huffman_tables |= 1 << 2; 131cabdff1aSopenharmony_ci i += 179; 132cabdff1aSopenharmony_ci dht_size -= 179; 133cabdff1aSopenharmony_ci } else { 134cabdff1aSopenharmony_ci i += dht_size; 135cabdff1aSopenharmony_ci dht_size = 0; 136cabdff1aSopenharmony_ci } 137cabdff1aSopenharmony_ci break; 138cabdff1aSopenharmony_ci case 0x11: 139cabdff1aSopenharmony_ci if ( dht_size >= 179 140cabdff1aSopenharmony_ci && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_chrominance + 1, 16) 141cabdff1aSopenharmony_ci && !memcmp(buf + i + 18, ff_mjpeg_val_ac_chrominance, 162)) { 142cabdff1aSopenharmony_ci default_huffman_tables |= 1 << 3; 143cabdff1aSopenharmony_ci i += 179; 144cabdff1aSopenharmony_ci dht_size -= 179; 145cabdff1aSopenharmony_ci } else { 146cabdff1aSopenharmony_ci i += dht_size; 147cabdff1aSopenharmony_ci dht_size = 0; 148cabdff1aSopenharmony_ci } 149cabdff1aSopenharmony_ci break; 150cabdff1aSopenharmony_ci default: 151cabdff1aSopenharmony_ci i += dht_size; 152cabdff1aSopenharmony_ci dht_size = 0; 153cabdff1aSopenharmony_ci continue; 154cabdff1aSopenharmony_ci } 155cabdff1aSopenharmony_ci } else if (buf[i + 1] == SOS) { 156cabdff1aSopenharmony_ci /* SOS is last marker in the header */ 157cabdff1aSopenharmony_ci i += AV_RB16(&buf[i + 2]) + 2; 158cabdff1aSopenharmony_ci if (i > size) { 159cabdff1aSopenharmony_ci av_log(s1, AV_LOG_ERROR, 160cabdff1aSopenharmony_ci "Insufficient data. Aborted!\n"); 161cabdff1aSopenharmony_ci return; 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci break; 164cabdff1aSopenharmony_ci } 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci if (default_huffman_tables && default_huffman_tables != 31) { 167cabdff1aSopenharmony_ci av_log(s1, AV_LOG_ERROR, 168cabdff1aSopenharmony_ci "RFC 2435 requires standard Huffman tables for jpeg\n"); 169cabdff1aSopenharmony_ci return; 170cabdff1aSopenharmony_ci } 171cabdff1aSopenharmony_ci if (nb_qtables && nb_qtables != 2) 172cabdff1aSopenharmony_ci av_log(s1, AV_LOG_WARNING, 173cabdff1aSopenharmony_ci "RFC 2435 suggests two quantization tables, %d provided\n", 174cabdff1aSopenharmony_ci nb_qtables); 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci /* skip JPEG header */ 177cabdff1aSopenharmony_ci buf += i; 178cabdff1aSopenharmony_ci size -= i; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci for (i = size - 2; i >= 0; i--) { 181cabdff1aSopenharmony_ci if (buf[i] == 0xff && buf[i + 1] == EOI) { 182cabdff1aSopenharmony_ci /* Remove the EOI marker */ 183cabdff1aSopenharmony_ci size = i; 184cabdff1aSopenharmony_ci break; 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci } 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci p = s->buf_ptr; 189cabdff1aSopenharmony_ci while (size > 0) { 190cabdff1aSopenharmony_ci int hdr_size = 8; 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci if (off == 0 && nb_qtables) 193cabdff1aSopenharmony_ci hdr_size += 4 + 64 * nb_qtables; 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci /* payload max in one packet */ 196cabdff1aSopenharmony_ci len = FFMIN(size, s->max_payload_size - hdr_size); 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci /* set main header */ 199cabdff1aSopenharmony_ci bytestream_put_byte(&p, 0); 200cabdff1aSopenharmony_ci bytestream_put_be24(&p, off); 201cabdff1aSopenharmony_ci bytestream_put_byte(&p, type); 202cabdff1aSopenharmony_ci bytestream_put_byte(&p, 255); 203cabdff1aSopenharmony_ci bytestream_put_byte(&p, w); 204cabdff1aSopenharmony_ci bytestream_put_byte(&p, h); 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci if (off == 0 && nb_qtables) { 207cabdff1aSopenharmony_ci /* set quantization tables header */ 208cabdff1aSopenharmony_ci bytestream_put_byte(&p, 0); 209cabdff1aSopenharmony_ci bytestream_put_byte(&p, 0); 210cabdff1aSopenharmony_ci bytestream_put_be16(&p, 64 * nb_qtables); 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci for (i = 0; i < nb_qtables; i++) 213cabdff1aSopenharmony_ci bytestream_put_buffer(&p, qtables[i], 64); 214cabdff1aSopenharmony_ci } 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci /* copy payload data */ 217cabdff1aSopenharmony_ci memcpy(p, buf, len); 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci /* marker bit is last packet in frame */ 220cabdff1aSopenharmony_ci ff_rtp_send_data(s1, s->buf, len + hdr_size, size == len); 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci buf += len; 223cabdff1aSopenharmony_ci size -= len; 224cabdff1aSopenharmony_ci off += len; 225cabdff1aSopenharmony_ci p = s->buf; 226cabdff1aSopenharmony_ci } 227cabdff1aSopenharmony_ci} 228