⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtp-jpeg.c

📁 spook是一个linux下开源的流媒体服务器
💻 C
字号:
/* * Copyright (C) 2004 Nathan Lutchansky <lutchann@litech.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <sys/types.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <fcntl.h>#include <errno.h>#include <event.h>#include <log.h>#include <frame.h>#include <stream.h>#include <outputs.h>#include <rtp.h>#include <rtp_media.h>#include <conf_parse.h>#include <jpeg_tables.h>struct rtp_jpeg {	int type;	int q;	int width;	int height;	int luma_table;	int chroma_table;	unsigned char *quant[16];	unsigned char *scan_data;	int scan_data_len;	int init_done;	int ts_incr;	unsigned int timestamp;};/* Unused at present */static int guess_q( unsigned char lq[] ){	int s = 0, i, count = 0;	s = 100 * lq[0] / jpeg_luma_quantizer[0];#if 0	printf( "Guessed quant scale is %d:\n", s );	for( i = 0; i < 8; ++i )	{		printf( "  " );		for( j = 0; j < 8; ++j )			printf( "%3d ", lq[8*i+j] );		printf( "  " );		for( j = 0; j < 8; ++j )			printf( "%1.2f ", (double)lq[8*i+j] /					(double)jpeg_luma_quantizer[8*i+j] );		printf( "\n" );	}#endif	if( s > 100 ) return 5000 / s;	else return 100 - ( s >> 1 );}static int parse_DQT( struct rtp_jpeg *out, unsigned char *d, int len ){	int i;	for( i = 0; i < len; i += 65 )	{		if( ( d[i] & 0xF0 ) != 0 )		{			printf( "Unsupported quant table precision 0x%X!\n",					d[i] & 0xF0 );			return -1;		}		out->quant[d[i] & 0xF] = d + i + 1;	}	return 0;}static int parse_SOF( struct rtp_jpeg *out, unsigned char *d, int len ){	int c;	out->chroma_table = -1;	if( d[0] != 8 )	{		printf( "Invalid precision %d in SOF0\n", d[0] );		return -1;	}	out->height = GET_16( d + 1 );	out->width = GET_16( d + 3 );	if( ( out->height & 0x7 ) || ( out->width & 0x7 ) )	{		printf( "Width/height not divisible by 8!\n" );		return -1;	}	out->width >>= 3;	out->height >>= 3;	if( d[5] != 3 )	{		printf( "Number of components is %d, not 3!\n", d[5] );		return -1;	}	/* Loop over the parameters for each component */	for( c = 6; c < 6 + 3 * 3; c += 3 )	{		if( d[c + 2] >= 16 || ! out->quant[d[c + 2]] )		{			printf( "Component %d specified undefined quant table %d!\n", d[c], d[c + 2] );			return -1;		}		switch( d[c] ) /* d[c] contains the component ID */		{		case 1: /* Y */			if( d[c + 1] == 0x11 ) out->type = 0;			else if( d[c + 1] == 0x22 ) out->type = 1;			else			{				printf( "Invalid sampling factor 0x%02X in Y component!\n", d[c + 1] );				return -1;			}			out->luma_table = d[c + 2];			break;		case 2: /* Cb */		case 3: /* Cr */			if( d[c + 1] != 0x11 )			{				printf( "Invalid sampling factor 0x%02X in %s component!\n", d[c + 1], d[c] == 2 ? "Cb" : "Cr" );				return -1;			}			if( out->chroma_table < 0 )				out->chroma_table = d[c + 2];			else if( out->chroma_table != d[c + 2] )			{				printf( "Cb and Cr components do not share a quantization table!\n" );				return -1;			}			break;		default:			printf( "Invalid component %d in SOF!\n", d[c] );			return -1;		}	}	return 0;}static int parse_DHT( struct rtp_jpeg *out, unsigned char *d, int len ){	/* We should verify that this coder uses the standard Huffman tables */	return 0;}static int jpeg_process_frame( struct frame *f, void *d ){	struct rtp_jpeg *out = (struct rtp_jpeg *)d;	int i, blen;	for( i = 0; i < 16; ++i ) out->quant[i] = NULL;	for( i = 0; i < f->length; i += blen + 2 )	{		if( f->d[i] != 0xFF )		{			printf( "Found %02X at %d, expecting FF\n", f->d[i], i );			out->scan_data_len = 0;			return 0;		}		/* SOI (FF D8) is a bare marker with no length field */		if( f->d[i + 1] == 0xD8 ) blen = 0;		else blen = GET_16( f->d + i + 2 );		switch( f->d[i + 1] )		{		case 0xDB: /* Quantization Table */			if( parse_DQT( out, f->d + i + 4, blen - 2 ) < 0 )			{				out->scan_data_len = 0;				return 0;			}			break;		case 0xC0: /* Start of Frame */			if( parse_SOF( out, f->d + i + 4, blen - 2 ) < 0 )			{				out->scan_data_len = 0;				return 0;			}			break;		case 0xC4: /* Huffman Table */			if( out->init_done ) break; /* only parse DHT once */			if( parse_DHT( out, f->d + i + 4, blen - 2 ) < 0 )			{				out->scan_data_len = 0;				return 0;			}			out->init_done = 1;			break;		case 0xDA: /* Start of Scan */			out->scan_data = f->d + i + 2 + blen;			out->scan_data_len = f->length - i - 2 - blen;			out->timestamp += out->ts_incr;			return out->init_done;		}	}	printf( "Found no scan data!\n" );	out->scan_data_len = 0;	return 0;}static int jpeg_get_sdp( char *dest, int len, int payload, int port, void *d ){	return snprintf( dest, len, "m=video %d RTP/AVP 26\r\n", port );}static int jpeg_get_payload( int payload, void *d ){	return 26;}static int jpeg_send( struct rtp_endpoint *ep, void *d ){	struct rtp_jpeg *out = (struct rtp_jpeg *)d;	int i, plen, vcnt, hdr_len;	struct iovec v[6];	unsigned char vhdr[8], qhdr[4];	/* Main JPEG header */	vhdr[0] = 0; /* type-specific, value 0 -> non-interlaced frame */	/* vhdr[1..3] is the fragment offset */	vhdr[4] = out->type; /* type */	vhdr[5] = 255; /* Q, value 255 -> dynamic quant tables */	vhdr[6] = out->width;	vhdr[7] = out->height;	v[1].iov_base = vhdr;	v[1].iov_len = 8;	/* Quantization table header */	qhdr[0] = 0; /* MBZ */	qhdr[1] = 0; /* precision */	PUT_16( qhdr + 2, 2 * 64 ); /* length */	v[2].iov_base = qhdr;	v[2].iov_len = 4;	/* Luma quant table */	v[3].iov_base = out->quant[out->luma_table];	v[3].iov_len = 64;	/* Chroma quant table */	v[4].iov_base = out->quant[out->chroma_table];	v[4].iov_len = 64;	hdr_len = 140;	vcnt = 5;	for( i = 0; i < out->scan_data_len; i += plen )	{		plen = out->scan_data_len - i;		if( plen > ep->max_data_size - hdr_len )			plen = ep->max_data_size - hdr_len;		/* No hay PUT_24 macro... */		vhdr[1] = i >> 16;		vhdr[2] = ( i >> 8 ) & 0xff;		vhdr[3] = i & 0xff;		v[vcnt].iov_base = out->scan_data + i;		v[vcnt].iov_len = plen;		if( send_rtp_packet( ep, v, vcnt + 1, out->timestamp,					plen + i == out->scan_data_len ) < 0 )			return -1;		/* Done with all headers except main JPEG header */		vcnt = 2;		hdr_len = 8;	}	return 0;}struct rtp_media *new_rtp_media_jpeg_stream( struct stream *stream ){	struct rtp_jpeg *out;	int fincr, fbase;	stream->get_framerate( stream, &fincr, &fbase );	out = (struct rtp_jpeg *)malloc( sizeof( struct rtp_jpeg ) );	out->init_done = 0;	out->timestamp = 0;	out->ts_incr = 90000 * fincr / fbase;	return new_rtp_media( jpeg_get_sdp, jpeg_get_payload,					jpeg_process_frame, jpeg_send, out );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -