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

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);
participants (1)
-
ods15