[NUT-devel] [nut]: r225 - in trunk: libnut/Makefile libnut/framecode.c libnut/libnut.h libnut/muxer.c nututils/nutmerge.c

ods15 subversion at mplayerhq.hu
Fri Nov 17 17:52:05 CET 2006


Author: ods15
Date: Fri Nov 17 17:52:04 2006
New Revision: 225

Added:
   trunk/libnut/framecode.c
Modified:
   trunk/libnut/Makefile
   trunk/libnut/libnut.h
   trunk/libnut/muxer.c
   trunk/nututils/nutmerge.c

Log:
Add framecode table generator, based on guesses on codecs


Modified: trunk/libnut/Makefile
==============================================================================
--- trunk/libnut/Makefile	(original)
+++ trunk/libnut/Makefile	Fri Nov 17 17:52:04 2006
@@ -1,5 +1,7 @@
 include ../config.mak
 
+OBJS = muxer.o demuxer.o reorder.o framecode.o
+
 all: libnut.a
 
 install:
@@ -12,12 +14,12 @@
 	rm -f $(prefix)/lib/libnut.a
 	rm -f $(prefix)/include/libnut.h
 
-libnut.a: muxer.o demuxer.o reorder.o
+libnut.a: ${OBJS}
 	rm -f $@
 	${AR} rc $@ $^
 	$(RANLIB) $@
 
-libnut.so: muxer.o demuxer.o reorder.o
+libnut.so: ${OBJS}
 	${CC} ${CFLAGS} -shared $^ -o $@
 
 .c.o: priv.h nut.h

Added: trunk/libnut/framecode.c
==============================================================================
--- (empty file)
+++ trunk/libnut/framecode.c	Fri Nov 17 17:52:04 2006
@@ -0,0 +1,127 @@
+// (C) 2005-2006 Oded Shimon
+// This file is available under the MIT/X license, see COPYING
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "libnut.h"
+#include "priv.h"
+
+typedef nut_frame_table_input_t fti_t; // just a shortcut
+
+static int count_streams(const nut_stream_header_t * s) {
+	int i;
+	for (i = 0; s[i].type != -1; i++);
+	return i;
+}
+
+void nut_framecode_generate(const nut_stream_header_t s[], nut_frame_table_input_t fti[256]) {
+	int stream_count = count_streams(s);
+	int i, n = 0, m = 0, tot_con = 0;
+	enum {
+		e_consume_none = 0,
+		e_consume_mpeg4,
+		e_consume_h264,
+		e_consume_video,
+		e_consume_vorbis,
+	} consume[stream_count];
+
+	for (i = 0; i < stream_count; i++) consume[i] = e_consume_none;
+
+	// the basic framecodes.                                                flag,  pts, stream, mul, size, count
+	fti[n++] = (fti_t){                            /*invalid 0x00*/ FLAG_INVALID,    0,      0,   1,    0,     1 };
+	fti[n++] = (fti_t){ NUT_FLAG_KEY|FLAG_CODED_PTS|FLAG_STREAM_ID|FLAG_SIZE_MSB,    0,      0,   1,    0,     1 };
+	fti[n++] = (fti_t){              FLAG_CODED_PTS|FLAG_STREAM_ID|FLAG_SIZE_MSB,    0,      0,   1,    0,     1 };
+	fti[n++] = (fti_t){                          /*extreme fallback*/ FLAG_CODED,    1,      0,   1,    0,     1 };
+
+	for (i = 0; i < stream_count; i++) {
+		if (n + m > 230) break; // that's enough! don't overflow
+		switch (s[i].type) {
+		case NUT_VIDEO_CLASS:
+			fti[n++] = (fti_t){ NUT_FLAG_KEY|              FLAG_SIZE_MSB,    1,      i,   1,    0,     1 };
+			fti[n++] = (fti_t){ NUT_FLAG_KEY|FLAG_CHECKSUM|FLAG_SIZE_MSB,    1,      i,   1,    0,     1 };
+			fti[n++] = (fti_t){             FLAG_CODED_PTS|FLAG_SIZE_MSB,    0,      i,   1,    0,     1 };
+			if (s[i].fourcc_len == 4 && !strncmp(s[i].fourcc, "mp4v", 4)) {
+				fti[n++] = (fti_t){                                0,    1,      i,   7,    6,     1 };
+				fti[n++] = (fti_t){                                0,    2,      i,   7,    6,     1 };
+				consume[i] = e_consume_mpeg4;
+			} else if (s[i].fourcc_len == 4 && !strncmp(s[i].fourcc, "h264", 4)) {
+				consume[i] = e_consume_h264;
+			} else {
+				consume[i] = e_consume_video;
+			}
+			break;
+		case NUT_AUDIO_CLASS:
+			fti[n++] = (fti_t){NUT_FLAG_KEY|               FLAG_SIZE_MSB,    1,      i,   1,    0,     1 };
+			fti[n++] = (fti_t){NUT_FLAG_KEY|FLAG_CODED_PTS|FLAG_SIZE_MSB,    0,      i,   1,    0,     1 };
+			if (s[i].fourcc_len == 4 && !strncmp(s[i].fourcc, "mp3 ", 4)) {
+				int j, a[] = {288,336,384,480,576,672,768,960};
+				for (j = 0; j < sizeof a/sizeof*a; j++)
+					fti[n++] = (fti_t){             NUT_FLAG_KEY,    1,   i, a[j]+1, a[j],     1 };
+				fti[n++] = (fti_t){       NUT_FLAG_KEY|FLAG_SIZE_MSB,    1,      i,   4,    0,     1 };
+				fti[n++] = (fti_t){       NUT_FLAG_KEY|FLAG_SIZE_MSB,    1,      i,   4,    2,     1 };
+			} else if (s[i].fourcc_len == 4 && !strncmp(s[i].fourcc, "vrbs", 4)) {
+				fti[n++] = (fti_t){       NUT_FLAG_KEY|FLAG_SIZE_MSB,    2,      i,   1,    0,     1 };
+				fti[n++] = (fti_t){       NUT_FLAG_KEY|FLAG_SIZE_MSB,    9,      i,   1,    0,     1 };
+				fti[n++] = (fti_t){       NUT_FLAG_KEY|FLAG_SIZE_MSB,   23,      i,   1,    0,     1 };
+				fti[n++] = (fti_t){       NUT_FLAG_KEY|FLAG_SIZE_MSB,   16,      i,   6,    0,     6 }; m+=5;
+				consume[i] = e_consume_vorbis;
+			}
+			break;
+		case NUT_SUBTITLE_CLASS:
+			fti[n++] = (fti_t){NUT_FLAG_KEY|FLAG_SIZE_MSB|FLAG_CODED_PTS,    0,      i,   5,    0,     5 }; m+=4;
+			fti[n++] = (fti_t){NUT_FLAG_KEY|NUT_FLAG_EOR| FLAG_CODED_PTS,    0,      i,   1,    0,     1 };
+			break;
+		case NUT_USERDATA_CLASS:
+			fti[n++] = (fti_t){NUT_FLAG_KEY|FLAG_SIZE_MSB|FLAG_CODED_PTS,    0,      i,   1,    0,     1 };
+			fti[n++] = (fti_t){             FLAG_SIZE_MSB|FLAG_CODED_PTS,    0,      i,   1,    0,     1 };
+			break;
+		default:
+			assert(0);
+		}
+	}
+
+	for (i = 0; i < stream_count; i++) if (consume[i]) tot_con++;
+	if (tot_con) for (i = 0; i < stream_count; i++) {
+		int al = (254 - (n+m))/tot_con; // 256 - 'N' - 0xFF invalids
+		switch (consume[i]) {
+		case e_consume_none:
+			break;
+		case e_consume_mpeg4: {
+			int al1 = al*35/100;
+			int al2 = al*45/100;
+			int al3 = al-al1-al2;
+			fti[n++] = (fti_t){                            FLAG_SIZE_MSB,    1,      i, al1,    0,   al1 }; m+=al1-1;
+			fti[n++] = (fti_t){                            FLAG_SIZE_MSB,    2,      i, al2,    0,   al2 }; m+=al2-1;
+			fti[n++] = (fti_t){                            FLAG_SIZE_MSB,   -1,      i, al3,    0,   al3 }; m+=al3-1;
+			break;
+		}
+		case e_consume_h264: {
+			int al1 = al*35/100;
+			int al2 = al*35/100;
+			int al3 = al*20/100;
+			int al4 = al-al1-al2-al3;
+			fti[n++] = (fti_t){                            FLAG_SIZE_MSB,    1,      i, al1,    0,   al1 }; m+=al1-1;
+			fti[n++] = (fti_t){                            FLAG_SIZE_MSB,    2,      i, al2,    0,   al2 }; m+=al2-1;
+			fti[n++] = (fti_t){                            FLAG_SIZE_MSB,   -1,      i, al3,    0,   al3 }; m+=al3-1;
+			fti[n++] = (fti_t){             FLAG_CODED_PTS|FLAG_SIZE_MSB,    0,      i, al4,    0,   al4 }; m+=al4-1;
+			break;
+		}
+		case e_consume_video:
+			fti[n++] = (fti_t){                            FLAG_SIZE_MSB,    1,      i,  al,    0,    al }; m+=al-1;
+			break;
+		case e_consume_vorbis: {
+			int al1 = al*70/100;
+			int al2 = al-al1;
+			al1 /= 2; al2 /= 2;
+			fti[n++] = (fti_t){                             NUT_FLAG_KEY,   16, i,240+al1,240-al1, al1*2 }; m+=al1*2-1;
+			fti[n++] = (fti_t){                             NUT_FLAG_KEY,    2, i, 65+al2, 65-al2, al2*2 }; m+=al2*2-1;
+			break;
+		}
+		}
+	}
+	i = 255-n-m;
+	fti[n++] = (fti_t){                            /*invalid 0xFF*/ FLAG_INVALID,    0,      0,   i,    0,     i };
+	// the final framecode.                                                 flag,  pts, stream, mul, size, count
+	fti[n++] = (fti_t){ -1 };
+}

Modified: trunk/libnut/libnut.h
==============================================================================
--- trunk/libnut/libnut.h	(original)
+++ trunk/libnut/libnut.h	Fri Nov 17 17:52:04 2006
@@ -155,6 +155,9 @@
 void nut_write_frame_reorder(nut_context_t * nut, const nut_packet_t * p, const uint8_t * buf);
 void nut_muxer_uninit_reorder(nut_context_t * nut);
 
+/** generate framecode table input for the muxer. the fallback for the muxer if the muxer option is NULL */
+void nut_framecode_generate(const nut_stream_header_t s[], nut_frame_table_input_t fti[256]);
+
 // Demuxer
 
 /** Just inits stuff, can never fail, except memory error... */

Modified: trunk/libnut/muxer.c
==============================================================================
--- trunk/libnut/muxer.c	(original)
+++ trunk/libnut/muxer.c	Fri Nov 17 17:52:04 2006
@@ -523,6 +523,7 @@
 
 nut_context_t * nut_muxer_init(const nut_muxer_opts_t * mopts, const nut_stream_header_t s[], const nut_info_packet_t info[]) {
 	nut_context_t * nut;
+	nut_frame_table_input_t * fti = mopts->fti, mfti[256];
 	int i, n;
 	// TODO check that all input is valid
 
@@ -549,24 +550,31 @@
 
 	if (nut->max_distance > 65536) nut->max_distance = 65536;
 
+	if (!fti) {
+		nut_framecode_generate(s, mfti);
+		fti = mfti;
+	}
+	fprintf(stderr, "/""/ { %4s, %3s, %6s, %3s, %4s, %5s },\n", "flag", "pts", "stream", "mul", "size", "count");
 	for (n=i=0; i < 256; n++) {
 		int j;
-		assert(mopts->fti[n].flag != -1);
+		assert(fti[n].flag != -1);
 
-		for(j = 0; j < mopts->fti[n].count && i < 256; j++, i++) {
+		fprintf(stderr, "   { %4d, %3d, %6d, %3d, %4d, %5d },\n", fti[n].flag, fti[n].pts, fti[n].stream, fti[n].mul, fti[n].size, fti[n].count);
+		for(j = 0; j < fti[n].count && i < 256; j++, i++) {
 			if (i == 'N') {
 				nut->ft[i].flags = FLAG_INVALID;
 				j--;
 				continue;
 			}
-			nut->ft[i].flags     = mopts->fti[n].flag;
-			nut->ft[i].pts_delta = mopts->fti[n].pts;
-			nut->ft[i].mul       = mopts->fti[n].mul;
-			nut->ft[i].stream    = mopts->fti[n].stream;
-			nut->ft[i].lsb       = mopts->fti[n].size + j;
+			nut->ft[i].flags     = fti[n].flag;
+			nut->ft[i].pts_delta = fti[n].pts;
+			nut->ft[i].mul       = fti[n].mul;
+			nut->ft[i].stream    = fti[n].stream;
+			nut->ft[i].lsb       = fti[n].size + j;
 		}
 	}
-	assert(mopts->fti[n].flag == -1);
+	fprintf(stderr, "   { %4d, %3d, %6d, %3d, %4d, %5d },\n", fti[n].flag, fti[n].pts, fti[n].stream, fti[n].mul, fti[n].size, fti[n].count);
+	assert(fti[n].flag == -1);
 
 	nut->sync_overhead = 0;
 

Modified: trunk/nututils/nutmerge.c
==============================================================================
--- trunk/nututils/nutmerge.c	(original)
+++ trunk/nututils/nutmerge.c	Fri Nov 17 17:52:04 2006
@@ -29,34 +29,6 @@
 	NULL
 };
 
-nut_frame_table_input_t ft_default[] = {
-	// There must be atleast this safety net:
-	//{ 4128,    0,      0,   1,    0,     1 },
-	//{ flag,  pts, stream, mul, size, count }
-	  { 8192,    0,      0,   1,    0,     1 }, // invalid 0x00
-	  {   56,    0,      0,   1,    0,     1 }, // safety net non key frame
-	  {   57,    0,      0,   1,    0,     1 }, // safety net key frame
-	  { 4128,    0,      0,   1,    0,     1 }, // one more safety net
-	  {   27,    0,      0,   1,    0,     1 }, // EOR frame
-	  {    1,    1,      1, 337,  336,     1 }, // used 82427 times
-	  {    1,    1,      1, 385,  384,     1 }, // used 56044 times
-	  {    0,    2,      0,   7,    6,     1 }, // used 20993 times
-	  {    0,    1,      0,   7,    6,     1 }, // used 10398 times
-	  {    1,    1,      1, 481,  480,     1 }, // used 3527 times
-	  {    1,    1,      1, 289,  288,     1 }, // used 2042 times
-	  {    1,    1,      1, 577,  576,     1 }, // used 1480 times
-	  {    1,    1,      1, 673,  672,     1 }, // used 862 times
-	  {    1,    1,      1, 769,  768,     1 }, // used 433 times
-	  {    1,    1,      1, 961,  960,     1 }, // used 191 times
-	  {   32,    2,      0, 101,    0,   101 }, // "1.2.0" => 14187
-	  {   32,   -1,      0,  40,    0,    40 }, // "1.-1.0" => 5707
-	  {   32,    1,      0,  81,    0,    81 }, // "1.1.0" => 11159
-	  {   33,    1,      0,  11,    0,    11 }, // "1.1.1" => 1409
-	  {  105,    0,      0,   6,    0,     6 }, // checksum for video
-	  { 8192,    0,      0,   1,    0,     1 }, // invalid 0xFF
-	  {   -1,    0,      0,   0,    0,     0 }, // end
-};
-
 void push_packet(stream_t * stream, packet_t * p) {
 	if (stream->npackets == stream->packets_alloc) {
 		stream->packets_alloc += 20;
@@ -128,7 +100,7 @@
 	mopts.output = (nut_output_stream_t){ .priv = out, .write = NULL };
 	mopts.write_index = 1;
 	mopts.realtime_stream = 0;
-	mopts.fti = ft_default;
+	mopts.fti = NULL;
 	mopts.max_distance = 32768;
 	mopts.alloc.malloc = NULL;
 	nut = nut_muxer_init(&mopts, nut_stream, NULL);



More information about the NUT-devel mailing list