Below are steps how to test on your local host: wget --no-check-certificate https://samples.ffmpeg.org/MPEG2/interlaced/burosch1.mpg 1. interlace format: ffmpeg -re -i ./burosch1.mpg -c:v bitpacked -pix_fmt yuv422p10 -f rtp rtp://239.255.0.1:6000 copy and create sdp file test.sdp ffplay -buffer_size 671088640 -protocol_whitelist "file,rtp,udp" test.sdp 2. progressive format: ffmpeg -re -i ./burosch1.mpg -vf yadif -c:v bitpacked -pix_fmt yuv422p10 -f rtp rtp://239.255.0.1:6000 copy and create sdp file test.sdp ffplay -buffer_size 671088640 -protocol_whitelist "file,rtp,udp" test.sdp Signed-off-by: Limin Wang <lance.lmwang@gmail.com>
		
			
				
	
	
		
			140 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * RTP Packetization of RAW video (RFC4175)
 | |
|  * Copyright (c) 2021 Limin Wang
 | |
|  *
 | |
|  * This file is part of FFmpeg.
 | |
|  *
 | |
|  * FFmpeg is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Lesser General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2.1 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * FFmpeg is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public
 | |
|  * License along with FFmpeg; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | |
|  */
 | |
| #include "avformat.h"
 | |
| #include "rtpenc.h"
 | |
| 
 | |
| void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size, int interlaced, int field)
 | |
| {
 | |
|     RTPMuxContext *s = s1->priv_data;
 | |
|     int width = s1->streams[0]->codecpar->width;
 | |
|     int height = s1->streams[0]->codecpar->height;
 | |
|     int xinc, yinc, pgroup;
 | |
|     int i = 0;
 | |
|     int offset = 0;
 | |
| 
 | |
|     s->timestamp = s->cur_timestamp;
 | |
|     switch (s1->streams[0]->codecpar->format) {
 | |
|         case AV_PIX_FMT_UYVY422:
 | |
|             xinc = 2;
 | |
|             yinc = 1 << interlaced;
 | |
|             pgroup = 4;
 | |
|             break;
 | |
|         case AV_PIX_FMT_YUV422P10:
 | |
|             xinc = 2;
 | |
|             yinc = 1 << interlaced;
 | |
|             pgroup = 5;
 | |
|             break;
 | |
|         case AV_PIX_FMT_YUV420P:
 | |
|             xinc = 4;
 | |
|             yinc = 1 << interlaced;
 | |
|             pgroup = 6;
 | |
|             break;
 | |
|         case AV_PIX_FMT_RGB24:
 | |
|             xinc = 1;
 | |
|             yinc = 1 << interlaced;
 | |
|             pgroup = 3;
 | |
|             break;
 | |
|         case AV_PIX_FMT_BGR24:
 | |
|             xinc = 1;
 | |
|             yinc = 1 << interlaced;
 | |
|             pgroup = 3;
 | |
|             break;
 | |
|         default:
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     while (i < height) {
 | |
|         int left = s->max_payload_size;
 | |
|         uint8_t *dest = s->buf;
 | |
|         uint8_t *headers;
 | |
|         const int head_size = 6;
 | |
|         int next_line;
 | |
|         int length, cont, pixels;
 | |
| 
 | |
|         /* Extended Sequence Number */
 | |
|         *dest++ = 0;
 | |
|         *dest++ = 0;
 | |
|         left   -= 2;
 | |
| 
 | |
|         headers = dest;
 | |
|         do {
 | |
|             int l_line;
 | |
| 
 | |
|             pixels = width - offset;
 | |
|             length = (pixels * pgroup) / xinc;
 | |
| 
 | |
|             left -= head_size;
 | |
|             if (left >= length) {
 | |
|                 next_line = 1;
 | |
|             } else {
 | |
|                 pixels = (left / pgroup) * xinc;
 | |
|                 length = (pixels * pgroup) / xinc;
 | |
|                 next_line = 0;
 | |
|             }
 | |
|             left -= length;
 | |
| 
 | |
|             /* Length */
 | |
|             *dest++ = (length >> 8) & 0xff;
 | |
|             *dest++ = length & 0xff;
 | |
| 
 | |
|             /* Line No */
 | |
|             l_line = i >> interlaced;
 | |
|             *dest++ = ((l_line >> 8) & 0x7f) | ((field << 7) & 0x80);
 | |
|             *dest++ = l_line & 0xff;
 | |
|             if (next_line) i += yinc;
 | |
| 
 | |
|             cont = (left > (head_size + pgroup) && i < height) ? 0x80 : 0x00;
 | |
|             /* Offset and Continuation marker */
 | |
|             *dest++ = ((offset >> 8) & 0x7f) | cont;
 | |
|             *dest++ = offset & 0xff;
 | |
| 
 | |
|             if (next_line)
 | |
|                 offset  = 0;
 | |
|             else
 | |
|                 offset += pixels;
 | |
|         } while (cont);
 | |
| 
 | |
|         do {
 | |
|             int l_field;
 | |
|             int l_line;
 | |
|             int l_off;
 | |
|             int copy_offset;
 | |
| 
 | |
|             length    = (headers[0] << 8) | headers[1];
 | |
|             l_field   = (headers[2] & 0x80) >> 7;
 | |
|             l_line    = ((headers[2] & 0x7f) << 8) | headers[3];
 | |
|             l_off     = ((headers[4] & 0x7f) << 8) | headers[5];
 | |
|             cont      = headers[4] & 0x80;
 | |
|             headers  += head_size;
 | |
| 
 | |
|             if (interlaced)
 | |
|                 l_line = 2 * l_line + l_field;
 | |
|             copy_offset = (l_line * width + l_off) * pgroup / xinc;
 | |
|             if (copy_offset + length > size)
 | |
|                 break;
 | |
|             memcpy (dest, buf + copy_offset, length);
 | |
|             dest += length;
 | |
|         } while (cont);
 | |
| 
 | |
|         ff_rtp_send_data (s1, s->buf, s->max_payload_size - left, i >= height);
 | |
|     }
 | |
| }
 |