mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	change the interface of video encapsulation routines, they only
need the buffer and mtu as input. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@95263 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -226,107 +226,6 @@ static void fbuf_free(struct fbuf_t *b) | ||||
| 	b->pix_fmt = x.pix_fmt; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Append a chunk of data to a buffer taking care of bit alignment | ||||
|  * Return 0 on success, != 0 on failure | ||||
|  */ | ||||
| static int fbuf_append(struct fbuf_t *b, uint8_t *src, int len, | ||||
| 	int sbit, int ebit) | ||||
| { | ||||
| 	/* | ||||
| 	 * Allocate buffer. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE, | ||||
| 	 * and also wants 0 as a buffer terminator to prevent trouble. | ||||
| 	 */ | ||||
| 	int need = len + FF_INPUT_BUFFER_PADDING_SIZE; | ||||
| 	int i; | ||||
| 	uint8_t *dst, mask; | ||||
|  | ||||
| 	if (b->data == NULL) { | ||||
| 		b->size = need; | ||||
| 		b->used = 0; | ||||
| 		b->ebit = 0; | ||||
| 		b->data = ast_calloc(1, b->size); | ||||
| 	} else if (b->used + need > b->size) { | ||||
| 		b->size = b->used + need; | ||||
| 		b->data = ast_realloc(b->data, b->size); | ||||
| 	} | ||||
| 	if (b->data == NULL) { | ||||
| 		ast_log(LOG_WARNING, "alloc failure for %d, discard\n", | ||||
| 			b->size); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	if (b->used == 0 && b->ebit != 0) { | ||||
| 		ast_log(LOG_WARNING, "ebit not reset at start\n"); | ||||
| 		b->ebit = 0; | ||||
| 	} | ||||
| 	dst = b->data + b->used; | ||||
| 	i = b->ebit + sbit;	/* bits to ignore around */ | ||||
| 	if (i == 0) {	/* easy case, just append */ | ||||
| 		/* do everything in the common block */ | ||||
| 	} else if (i == 8) { /* easy too, just handle the overlap byte */ | ||||
| 		mask = (1 << b->ebit) - 1; | ||||
| 		/* update the last byte in the buffer */ | ||||
| 		dst[-1] &= ~mask;	/* clear bits to ignore */ | ||||
| 		dst[-1] |= (*src & mask);	/* append new bits */ | ||||
| 		src += 1;	/* skip and prepare for common block */ | ||||
| 		len --; | ||||
| 	} else {	/* must shift the new block, not done yet */ | ||||
| 		ast_log(LOG_WARNING, "must handle shift %d %d at %d\n", | ||||
| 			b->ebit, sbit, b->used); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	memcpy(dst, src, len); | ||||
| 	b->used += len; | ||||
| 	b->ebit = ebit; | ||||
| 	b->data[b->used] = 0;	/* padding */ | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * Build an ast_frame for a given chunk of data, and link it into | ||||
|  * the queue, with possibly 'head' bytes at the beginning to | ||||
|  * fill in some fields later. | ||||
|  */ | ||||
| static struct ast_frame *create_video_frame(uint8_t *start, uint8_t *end, | ||||
| 	               int format, int head, struct ast_frame *prev) | ||||
| { | ||||
| 	int len = end-start; | ||||
| 	uint8_t *data; | ||||
| 	struct ast_frame *f; | ||||
|  | ||||
| 	data = ast_calloc(1, len+head); | ||||
| 	f = ast_calloc(1, sizeof(*f)); | ||||
| 	if (f == NULL || data == NULL) { | ||||
| 		ast_log(LOG_WARNING, "--- frame error f %p data %p len %d format %d\n", | ||||
| 				f, data, len, format); | ||||
| 		if (f) | ||||
| 			ast_free(f); | ||||
| 		if (data) | ||||
| 			ast_free(data); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	memcpy(data+head, start, len); | ||||
| 	f->data = data; | ||||
| 	f->mallocd = AST_MALLOCD_DATA | AST_MALLOCD_HDR; | ||||
| 	//f->has_timing_info = 1; | ||||
| 	//f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts); | ||||
| 	f->datalen = len+head; | ||||
| 	f->frametype = AST_FRAME_VIDEO; | ||||
| 	f->subclass = format; | ||||
| 	f->samples = 0; | ||||
| 	f->offset = 0; | ||||
| 	f->src = "Console"; | ||||
| 	f->delivery.tv_sec = 0; | ||||
| 	f->delivery.tv_usec = 0; | ||||
| 	f->seqno = 0; | ||||
| 	AST_LIST_NEXT(f, frame_list) = NULL; | ||||
|  | ||||
| 	if (prev) | ||||
| 	        AST_LIST_NEXT(prev, frame_list) = f; | ||||
|  | ||||
| 	return f; | ||||
| } | ||||
|  | ||||
| #include "vcodecs.c" | ||||
| #include "console_gui.c" | ||||
|  | ||||
| @@ -924,7 +823,7 @@ static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_fra | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	v->enc->enc_run(v); | ||||
| 	return v->enc->enc_encap(v, tail); | ||||
| 	return v->enc->enc_encap(&v->enc_out, v->mtu, tail); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "asterisk.h" | ||||
| #include "console_video.h" | ||||
| #include "asterisk/frame.h" | ||||
| #include "asterisk/utils.h"	/* ast_calloc() */ | ||||
|  | ||||
| struct video_out_desc; | ||||
| struct video_dec_desc; | ||||
| @@ -21,8 +22,7 @@ typedef int (*encoder_init_f)(AVCodecContext *v); | ||||
| typedef int (*encoder_encode_f)(struct video_out_desc *v); | ||||
|  | ||||
| /*! \brief encapsulate the bistream in RTP frames */ | ||||
| /* struct fbuf_t, int mtu, struct ast_frame **tail */ | ||||
| typedef struct ast_frame *(*encoder_encap_f)(struct video_out_desc *out, | ||||
| typedef struct ast_frame *(*encoder_encap_f)(struct fbuf_t *, int mtu, | ||||
| 		struct ast_frame **tail); | ||||
|  | ||||
| /*! \brief inizialize the decoder */ | ||||
| @@ -200,6 +200,107 @@ void dump_buf(struct fbuf_t *b) | ||||
| } | ||||
| #endif /* debugging_only */ | ||||
|  | ||||
| /*! | ||||
|  * Build an ast_frame for a given chunk of data, and link it into | ||||
|  * the queue, with possibly 'head' bytes at the beginning to | ||||
|  * fill in some fields later. | ||||
|  */ | ||||
| static struct ast_frame *create_video_frame(uint8_t *start, uint8_t *end, | ||||
| 	               int format, int head, struct ast_frame *prev) | ||||
| { | ||||
| 	int len = end-start; | ||||
| 	uint8_t *data; | ||||
| 	struct ast_frame *f; | ||||
|  | ||||
| 	data = ast_calloc(1, len+head); | ||||
| 	f = ast_calloc(1, sizeof(*f)); | ||||
| 	if (f == NULL || data == NULL) { | ||||
| 		ast_log(LOG_WARNING, "--- frame error f %p data %p len %d format %d\n", | ||||
| 				f, data, len, format); | ||||
| 		if (f) | ||||
| 			ast_free(f); | ||||
| 		if (data) | ||||
| 			ast_free(data); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	memcpy(data+head, start, len); | ||||
| 	f->data = data; | ||||
| 	f->mallocd = AST_MALLOCD_DATA | AST_MALLOCD_HDR; | ||||
| 	//f->has_timing_info = 1; | ||||
| 	//f->ts = ast_tvdiff_ms(ast_tvnow(), out->ts); | ||||
| 	f->datalen = len+head; | ||||
| 	f->frametype = AST_FRAME_VIDEO; | ||||
| 	f->subclass = format; | ||||
| 	f->samples = 0; | ||||
| 	f->offset = 0; | ||||
| 	f->src = "Console"; | ||||
| 	f->delivery.tv_sec = 0; | ||||
| 	f->delivery.tv_usec = 0; | ||||
| 	f->seqno = 0; | ||||
| 	AST_LIST_NEXT(f, frame_list) = NULL; | ||||
|  | ||||
| 	if (prev) | ||||
| 	        AST_LIST_NEXT(prev, frame_list) = f; | ||||
|  | ||||
| 	return f; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Append a chunk of data to a buffer taking care of bit alignment | ||||
|  * Return 0 on success, != 0 on failure | ||||
|  */ | ||||
| static int fbuf_append(struct fbuf_t *b, uint8_t *src, int len, | ||||
| 	int sbit, int ebit) | ||||
| { | ||||
| 	/* | ||||
| 	 * Allocate buffer. ffmpeg wants an extra FF_INPUT_BUFFER_PADDING_SIZE, | ||||
| 	 * and also wants 0 as a buffer terminator to prevent trouble. | ||||
| 	 */ | ||||
| 	int need = len + FF_INPUT_BUFFER_PADDING_SIZE; | ||||
| 	int i; | ||||
| 	uint8_t *dst, mask; | ||||
|  | ||||
| 	if (b->data == NULL) { | ||||
| 		b->size = need; | ||||
| 		b->used = 0; | ||||
| 		b->ebit = 0; | ||||
| 		b->data = ast_calloc(1, b->size); | ||||
| 	} else if (b->used + need > b->size) { | ||||
| 		b->size = b->used + need; | ||||
| 		b->data = ast_realloc(b->data, b->size); | ||||
| 	} | ||||
| 	if (b->data == NULL) { | ||||
| 		ast_log(LOG_WARNING, "alloc failure for %d, discard\n", | ||||
| 			b->size); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	if (b->used == 0 && b->ebit != 0) { | ||||
| 		ast_log(LOG_WARNING, "ebit not reset at start\n"); | ||||
| 		b->ebit = 0; | ||||
| 	} | ||||
| 	dst = b->data + b->used; | ||||
| 	i = b->ebit + sbit;	/* bits to ignore around */ | ||||
| 	if (i == 0) {	/* easy case, just append */ | ||||
| 		/* do everything in the common block */ | ||||
| 	} else if (i == 8) { /* easy too, just handle the overlap byte */ | ||||
| 		mask = (1 << b->ebit) - 1; | ||||
| 		/* update the last byte in the buffer */ | ||||
| 		dst[-1] &= ~mask;	/* clear bits to ignore */ | ||||
| 		dst[-1] |= (*src & mask);	/* append new bits */ | ||||
| 		src += 1;	/* skip and prepare for common block */ | ||||
| 		len --; | ||||
| 	} else {	/* must shift the new block, not done yet */ | ||||
| 		ast_log(LOG_WARNING, "must handle shift %d %d at %d\n", | ||||
| 			b->ebit, sbit, b->used); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	memcpy(dst, src, len); | ||||
| 	b->used += len; | ||||
| 	b->ebit = ebit; | ||||
| 	b->data[b->used] = 0;	/* padding */ | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Here starts the glue code for the various supported video codecs. | ||||
| @@ -236,12 +337,12 @@ static int h263p_enc_init(AVCodecContext *enc_ctx) | ||||
|  * PSC or a GBSC, but if we don't find a suitable place just break somewhere. | ||||
|  * Everything is byte-aligned. | ||||
|  */ | ||||
| static struct ast_frame *h263p_encap(struct video_out_desc *out, | ||||
| static struct ast_frame *h263p_encap(struct fbuf_t *b, int mtu, | ||||
| 	struct ast_frame **tail) | ||||
| { | ||||
| 	struct ast_frame *cur = NULL, *first = NULL; | ||||
| 	uint8_t *d = out->enc_out.data; | ||||
| 	int len = out->enc_out.used; | ||||
| 	uint8_t *d = b->data; | ||||
| 	int len = b->used; | ||||
| 	int l = len; /* size of the current fragment. If 0, must look for a psc */ | ||||
|  | ||||
| 	for (;len > 0; len -= l, d += l) { | ||||
| @@ -258,10 +359,10 @@ static struct ast_frame *h263p_encap(struct video_out_desc *out, | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (l > out->mtu || l > len) { /* psc not found, split */ | ||||
| 			l = MIN(len, out->mtu); | ||||
| 		if (l > mtu || l > len) { /* psc not found, split */ | ||||
| 			l = MIN(len, mtu); | ||||
| 		} | ||||
| 		if (l < 1 || l > out->mtu) { | ||||
| 		if (l < 1 || l > mtu) { | ||||
| 			ast_log(LOG_WARNING, "--- frame error l %d\n", l); | ||||
| 			break; | ||||
| 		} | ||||
| @@ -451,11 +552,11 @@ static int h263_enc_init(AVCodecContext *enc_ctx) | ||||
|  *  | ||||
|  * The assumption below is that we start with a PSC. | ||||
|  */ | ||||
| static struct ast_frame *h263_encap(struct video_out_desc *out, | ||||
| static struct ast_frame *h263_encap(struct fbuf_t *b, int mtu, | ||||
| 		struct ast_frame **tail) | ||||
| { | ||||
| 	uint8_t *d = out->enc_out.data; | ||||
| 	int start = 0, i, len = out->enc_out.used; | ||||
| 	uint8_t *d = b->data; | ||||
| 	int start = 0, i, len = b->used; | ||||
| 	struct ast_frame *f, *cur = NULL, *first = NULL; | ||||
| 	const int pheader_len = 4;	/* Use RFC-2190 Mode A */ | ||||
| 	uint8_t h263_hdr[12];	/* worst case, room for a type c header */ | ||||
| @@ -605,11 +706,11 @@ static int h261_enc_init(AVCodecContext *enc_ctx) | ||||
|  * with MacroBlock fragmentation. However it is likely that blocks | ||||
|  * are not bit-aligned so we must take care of this. | ||||
|  */ | ||||
| static struct ast_frame *h261_encap(struct video_out_desc *out, | ||||
| static struct ast_frame *h261_encap(struct fbuf_t *b, int mtu, | ||||
| 		struct ast_frame **tail) | ||||
| { | ||||
| 	uint8_t *d = out->enc_out.data; | ||||
| 	int start = 0, i, len = out->enc_out.used; | ||||
| 	uint8_t *d = b->data; | ||||
| 	int start = 0, i, len = b->used; | ||||
| 	struct ast_frame *f, *cur = NULL, *first = NULL; | ||||
| 	const int pheader_len = 4; | ||||
| 	uint8_t h261_hdr[4]; | ||||
| @@ -656,7 +757,7 @@ static struct ast_frame *h261_encap(struct video_out_desc *out, | ||||
| 			/* now we have a GBSC starting somewhere in d[i-1], | ||||
| 			 * but it might be not byte-aligned. Just remember it. | ||||
| 			 */ | ||||
| 			if (i - start > out->mtu) /* too large, stop now */ | ||||
| 			if (i - start > mtu) /* too large, stop now */ | ||||
| 				break; | ||||
| 			found_ebit = ebit; | ||||
| 			found = i; | ||||
| @@ -666,7 +767,7 @@ static struct ast_frame *h261_encap(struct video_out_desc *out, | ||||
| 			i = len; | ||||
| 			ebit = 0;	/* hopefully... should ask the bitstream ? */ | ||||
| 		} | ||||
| 		if (i - start > out->mtu && found) { | ||||
| 		if (i - start > mtu && found) { | ||||
| 			/* use the previous GBSC, hope is within the mtu */ | ||||
| 			i = found; | ||||
| 			ebit = found_ebit; | ||||
| @@ -747,17 +848,17 @@ static int mpeg4_enc_init(AVCodecContext *enc_ctx) | ||||
| } | ||||
|  | ||||
| /* simplistic encapsulation - just split frames in mtu-size units */ | ||||
| static struct ast_frame *mpeg4_encap(struct  video_out_desc *out, | ||||
| static struct ast_frame *mpeg4_encap(struct fbuf_t *b, int mtu, | ||||
| 	struct ast_frame **tail) | ||||
| { | ||||
| 	struct ast_frame *f, *cur = NULL, *first = NULL; | ||||
| 	uint8_t *d = out->enc_out.data; | ||||
| 	uint8_t *end = d+out->enc_out.used; | ||||
| 	uint8_t *d = b->data; | ||||
| 	uint8_t *end = d + b->used; | ||||
| 	int len; | ||||
|  | ||||
| 	for (;d < end; d += len, cur = f) { | ||||
| 		len = MIN(out->mtu, end-d); | ||||
| 		f = create_video_frame(d, d+len, AST_FORMAT_MP4_VIDEO, 0, cur); | ||||
| 		len = MIN(mtu, end - d); | ||||
| 		f = create_video_frame(d, d + len, AST_FORMAT_MP4_VIDEO, 0, cur); | ||||
| 		if (!f) | ||||
| 			break; | ||||
| 		if (!first) | ||||
| @@ -835,12 +936,12 @@ static int h264_dec_init(AVCodecContext *dec_ctx) | ||||
|  * If fragments are too long... we don't support it yet. | ||||
|  * - encapsulate (or fragment) the byte-stream (with NAL header included) | ||||
|  */ | ||||
| static struct ast_frame *h264_encap(struct video_out_desc *out, | ||||
| static struct ast_frame *h264_encap(struct fbuf_t *b, int mtu, | ||||
| 	struct ast_frame **tail) | ||||
| { | ||||
| 	struct ast_frame *f = NULL, *cur = NULL, *first = NULL; | ||||
| 	uint8_t *d, *start = out->enc_out.data; | ||||
| 	uint8_t *end = start + out->enc_out.used; | ||||
| 	uint8_t *d, *start = b->data; | ||||
| 	uint8_t *end = start + b->used; | ||||
|  | ||||
| 	/* Search the first start code prefix - ITU-T H.264 sec. B.2, | ||||
| 	 * and move start right after that, on the NAL header byte. | ||||
| @@ -872,13 +973,13 @@ static struct ast_frame *h264_encap(struct video_out_desc *out, | ||||
| 		d = end + 4; | ||||
| 	} else if (ty == 0 || ty == 31) { /* found but invalid type, skip */ | ||||
| 		ast_log(LOG_WARNING, "skip invalid nal type %d at %d of %d\n", | ||||
| 			ty, d - out->enc_out.data, out->enc_out.used); | ||||
| 			ty, d - (uint8_t *)b->data, b->used); | ||||
| 		continue; | ||||
| 	} | ||||
|  | ||||
| 	size = d - start - 4;	/* don't count the end */ | ||||
|  | ||||
| 	if (size < out->mtu) {	// test - don't fragment | ||||
| 	if (size < mtu) {	// test - don't fragment | ||||
| 		// Single NAL Unit | ||||
| 		f = create_video_frame(start, d - 4, AST_FORMAT_H264, 0, cur); | ||||
| 		if (!f) | ||||
| @@ -896,7 +997,7 @@ static struct ast_frame *h264_encap(struct video_out_desc *out, | ||||
| 	size--;		/* skip the NAL header */ | ||||
| 	while (size) { | ||||
| 		uint8_t *data; | ||||
| 		int frag_size = MIN(size, out->mtu); | ||||
| 		int frag_size = MIN(size, mtu); | ||||
|  | ||||
| 		f = create_video_frame(start, start+frag_size, AST_FORMAT_H264, 2, cur); | ||||
| 		if (!f) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user