[Avidemux-svn-commit] r3582 - in branches/avidemux_2.4_branch: . avidemux avidemux/ADM_editor avidemux/ADM_filter avidemux/ADM_libraries/ADM_lavcodec avidemux/ADM_libraries/ADM_lavformat avidemux/ADM_libraries/ADM_lavutil avidemux/ADM_outputs/oplug_mp4 avidemux/ADM_script avidemux/ADM_video

mean at BerliOS mean at mail.berlios.de
Sat Sep 8 12:54:37 CEST 2007


Author: mean
Date: 2007-09-08 12:54:35 +0200 (Sat, 08 Sep 2007)
New Revision: 3582

Added:
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/xiph.c
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroskaenc.c
Modified:
   branches/avidemux_2.4_branch/avidemux/ADM_editor/ADM_outputfmt.h
   branches/avidemux_2.4_branch/avidemux/ADM_filter/filter.cpp
   branches/avidemux_2.4_branch/avidemux/ADM_filter/filter_declaration.cpp
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/CMakeLists.txt
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/Makefile.am
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/utils.c
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.cpp
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.h
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/CMakeLists.txt
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/Makefile.am
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.c
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.h
   branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavutil/crc.h
   branches/avidemux_2.4_branch/avidemux/ADM_outputs/oplug_mp4/oplug_mp4.cpp
   branches/avidemux_2.4_branch/avidemux/ADM_script/ADM_container.h
   branches/avidemux_2.4_branch/avidemux/ADM_video/ADM_genvideo.hxx
   branches/avidemux_2.4_branch/avidemux/gui_savenew.cpp
   branches/avidemux_2.4_branch/config.h.cmake
   branches/avidemux_2.4_branch/configure.in.in
Log:
[Output Format] Matroska output, VERY incomplete

Modified: branches/avidemux_2.4_branch/avidemux/ADM_editor/ADM_outputfmt.h
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_editor/ADM_outputfmt.h	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_editor/ADM_outputfmt.h	2007-09-08 10:54:35 UTC (rev 3582)
@@ -24,9 +24,9 @@
 	ADM_OGM,
 	ADM_PSP,
 	ADM_FLV,
+        ADM_MATROSKA,
 	ADM_DUMMY,
 	ADM_FORMAT_MAX,
-	ADM_FMT_DUMMY=ADM_FORMAT_MAX
 }ADM_OUT_FORMAT;
 
 typedef struct 
@@ -50,6 +50,7 @@
   {ADM_OGM,_("OGM")},
   {ADM_PSP,_("PSP")},
   {ADM_FLV,_("FLV")},
+  {ADM_MATROSKA,_("MKV")},
   {ADM_DUMMY,_("DUMMY")}
 };
 

Modified: branches/avidemux_2.4_branch/avidemux/ADM_filter/filter.cpp
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_filter/filter.cpp	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_filter/filter.cpp	2007-09-08 10:54:35 UTC (rev 3582)
@@ -100,7 +100,7 @@
 	for(uint32_t i=0;i<allfilters.size();i++)
 	{
 		name=allfilters[ i].filtername;
-		if(allfilters[ i].viewable)
+		if(allfilters[ i].viewable || allfilters[i].tag==VF_PARTIAL)
 		{
 			if(name)
 			{
@@ -323,55 +323,106 @@
 {
 int found,l;
 int trans[MAXPARAM];
-	if(nb!=param->nb)
+	if(param->nb>VARIABLE_PARAMS)
 	{
-		printf("# of parameters mismatch\n");
-		return NULL;
+		// Variable # of parameters
+		// We check we have at least what is required by the template
+		for(int i=0;i<(param->nb-VARIABLE_PARAMS);i++)
+				{
+					l=strlen(param->param[i]);
+					ADM_assert(l);
+					found=-1;
+					for(int j=0;j<nb;j++)
+					{
+						if(!strncasecmp(param->param[i],args[j].arg.string,l))
+						{
+							if(strlen(args[j].arg.string)>l && args[j].arg.string[l]=='=')
+							{
+								found=j;
+								break;
+							}
+						}
+					}
+					if(found==-1)
+					{	
+						printf("Param : %s not found or incorrect\n",param->param[i]);
+						 return NULL;
+					}
+				}
+				// if we get here, it means we found each param, time to build the couples
+				CONFcouple *couple;
+				couple=new CONFcouple(nb);
+				for(int i=0;i<nb;i++)
+				{
+					char *copy=ADM_strdup(args[i].arg.string);
+					// Search "="
+					char *where=strstr(copy,"=");
+					if(!where) ADM_assert(0);
+					*where=0;
+					if(!couple->setCouple(copy,where+1))
+						{
+							printf("Set couple failed\n");
+							delete couple;
+							return NULL;
+						}
+					ADM_dealloc(copy);
+				}
+				return couple;
 	}
-	// For each param check we are ok
-	// the generic form is name=value
-	// name should be the same as in the param array
-	for(int i=0;i<nb;i++)
+	//********************* Constant # of parameters #################
+	else
 	{
-		l=strlen(param->param[i]);
-		ADM_assert(l);
-		found=-1;
-		for(int j=0;j<nb;j++)
+		if(nb!=param->nb )
 		{
-			if(!strncasecmp(param->param[i],args[j].arg.string,l))
+			printf("# of parameters mismatch: expected %d, got %d\n",nb,param->nb);
+			return NULL;
+		}
+		// For each param check we are ok
+		// the generic form is name=value
+		// name should be the same as in the param array
+		for(int i=0;i<nb;i++)
+		{
+			l=strlen(param->param[i]);
+			ADM_assert(l);
+			found=-1;
+			for(int j=0;j<nb;j++)
 			{
-				if(strlen(args[j].arg.string)>l && args[j].arg.string[l]=='=')
+				if(!strncasecmp(param->param[i],args[j].arg.string,l))
 				{
-					found=j;
-					trans[i]=j;
-					break;
+					if(strlen(args[j].arg.string)>l && args[j].arg.string[l]=='=')
+					{
+						found=j;
+						trans[i]=j;
+						break;
+					}
 				}
 			}
+			if(found==-1)
+			{	
+				printf("Param : %s not found or incorrect\n",param->param[i]);
+				 return NULL;
+			}
 		}
-		if(found==-1)
-		{	
-			printf("Param : %s not found or incorrect\n",param->param[i]);
-			 return NULL;
+		// if we get here, it means we found each param, time to build the couples
+		CONFcouple *couple;
+		couple=new CONFcouple(nb);
+		for(int i=0;i<nb;i++)
+		{
+			l=strlen(param->param[i]);
+			if(!couple->setCouple(param->param[i],args[ trans[i]].arg.string+l+1))
+				{
+					printf("Set couple failed\n");
+					delete couple;
+					return NULL;
+				}
 		}
+		return couple;
 	}
-	// if we get here, it means we found each param, time to build the couples
-	CONFcouple *couple;
-	couple=new CONFcouple(nb);
-	for(int i=0;i<nb;i++)
-	{
-		l=strlen(param->param[i]);
-		if(!couple->setCouple(param->param[i],args[ trans[i]].arg.string+l+1))
-			{
-				printf("Set couple failed\n");
-				delete couple;
-				return NULL;
-			}
-	}
-	return couple;
+	
 }
 uint8_t 	filterAddScript(VF_FILTERS tag,uint32_t n,Arg *args)
 {
-	// 1- searc filter
+	// 1- search filter
 	int found=-1;
 	aviInfo info;
 
@@ -403,7 +454,7 @@
 			return 1;
 		}
 	}
-	printf("Tag not found\n");
+	printf("Tag not found:%d\n",tag);
 	return 0;
 }
 

Modified: branches/avidemux_2.4_branch/avidemux/ADM_filter/filter_declaration.cpp
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_filter/filter_declaration.cpp	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_filter/filter_declaration.cpp	2007-09-08 10:54:35 UTC (rev 3582)
@@ -177,7 +177,7 @@
 // Does not work
 //        REGISTERX("unblend","Unblend by Bach",VF_UNBLEND,1,unblend_create,unblend_script);
         
-        REGISTER("","Partial","",VF_PARTIAL,0,partial_create);
+        REGISTERX("partial","Partial","",VF_PARTIAL,0,partial_create,partial_script);
 //	REGISTER("","Remove Salt",VF_SALT,0,salt_create);
  printf("\n");
 }		

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/CMakeLists.txt
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/CMakeLists.txt	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/CMakeLists.txt	2007-09-08 10:54:35 UTC (rev 3582)
@@ -30,7 +30,7 @@
                 wma.c
                 dvbsub_parser.c
                 dvbsubdec.c
-                dvbsub.c
+                dvbsub.c xiph.c
 )
 # ADD x86 ones
 

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/Makefile.am
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/Makefile.am	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/Makefile.am	2007-09-08 10:54:35 UTC (rev 3582)
@@ -69,7 +69,7 @@
                 wma.c \
                 dvbsub_parser.c \
                 dvbsubdec.c \
-                dvbsub.c
+                dvbsub.c xiph.c
 
 	
 

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/utils.c
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/utils.c	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/utils.c	2007-09-08 10:54:35 UTC (rev 3582)
@@ -147,6 +147,8 @@
     uint8_t *base[4];
     uint8_t *data[4];
     int linesize[4];
+    int width, height;
+    enum PixelFormat pix_fmt;
 }InternalBuffer;
 
 #define INTERNAL_BUFFER_SIZE 32
@@ -251,6 +253,13 @@
     picture_number= &(((InternalBuffer*)s->internal_buffer)[INTERNAL_BUFFER_SIZE-1]).last_pic_num; //FIXME ugly hack
     (*picture_number)++;
 
+    if(buf->base[0] && (buf->width != w || buf->height != h || buf->pix_fmt != s->pix_fmt)){
+        for(i=0; i<4; i++){
+            av_freep(&buf->base[i]);
+            buf->data[i]= NULL;
+        }
+    }
+
     if(buf->base[0]){
         pic->age= *picture_number - buf->last_pic_num;
         buf->last_pic_num= *picture_number;
@@ -306,6 +315,9 @@
             else
                 buf->data[i] = buf->base[i] + ALIGN((buf->linesize[i]*EDGE_WIDTH>>v_shift) + (EDGE_WIDTH>>h_shift), STRIDE_ALIGN);
         }
+        buf->width  = s->width;
+        buf->height = s->height;
+        buf->pix_fmt= s->pix_fmt;
         pic->age= 256*256*256*64;
     }
     pic->type= FF_BUFFER_TYPE_INTERNAL;
@@ -741,6 +753,7 @@
 {"timecode_frame_start", "GOP timecode frame start number, in non drop frame format", OFFSET(timecode_frame_start), FF_OPT_TYPE_INT, 0, 0, INT_MAX, V|E},
 {"drop_frame_timecode", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_DROP_FRAME_TIMECODE, INT_MIN, INT_MAX, V|E, "flags2"},
 {"non_linear_q", "use non linear quantizer", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_NON_LINEAR_QUANT, INT_MIN, INT_MAX, V|E, "flags2"},
+// MEANX {"request_channels", "set desired number of audio channels", OFFSET(request_channels), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, A|D},
 {NULL},
 };
 
@@ -759,6 +772,7 @@
 
     s->av_class= &av_codec_context_class;
 
+    s->codec_type = codec_type;
     if(codec_type == CODEC_TYPE_AUDIO)
         flags= AV_OPT_FLAG_AUDIO_PARAM;
     else if(codec_type == CODEC_TYPE_VIDEO)
@@ -831,8 +845,10 @@
 
     if (codec->priv_data_size > 0) {
         avctx->priv_data = av_mallocz(codec->priv_data_size);
-        if (!avctx->priv_data)
+        if (!avctx->priv_data) {
+            ret = AVERROR(ENOMEM);
             goto end;
+        }
     } else {
         avctx->priv_data = NULL;
     }
@@ -844,6 +860,7 @@
 
     if((avctx->coded_width||avctx->coded_height) && avcodec_check_dimensions(avctx,avctx->coded_width,avctx->coded_height)){
         av_freep(&avctx->priv_data);
+        ret = AVERROR(EINVAL);
         goto end;
     }
 
@@ -938,7 +955,7 @@
 
     if((avctx->codec->capabilities & CODEC_CAP_DELAY) || buf_size){
         //FIXME remove the check below _after_ ensuring that all audio check that the available space is enough
-#if 0 // MEANX SILENCE!
+#if 0 // MEANX : Silence
         if(*frame_size_ptr < AVCODEC_MAX_AUDIO_FRAME_SIZE){
             av_log(avctx, AV_LOG_ERROR, "buffer smaller than AVCODEC_MAX_AUDIO_FRAME_SIZE\n");
             return -1;
@@ -1221,9 +1238,9 @@
     av_crc8005    = av_mallocz_static(sizeof(AVCRC) * 257);
     av_crc07      = av_mallocz_static(sizeof(AVCRC) * 257);
 #endif
-    av_crc_init(av_crc04C11DB7, 0, 32, 0x04c11db7, sizeof(AVCRC)*257);
-    av_crc_init(av_crc8005    , 0, 16, 0x8005    , sizeof(AVCRC)*257);
-    av_crc_init(av_crc07      , 0,  8, 0x07      , sizeof(AVCRC)*257);
+    av_crc_init(av_crc04C11DB7, 0, 32, AV_CRC_32_IEEE, sizeof(AVCRC)*257);
+    av_crc_init(av_crc8005    , 0, 16, AV_CRC_16     , sizeof(AVCRC)*257);
+    av_crc_init(av_crc07      , 0,  8, AV_CRC_8_ATM  , sizeof(AVCRC)*257);
 }
 
 void avcodec_init(void)
@@ -1308,6 +1325,22 @@
     }
 }
 
+int av_get_bits_per_sample_format(enum SampleFormat sample_fmt) {
+    switch (sample_fmt) {
+    case SAMPLE_FMT_U8:
+        return 8;
+    case SAMPLE_FMT_S16:
+        return 16;
+    case SAMPLE_FMT_S24:
+        return 24;
+    case SAMPLE_FMT_S32:
+    case SAMPLE_FMT_FLT:
+        return 32;
+    default:
+        return 0;
+    }
+}
+
 #if !defined(HAVE_THREADS)
 int avcodec_thread_init(AVCodecContext *s, int thread_count){
     return -1;
@@ -1347,7 +1380,7 @@
         return -1;
     }
 #if !defined(HAVE_MKSTEMP)
-    fd = open(*filename, O_RDWR | /* MEANX ??O_BINARY |*/ O_CREAT, 0444);
+    fd = open(*filename, O_RDWR /* MEANX | O_BINARY*/ | O_CREAT, 0444);
 #else
     snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
     fd = mkstemp(*filename);

Added: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/xiph.c
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/xiph.c	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavcodec/xiph.c	2007-09-08 10:54:35 UTC (rev 3582)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007  FFmpeg Project
+ *
+ * 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 "xiph.h"
+
+int ff_split_xiph_headers(uint8_t *extradata, int extradata_size,
+                          int first_header_size, uint8_t *header_start[3],
+                          int header_len[3])
+{
+    int i, j;
+
+    if (AV_RB16(extradata) == first_header_size) {
+        for (i=0; i<3; i++) {
+            header_len[i] = AV_RB16(extradata);
+            extradata += 2;
+            header_start[i] = extradata;
+            extradata += header_len[i];
+        }
+    } else if (extradata[0] == 2) {
+        for (i=0,j=1; i<2; i++,j++) {
+            header_len[i] = 0;
+            for (; j<extradata_size && extradata[j]==0xff; j++) {
+                header_len[i] += 0xff;
+            }
+            if (j >= extradata_size)
+                return -1;
+
+            header_len[i] += extradata[j];
+        }
+        header_len[2] = extradata_size - header_len[0] - header_len[1] - j;
+        extradata += j;
+        header_start[0] = extradata;
+        header_start[1] = header_start[0] + header_len[0];
+        header_start[2] = header_start[1] + header_len[1];
+    } else {
+        return -1;
+    }
+    return 0;
+}

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.cpp
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.cpp	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.cpp	2007-09-08 10:54:35 UTC (rev 3582)
@@ -130,12 +130,17 @@
 	case MUXER_FLV:
 		fmt = guess_format("flv", NULL, NULL);
 		break;          
+	case MUXER_MATROSKA:
+		fmt = guess_format("matroska", NULL, NULL);
+		break;          
+
 	default:
 		fmt=NULL;
 	}
 	if (!fmt) 
 	{
         	printf("Lav:Cannot guess format\n");
+                ADM_assert(0);
 		return 0;
 	}
 	oc = av_alloc_format_context();
@@ -179,6 +184,32 @@
 					 }
 					 
 					 break;
+                case MUXER_MATROSKA:
+                        strcpy(oc->title,"Avidemux");
+                        strcpy(oc->author,"Avidemux");
+                        c->sample_aspect_ratio.num=1;
+                        c->sample_aspect_ratio.den=1;
+                        if(isMpeg4Compatible(info->fcc))
+                        {
+                                c->codec_id = CODEC_ID_MPEG4;
+                                c->has_b_frames=1; // in doubt...
+                        }else
+                        {
+                                if(isH264Compatible(info->fcc))
+                                {
+                                        c->has_b_frames=1; // in doubt...
+                                        c->codec_id = CODEC_ID_H264;
+                                        c->codec=new AVCodec;
+                                        memset(c->codec,0,sizeof(AVCodec));
+                                        c->codec->name=ADM_strdup("H264");
+                                }
+                        }
+                        if(videoExtraDataSize)
+                        {
+                                c->extradata=videoExtraData;
+                                c->extradata_size= videoExtraDataSize;
+                        }
+                        break;
                 case MUXER_MP4:
                 case MUXER_PSP:
                         strcpy(oc->title,"Avidemux");
@@ -321,7 +352,7 @@
 			break;
 		default:
                       {
-                            if(_type==MUXER_MP4 || _type==MUXER_PSP || _type==MUXER_FLV)
+                            if(_type==MUXER_MP4 || _type==MUXER_PSP || _type==MUXER_FLV || _type==MUXER_MATROSKA)
                             {
                                     c->time_base=fpsfree;// (AVRational){1000,_fps1000};
                                     break;
@@ -407,6 +438,7 @@
 				case MUXER_FLV:
                 case MUXER_PSP:
                 case MUXER_MP4:
+                case MUXER_MATROSKA:
                         oc->mux_rate=10080*1000; // Needed ?
                         break;
 
@@ -473,7 +505,7 @@
 
             timeInUs=(int64_t)sample2time_us(sample);
             /* Rescale to ?? */
-            if(_type==MUXER_FLV) /* The FLV muxer expects packets dated in ms, there is something i did not get... WTF */
+            if(_type==MUXER_FLV || _type==MUXER_MATROSKA) /* The FLV muxer expects packets dated in ms, there is something i did not get... WTF */
             {
             			f=timeInUs/1000;
             			f=floor(f+0.4);
@@ -567,7 +599,7 @@
         d=bitstream->dtsFrame;
         RESCALE(d);
         
-        if(_type==MUXER_FLV) /* The FLV muxer expects packets dated in ms, there is something i did not get... WTF */
+        if(_type==MUXER_FLV || _type==MUXER_MATROSKA) /* The FLV muxer expects packets dated in ms, there is something i did not get... WTF */
         {
         			p=p*1000/_fps1000;
         			d=d*1000/_fps1000;
@@ -646,12 +678,14 @@
      extern  int        mpegps_init(void );
      extern  int        movenc_init(void );
      extern  int        flvenc_init(void );
+     extern  int        matroskaenc_init(void );
 };
 extern URLProtocol file_protocol ;
 uint8_t lavformat_init(void)
 {
                 movenc_init();
                 flvenc_init();
+                matroskaenc_init();
                 register_protocol(&file_protocol);
 }
 extern "C"

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.h
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.h	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/ADM_lavformat.h	2007-09-08 10:54:35 UTC (rev 3582)
@@ -24,6 +24,7 @@
         MUXER_MP4,
         MUXER_PSP,
         MUXER_FLV,
+        MUXER_MATROSKA,
         MUXER_DUMMY
 }ADM_MUXER_TYPE;
 

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/CMakeLists.txt
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/CMakeLists.txt	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/CMakeLists.txt	2007-09-08 10:54:35 UTC (rev 3582)
@@ -8,7 +8,7 @@
  mpeg.c utils.c avio.c ADM_lavformat.cpp 
 aviobuf.c cutils.c img2.c file.c mpegtsenc.c ADM_muxts.cpp movenc.c 
 avienc.c wav.c mov.c matroska.c isom.c isom.h riff.c
-flvenc.c
+flvenc.c matroskaenc.c
 )
 ADD_LIBRARY(${ADM_LIB} STATIC ${${ADM_LIB}_SRCS})
 ADD_ADM_LIB(${ADM_LIB} ADM_libraries)

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/Makefile.am
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/Makefile.am	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/Makefile.am	2007-09-08 10:54:35 UTC (rev 3582)
@@ -6,7 +6,8 @@
 
 libADM_lavformat_a_SOURCES =  mpeg.c utils.c avio.c ADM_lavformat.cpp \
 aviobuf.c cutils.c img2.c file.c mpegtsenc.c ADM_muxts.cpp movenc.c \
-avienc.c wav.c mov.c matroska.c isom.c isom.h riff.c flvenc.c
+avienc.c wav.c mov.c matroska.c isom.c isom.h riff.c flvenc.c \
+matroskaenc.c
 
 
 EXTRA_DIST = ADM_lavformat.cpp  ADM_muxts.cpp  avformat.h  avio.h   \

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.c
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.c	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.c	2007-09-08 10:54:35 UTC (rev 3582)
@@ -24,8 +24,8 @@
 CodecTags ff_mkv_codec_tags[]={
 //    {"V_MS/VFW/FOURCC"  , CODEC_ID_NONE},
     {"V_UNCOMPRESSED"   , CODEC_ID_RAWVIDEO},
+    {"V_MPEG4/ISO/ASP"  , CODEC_ID_MPEG4},
     {"V_MPEG4/ISO/SP"   , CODEC_ID_MPEG4},
-    {"V_MPEG4/ISO/ASP"  , CODEC_ID_MPEG4},
     {"V_MPEG4/ISO/AP"   , CODEC_ID_MPEG4},
     {"V_MPEG4/ISO/AVC"  , CODEC_ID_H264},
     {"V_MPEG4/MS/V3"    , CODEC_ID_MSMPEG4V3},
@@ -37,12 +37,13 @@
     {"V_REAL/RV30"      , CODEC_ID_RV30},
     {"V_REAL/RV40"      , CODEC_ID_RV40},
     {"V_THEORA"         , CODEC_ID_THEORA},
+    {"V_SNOW"           , CODEC_ID_SNOW},
 /* TODO: Real/Quicktime */
 
 //    {"A_MS/ACM"         , CODEC_ID_NONE},
-    {"A_MPEG/L1"        , CODEC_ID_MP3},
-    {"A_MPEG/L2"        , CODEC_ID_MP3},
     {"A_MPEG/L3"        , CODEC_ID_MP3},
+    {"A_MPEG/L2"        , CODEC_ID_MP2},
+    {"A_MPEG/L1"        , CODEC_ID_MP2},
     {"A_PCM/INT/BIG"    , CODEC_ID_PCM_U16BE},
     {"A_PCM/INT/LIT"    , CODEC_ID_PCM_U16LE},
 //    {"A_PCM/FLOAT/IEEE" , CODEC_ID_NONE},
@@ -59,10 +60,12 @@
     {"A_REAL/COOK"      , CODEC_ID_COOK},
 //    {"A_REAL/SIPR"      , CODEC_ID_SIPRO},
 
+    {"S_TEXT/UTF8"      , CODEC_ID_TEXT},
     {"S_TEXT/ASCII"     , CODEC_ID_TEXT},
-    {"S_TEXT/UTF8"      , CODEC_ID_TEXT},
     {"S_TEXT/ASS"       , CODEC_ID_TEXT},
     {"S_TEXT/SSA"       , CODEC_ID_TEXT},
+    {"S_ASS"            , CODEC_ID_TEXT},
+    {"S_SSA"            , CODEC_ID_TEXT},
     {"S_VOBSUB"         , CODEC_ID_DVD_SUBTITLE},
 
     {NULL               , CODEC_ID_NONE}

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.h
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.h	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroska.h	2007-09-08 10:54:35 UTC (rev 3582)
@@ -64,6 +64,7 @@
 #define MATROSKA_ID_WRITINGAPP 0x5741
 #define MATROSKA_ID_MUXINGAPP  0x4D80
 #define MATROSKA_ID_DATEUTC    0x4461
+#define MATROSKA_ID_SEGMENTUID 0x73A4
 
 /* ID in the tracks master */
 #define MATROSKA_ID_TRACKENTRY 0xAE

Added: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroskaenc.c
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroskaenc.c	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavformat/matroskaenc.c	2007-09-08 10:54:35 UTC (rev 3582)
@@ -0,0 +1,836 @@
+/*
+ * Matroska muxer
+ * Copyright (c) 2007 David Conrad
+ *
+ * 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 "md5.h"
+#include "riff.h"
+#include "xiph.h"
+#include "matroska.h"
+
+typedef struct ebml_master {
+    offset_t        pos;                ///< absolute offset in the file where the master's elements start
+    int             sizebytes;          ///< how many bytes were reserved for the size
+} ebml_master;
+
+typedef struct mkv_seekhead_entry {
+    unsigned int    elementid;
+    uint64_t        segmentpos;
+} mkv_seekhead_entry;
+
+typedef struct mkv_seekhead {
+    offset_t                filepos;
+    offset_t                segment_offset;     ///< the file offset to the beginning of the segment
+    int                     reserved_size;      ///< -1 if appending to file
+    int                     max_entries;
+    mkv_seekhead_entry      *entries;
+    int                     num_entries;
+} mkv_seekhead;
+
+typedef struct {
+    uint64_t        pts;
+    int             tracknum;
+    offset_t        cluster_pos;        ///< file offset of the cluster containing the block
+} mkv_cuepoint;
+
+typedef struct {
+    offset_t        segment_offset;
+    mkv_cuepoint    *entries;
+    int             num_entries;
+} mkv_cues;
+
+typedef struct MatroskaMuxContext {
+    ebml_master     segment;
+    offset_t        segment_offset;
+    offset_t        segment_uid;
+    ebml_master     cluster;
+    offset_t        cluster_pos;        ///< file offset of the current cluster
+    uint64_t        cluster_pts;
+    offset_t        duration_offset;
+    uint64_t        duration;
+    mkv_seekhead    *main_seekhead;
+    mkv_seekhead    *cluster_seekhead;
+    mkv_cues        *cues;
+
+    struct AVMD5    *md5_ctx;
+} MatroskaMuxContext;
+
+
+/** 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit
+ * offset, 4 bytes for target EBML ID */
+#define MAX_SEEKENTRY_SIZE 21
+
+/** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2
+ * 8-byte uint max */
+#define MAX_CUETRACKPOS_SIZE 22
+
+/** per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max */
+#define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks
+
+
+static int ebml_id_size(unsigned int id)
+{
+    return (av_log2(id+1)-1)/7+1;
+}
+
+static void put_ebml_id(ByteIOContext *pb, unsigned int id)
+{
+    int i = ebml_id_size(id);
+    while (i--)
+        put_byte(pb, id >> (i*8));
+}
+
+/**
+ * Write an EBML size meaning "unknown size".
+ *
+ * @param bytes The number of bytes the size should occupy (maximum: 8).
+ */
+static void put_ebml_size_unknown(ByteIOContext *pb, int bytes)
+{
+    assert(bytes <= 8);
+    put_byte(pb, 0x1ff >> bytes);
+    while (--bytes)
+        put_byte(pb, 0xff);
+}
+
+/**
+ * Calculate how many bytes are needed to represent a given number in EBML.
+ */
+static int ebml_num_size(uint64_t num)
+{
+    int bytes = 1;
+    while ((num+1) >> bytes*7) bytes++;
+    return bytes;
+}
+
+/**
+ * Write a number in EBML variable length format.
+ *
+ * @param bytes The number of bytes that need to be used to write the number.
+ *              If zero, any number of bytes can be used.
+ */
+static void put_ebml_num(ByteIOContext *pb, uint64_t num, int bytes)
+{
+    int i, needed_bytes = ebml_num_size(num);
+
+    // sizes larger than this are currently undefined in EBML
+    assert(num < (1ULL<<56)-1);
+
+    if (bytes == 0)
+        // don't care how many bytes are used, so use the min
+        bytes = needed_bytes;
+    // the bytes needed to write the given size would exceed the bytes
+    // that we need to use, so write unknown size. This shouldn't happen.
+    assert(bytes >= needed_bytes);
+
+    num |= 1ULL << bytes*7;
+    for (i = bytes - 1; i >= 0; i--)
+        put_byte(pb, num >> i*8);
+}
+
+static void put_ebml_uint(ByteIOContext *pb, unsigned int elementid, uint64_t val)
+{
+    int i, bytes = 1;
+    while (val >> bytes*8) bytes++;
+
+    put_ebml_id(pb, elementid);
+    put_ebml_num(pb, bytes, 0);
+    for (i = bytes - 1; i >= 0; i--)
+        put_byte(pb, val >> i*8);
+}
+
+static void put_ebml_float(ByteIOContext *pb, unsigned int elementid, double val)
+{
+    put_ebml_id(pb, elementid);
+    put_ebml_num(pb, 8, 0);
+    put_be64(pb, av_dbl2int(val));
+}
+
+static void put_ebml_binary(ByteIOContext *pb, unsigned int elementid,
+                            const uint8_t *buf, int size)
+{
+    put_ebml_id(pb, elementid);
+    put_ebml_num(pb, size, 0);
+    put_buffer(pb, buf, size);
+}
+
+static void put_ebml_string(ByteIOContext *pb, unsigned int elementid, const char *str)
+{
+    put_ebml_binary(pb, elementid, str, strlen(str));
+}
+
+/**
+ * Writes a void element of a given size. Useful for reserving space in
+ * the file to be written to later.
+ *
+ * @param size The number of bytes to reserve, which must be at least 2.
+ */
+static void put_ebml_void(ByteIOContext *pb, uint64_t size)
+{
+    offset_t currentpos = url_ftell(pb);
+
+    assert(size >= 2);
+
+    put_ebml_id(pb, EBML_ID_VOID);
+    // we need to subtract the length needed to store the size from the
+    // size we need to reserve so 2 cases, we use 8 bytes to store the
+    // size if possible, 1 byte otherwise
+    if (size < 10)
+        put_ebml_num(pb, size-1, 0);
+    else
+        put_ebml_num(pb, size-9, 8);
+    url_fseek(pb, currentpos + size, SEEK_SET);
+}
+
+static ebml_master start_ebml_master(ByteIOContext *pb, unsigned int elementid, uint64_t expectedsize)
+{
+    int bytes = expectedsize ? ebml_num_size(expectedsize) : 8;
+    put_ebml_id(pb, elementid);
+    put_ebml_size_unknown(pb, bytes);
+    return (ebml_master){ url_ftell(pb), bytes };
+}
+
+static void end_ebml_master(ByteIOContext *pb, ebml_master master)
+{
+    offset_t pos = url_ftell(pb);
+
+    // leave the unknown size for masters when streaming
+    if (url_is_streamed(pb))
+        return;
+
+    url_fseek(pb, master.pos - master.sizebytes, SEEK_SET);
+    put_ebml_num(pb, pos - master.pos, master.sizebytes);
+    url_fseek(pb, pos, SEEK_SET);
+}
+
+static void put_xiph_size(ByteIOContext *pb, int size)
+{
+    int i;
+    for (i = 0; i < size / 255; i++)
+        put_byte(pb, 255);
+    put_byte(pb, size % 255);
+}
+
+/**
+ * Initialize a mkv_seekhead element to be ready to index level 1 Matroska
+ * elements. If a maximum number of elements is specified, enough space
+ * will be reserved at the current file location to write a seek head of
+ * that size.
+ *
+ * @param segment_offset The absolute offset to the position in the file
+ *                       where the segment begins.
+ * @param numelements The maximum number of elements that will be indexed
+ *                    by this seek head, 0 if unlimited.
+ */
+static mkv_seekhead * mkv_start_seekhead(ByteIOContext *pb, offset_t segment_offset, int numelements)
+{
+    mkv_seekhead *new_seekhead = av_mallocz(sizeof(mkv_seekhead));
+    if (new_seekhead == NULL)
+        return NULL;
+
+    new_seekhead->segment_offset = segment_offset;
+
+    if (numelements > 0) {
+        new_seekhead->filepos = url_ftell(pb);
+        // 21 bytes max for a seek entry, 10 bytes max for the SeekHead ID
+        // and size, and 3 bytes to guarantee that an EBML void element
+        // will fit afterwards
+        new_seekhead->reserved_size = numelements * MAX_SEEKENTRY_SIZE + 13;
+        new_seekhead->max_entries = numelements;
+        put_ebml_void(pb, new_seekhead->reserved_size);
+    }
+    return new_seekhead;
+}
+
+static int mkv_add_seekhead_entry(mkv_seekhead *seekhead, unsigned int elementid, uint64_t filepos)
+{
+    mkv_seekhead_entry *entries = seekhead->entries;
+
+    // don't store more elements than we reserved space for
+    if (seekhead->max_entries > 0 && seekhead->max_entries <= seekhead->num_entries)
+        return -1;
+
+    entries = av_realloc(entries, (seekhead->num_entries + 1) * sizeof(mkv_seekhead_entry));
+    if (entries == NULL)
+        return AVERROR(ENOMEM);
+
+    entries[seekhead->num_entries  ].elementid = elementid;
+    entries[seekhead->num_entries++].segmentpos = filepos - seekhead->segment_offset;
+
+    seekhead->entries = entries;
+    return 0;
+}
+
+/**
+ * Write the seek head to the file and free it. If a maximum number of
+ * elements was specified to mkv_start_seekhead(), the seek head will
+ * be written at the location reserved for it. Otherwise, it is written
+ * at the current location in the file.
+ *
+ * @return The file offset where the seekhead was written.
+ */
+static offset_t mkv_write_seekhead(ByteIOContext *pb, mkv_seekhead *seekhead)
+{
+    ebml_master metaseek, seekentry;
+    offset_t currentpos;
+    int i;
+
+    currentpos = url_ftell(pb);
+
+    if (seekhead->reserved_size > 0)
+        url_fseek(pb, seekhead->filepos, SEEK_SET);
+
+    metaseek = start_ebml_master(pb, MATROSKA_ID_SEEKHEAD, seekhead->reserved_size);
+    for (i = 0; i < seekhead->num_entries; i++) {
+        mkv_seekhead_entry *entry = &seekhead->entries[i];
+
+        seekentry = start_ebml_master(pb, MATROSKA_ID_SEEKENTRY, MAX_SEEKENTRY_SIZE);
+
+        put_ebml_id(pb, MATROSKA_ID_SEEKID);
+        put_ebml_num(pb, ebml_id_size(entry->elementid), 0);
+        put_ebml_id(pb, entry->elementid);
+
+        put_ebml_uint(pb, MATROSKA_ID_SEEKPOSITION, entry->segmentpos);
+        end_ebml_master(pb, seekentry);
+    }
+    end_ebml_master(pb, metaseek);
+
+    if (seekhead->reserved_size > 0) {
+        uint64_t remaining = seekhead->filepos + seekhead->reserved_size - url_ftell(pb);
+        put_ebml_void(pb, remaining);
+        url_fseek(pb, currentpos, SEEK_SET);
+
+        currentpos = seekhead->filepos;
+    }
+    av_free(seekhead->entries);
+    av_free(seekhead);
+
+    return currentpos;
+}
+
+static mkv_cues * mkv_start_cues(offset_t segment_offset)
+{
+    mkv_cues *cues = av_mallocz(sizeof(mkv_cues));
+    if (cues == NULL)
+        return NULL;
+
+    cues->segment_offset = segment_offset;
+    return cues;
+}
+
+static int mkv_add_cuepoint(mkv_cues *cues, AVPacket *pkt, offset_t cluster_pos)
+{
+    mkv_cuepoint *entries = cues->entries;
+
+    entries = av_realloc(entries, (cues->num_entries + 1) * sizeof(mkv_cuepoint));
+    if (entries == NULL)
+        return AVERROR(ENOMEM);
+
+    entries[cues->num_entries  ].pts = pkt->pts;
+    entries[cues->num_entries  ].tracknum = pkt->stream_index + 1;
+    entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offset;
+
+    cues->entries = entries;
+    return 0;
+}
+
+static offset_t mkv_write_cues(ByteIOContext *pb, mkv_cues *cues, int num_tracks)
+{
+    ebml_master cues_element;
+    offset_t currentpos;
+    int i, j;
+
+    currentpos = url_ftell(pb);
+    cues_element = start_ebml_master(pb, MATROSKA_ID_CUES, 0);
+
+    for (i = 0; i < cues->num_entries; i++) {
+        ebml_master cuepoint, track_positions;
+        mkv_cuepoint *entry = &cues->entries[i];
+        uint64_t pts = entry->pts;
+
+        cuepoint = start_ebml_master(pb, MATROSKA_ID_POINTENTRY, MAX_CUEPOINT_SIZE(num_tracks));
+        put_ebml_uint(pb, MATROSKA_ID_CUETIME, pts);
+
+        // put all the entries from different tracks that have the exact same
+        // timestamp into the same CuePoint
+        for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) {
+            track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
+            put_ebml_uint(pb, MATROSKA_ID_CUETRACK          , entry[j].tracknum   );
+            put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION, entry[j].cluster_pos);
+            end_ebml_master(pb, track_positions);
+        }
+        i += j - 1;
+        end_ebml_master(pb, cuepoint);
+    }
+    end_ebml_master(pb, cues_element);
+
+    av_free(cues->entries);
+    av_free(cues);
+    return currentpos;
+}
+
+static int put_xiph_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec)
+{
+    uint8_t *header_start[3];
+    int header_len[3];
+    int first_header_size;
+    int j;
+
+    if (codec->codec_id == CODEC_ID_VORBIS)
+        first_header_size = 30;
+    else
+        first_header_size = 42;
+
+    if (ff_split_xiph_headers(codec->extradata, codec->extradata_size,
+                              first_header_size, header_start, header_len) < 0) {
+        av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
+        return -1;
+    }
+
+    put_byte(pb, 2);                    // number packets - 1
+    for (j = 0; j < 2; j++) {
+        put_xiph_size(pb, header_len[j]);
+    }
+    for (j = 0; j < 3; j++)
+        put_buffer(pb, header_start[j], header_len[j]);
+
+    return 0;
+}
+
+#define FLAC_STREAMINFO_SIZE 34
+
+static int put_flac_codecpriv(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec)
+{
+    // if the extradata_size is greater than FLAC_STREAMINFO_SIZE,
+    // assume that it's in Matroska's format already
+    if (codec->extradata_size < FLAC_STREAMINFO_SIZE) {
+        av_log(s, AV_LOG_ERROR, "Invalid FLAC extradata\n");
+        return -1;
+    } else if (codec->extradata_size == FLAC_STREAMINFO_SIZE) {
+        // only the streaminfo packet
+        put_byte(pb, 0);
+        put_xiph_size(pb, codec->extradata_size);
+        av_log(s, AV_LOG_ERROR, "Only one packet\n");
+    }
+    put_buffer(pb, codec->extradata, codec->extradata_size);
+    return 0;
+}
+
+static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *sample_rate, int *output_sample_rate)
+{
+    static const int aac_sample_rates[] = {
+        96000, 88200, 64000, 48000, 44100, 32000,
+        24000, 22050, 16000, 12000, 11025,  8000,
+    };
+    int sri;
+
+    if (codec->extradata_size < 2) {
+        av_log(s, AV_LOG_WARNING, "No AAC extradata, unable to determine samplerate.\n");
+        return;
+    }
+
+    sri = ((codec->extradata[0] << 1) & 0xE) | (codec->extradata[1] >> 7);
+    if (sri > 12) {
+        av_log(s, AV_LOG_WARNING, "AAC samplerate index out of bounds\n");
+        return;
+    }
+    *sample_rate = aac_sample_rates[sri];
+
+    // if sbr, get output sample rate as well
+    if (codec->extradata_size == 5) {
+        sri = (codec->extradata[4] >> 3) & 0xF;
+        if (sri > 12) {
+            av_log(s, AV_LOG_WARNING, "AAC output samplerate index out of bounds\n");
+            return;
+        }
+        *output_sample_rate = aac_sample_rates[sri];
+    }
+}
+
+static int mkv_write_codecprivate(AVFormatContext *s, ByteIOContext *pb, AVCodecContext *codec, int native_id)
+{
+    ByteIOContext dyn_cp;
+    uint8_t *codecpriv;
+    int ret = 0, codecpriv_size;
+
+    url_open_dyn_buf(&dyn_cp);
+
+    if (native_id) {
+        if (codec->codec_id == CODEC_ID_VORBIS || codec->codec_id == CODEC_ID_THEORA)
+            ret = put_xiph_codecpriv(s, &dyn_cp, codec);
+        else if (codec->codec_id == CODEC_ID_FLAC)
+            ret = put_flac_codecpriv(s, &dyn_cp, codec);
+        else if (codec->extradata_size)
+            put_buffer(&dyn_cp, codec->extradata, codec->extradata_size);
+    } else if (codec->codec_type == CODEC_TYPE_VIDEO) {
+        if (!codec->codec_tag)
+            codec->codec_tag = codec_get_tag(codec_bmp_tags, codec->codec_id);
+        if (!codec->codec_tag) {
+            av_log(s, AV_LOG_ERROR, "No bmp codec ID found.");
+            ret = -1;
+        }
+
+        put_bmp_header(&dyn_cp, codec, codec_bmp_tags, 0);
+
+    } else if (codec->codec_type == CODEC_TYPE_AUDIO) {
+        if (!codec->codec_tag)
+            codec->codec_tag = codec_get_tag(codec_wav_tags, codec->codec_id);
+        if (!codec->codec_tag) {
+            av_log(s, AV_LOG_ERROR, "No wav codec ID found.");
+            ret = -1;
+        }
+
+        put_wav_header(&dyn_cp, codec);
+    }
+
+    codecpriv_size = url_close_dyn_buf(&dyn_cp, &codecpriv);
+    if (codecpriv_size)
+        put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, codecpriv_size);
+    av_free(codecpriv);
+    return ret;
+}
+
+static int mkv_write_tracks(AVFormatContext *s)
+{
+    MatroskaMuxContext *mkv = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    ebml_master tracks;
+    int i, j, ret;
+
+    ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TRACKS, url_ftell(pb));
+    if (ret < 0) return ret;
+
+    tracks = start_ebml_master(pb, MATROSKA_ID_TRACKS, 0);
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *st = s->streams[i];
+        AVCodecContext *codec = st->codec;
+        ebml_master subinfo, track;
+        int native_id = 0;
+        int bit_depth = av_get_bits_per_sample(codec->codec_id);
+        int sample_rate = codec->sample_rate;
+        int output_sample_rate = 0;
+
+        if (!bit_depth)
+            bit_depth = av_get_bits_per_sample_format(codec->sample_fmt);
+
+        if (codec->codec_id == CODEC_ID_AAC)
+            get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate);
+
+        track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
+        put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER     , i + 1);
+        put_ebml_uint (pb, MATROSKA_ID_TRACKUID        , i + 1);
+        put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0);    // no lacing (yet)
+
+        if (st->language[0])
+            put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, st->language);
+        else
+            put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, "und");
+
+        // look for a codec ID string specific to mkv to use,
+        // if none are found, use AVI codes
+        for (j = 0; ff_mkv_codec_tags[j].id != CODEC_ID_NONE; j++) {
+            if (ff_mkv_codec_tags[j].id == codec->codec_id) {
+                put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);
+                native_id = 1;
+                break;
+            }
+        }
+
+        switch (codec->codec_type) {
+            case CODEC_TYPE_VIDEO:
+                put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
+
+                if (!native_id)
+                    // if there is no mkv-specific codec ID, use VFW mode
+                    put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
+
+                subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
+                // XXX: interlace flag?
+                put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
+                put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
+                if (codec->sample_aspect_ratio.num) {
+                    AVRational dar = av_mul_q(codec->sample_aspect_ratio,
+                                    (AVRational){codec->width, codec->height});
+                    put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , dar.num);
+                    put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, dar.den);
+                }
+                end_ebml_master(pb, subinfo);
+                break;
+
+            case CODEC_TYPE_AUDIO:
+                put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO);
+
+                if (!native_id)
+                    // no mkv-specific ID, use ACM mode
+                    put_ebml_string(pb, MATROSKA_ID_CODECID, MATROSKA_CODEC_ID_AUDIO_ACM);
+
+                subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);
+                put_ebml_uint  (pb, MATROSKA_ID_AUDIOCHANNELS    , codec->channels);
+                put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
+                if (output_sample_rate)
+                    put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
+                if (bit_depth)
+                    put_ebml_uint(pb, MATROSKA_ID_AUDIOBITDEPTH, bit_depth);
+                end_ebml_master(pb, subinfo);
+                break;
+
+            case CODEC_TYPE_SUBTITLE:
+                put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_SUBTITLE);
+                break;
+            default:
+                av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.");
+                break;
+        }
+        ret = mkv_write_codecprivate(s, pb, codec, native_id);
+        if (ret < 0) return ret;
+
+        end_ebml_master(pb, track);
+
+        // ms precision is the de-facto standard timescale for mkv files
+        av_set_pts_info(st, 64, 1, 1000);
+    }
+    end_ebml_master(pb, tracks);
+    return 0;
+}
+
+static int mkv_write_header(AVFormatContext *s)
+{
+    MatroskaMuxContext *mkv = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    ebml_master ebml_header, segment_info;
+    int ret;
+
+    mkv->md5_ctx = av_mallocz(av_md5_size);
+    av_md5_init(mkv->md5_ctx);
+
+    ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);
+    put_ebml_uint   (pb, EBML_ID_EBMLVERSION        ,           1);
+    put_ebml_uint   (pb, EBML_ID_EBMLREADVERSION    ,           1);
+    put_ebml_uint   (pb, EBML_ID_EBMLMAXIDLENGTH    ,           4);
+    put_ebml_uint   (pb, EBML_ID_EBMLMAXSIZELENGTH  ,           8);
+    put_ebml_string (pb, EBML_ID_DOCTYPE            ,  "matroska");
+    put_ebml_uint   (pb, EBML_ID_DOCTYPEVERSION     ,           2);
+    put_ebml_uint   (pb, EBML_ID_DOCTYPEREADVERSION ,           2);
+    end_ebml_master(pb, ebml_header);
+
+    mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0);
+    mkv->segment_offset = url_ftell(pb);
+
+    // we write 2 seek heads - one at the end of the file to point to each
+    // cluster, and one at the beginning to point to all other level one
+    // elements (including the seek head at the end of the file), which
+    // isn't more than 10 elements if we only write one of each other
+    // currently defined level 1 element
+    mkv->main_seekhead    = mkv_start_seekhead(pb, mkv->segment_offset, 10);
+    mkv->cluster_seekhead = mkv_start_seekhead(pb, mkv->segment_offset, 0);
+    if (mkv->main_seekhead == NULL || mkv->cluster_seekhead == NULL)
+        return AVERROR(ENOMEM);
+
+    ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_INFO, url_ftell(pb));
+    if (ret < 0) return ret;
+
+    segment_info = start_ebml_master(pb, MATROSKA_ID_INFO, 0);
+    put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
+    if (strlen(s->title))
+        put_ebml_string(pb, MATROSKA_ID_TITLE, s->title);
+    if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
+        put_ebml_string(pb, MATROSKA_ID_MUXINGAPP , LIBAVFORMAT_IDENT);
+        put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT);
+
+        // reserve space to write the segment UID later
+        mkv->segment_uid = url_ftell(pb);
+        put_ebml_void(pb, 19);
+    }
+
+    // reserve space for the duration
+    mkv->duration = 0;
+    mkv->duration_offset = url_ftell(pb);
+    put_ebml_void(pb, 11);                  // assumes double-precision float to be written
+    end_ebml_master(pb, segment_info);
+
+    ret = mkv_write_tracks(s);
+    if (ret < 0) return ret;
+
+    ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb));
+    if (ret < 0) return ret;
+
+    mkv->cluster_pos = url_ftell(pb);
+    mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
+    put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, 0);
+    mkv->cluster_pts = 0;
+
+    mkv->cues = mkv_start_cues(mkv->segment_offset);
+    if (mkv->cues == NULL)
+        return AVERROR(ENOMEM);
+
+    return 0;
+}
+
+static int mkv_block_size(AVPacket *pkt)
+{
+    int size = 4;           // track num + timecode + flags
+    return size + pkt->size;
+}
+
+static int mkv_blockgroup_size(AVPacket *pkt)
+{
+    int size = mkv_block_size(pkt);
+    size += ebml_num_size(size);
+    size += 2;              // EBML ID for block and block duration
+    size += 8;              // max size of block duration
+    size += ebml_num_size(size);
+    size += 1;              // blockgroup EBML ID
+    return size;
+}
+
+static void mkv_write_block(AVFormatContext *s, unsigned int blockid, AVPacket *pkt, int flags)
+{
+    MatroskaMuxContext *mkv = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+
+    av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
+           "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n",
+           url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags);
+    put_ebml_id(pb, blockid);
+    put_ebml_num(pb, mkv_block_size(pkt), 0);
+    put_byte(pb, 0x80 | (pkt->stream_index + 1));     // this assumes stream_index is less than 126
+    put_be16(pb, pkt->pts - mkv->cluster_pts);
+    put_byte(pb, flags);
+    put_buffer(pb, pkt->data, pkt->size);
+}
+
+static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    MatroskaMuxContext *mkv = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
+    int keyframe = !!(pkt->flags & PKT_FLAG_KEY);
+    int ret;
+
+    // start a new cluster every 5 MB or 5 sec
+    if (url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || pkt->pts > mkv->cluster_pts + 5000) {
+        av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
+               " bytes, pts %" PRIu64 "\n", url_ftell(pb), pkt->pts);
+        end_ebml_master(pb, mkv->cluster);
+
+        ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb));
+        if (ret < 0) return ret;
+
+        mkv->cluster_pos = url_ftell(pb);
+        mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
+        put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts);
+        mkv->cluster_pts = pkt->pts;
+        av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size));
+    }
+
+    if (codec->codec_type != CODEC_TYPE_SUBTITLE) {
+        mkv_write_block(s, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7);
+    } else {
+        ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt));
+        mkv_write_block(s, MATROSKA_ID_BLOCK, pkt, 0);
+        put_ebml_uint(pb, MATROSKA_ID_DURATION, pkt->duration);
+        end_ebml_master(pb, blockgroup);
+    }
+
+    if (codec->codec_type == CODEC_TYPE_VIDEO && keyframe) {
+        ret = mkv_add_cuepoint(mkv->cues, pkt, mkv->cluster_pos);
+        if (ret < 0) return ret;
+    }
+
+    mkv->duration = FFMAX(mkv->duration, pkt->pts + pkt->duration);
+    return 0;
+}
+
+static int mkv_write_trailer(AVFormatContext *s)
+{
+    MatroskaMuxContext *mkv = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    offset_t currentpos, second_seekhead, cuespos;
+    int ret;
+
+    end_ebml_master(pb, mkv->cluster);
+
+    if (!url_is_streamed(pb)) {
+        cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
+        second_seekhead = mkv_write_seekhead(pb, mkv->cluster_seekhead);
+
+        ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES    , cuespos);
+        if (ret < 0) return ret;
+        ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_SEEKHEAD, second_seekhead);
+        if (ret < 0) return ret;
+        mkv_write_seekhead(pb, mkv->main_seekhead);
+
+        // update the duration
+        av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration);
+        currentpos = url_ftell(pb);
+        url_fseek(pb, mkv->duration_offset, SEEK_SET);
+        put_ebml_float(pb, MATROSKA_ID_DURATION, mkv->duration);
+
+        // write the md5sum of some frames as the segment UID
+        if (!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
+            uint8_t segment_uid[16];
+            av_md5_final(mkv->md5_ctx, segment_uid);
+            url_fseek(pb, mkv->segment_uid, SEEK_SET);
+            put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, segment_uid, 16);
+        }
+        url_fseek(pb, currentpos, SEEK_SET);
+    }
+
+    end_ebml_master(pb, mkv->segment);
+    av_free(mkv->md5_ctx);
+    return 0;
+}
+
+AVOutputFormat matroska_muxer = {
+    "matroska",
+    "Matroska File Format",
+    "video/x-matroska",
+    "mkv",
+    sizeof(MatroskaMuxContext),
+    CODEC_ID_MP2,
+    CODEC_ID_MPEG4,
+    mkv_write_header,
+    mkv_write_packet,
+    mkv_write_trailer,
+    .codec_tag = (const AVCodecTag*[]){codec_bmp_tags, codec_wav_tags, 0},
+    // MEANX .subtitle_codec = CODEC_ID_TEXT,
+};
+
+AVOutputFormat matroska_audio_muxer = {
+    "matroska",
+    "Matroska File Format",
+    "audio/x-matroska",
+    "mka",
+    sizeof(MatroskaMuxContext),
+    CODEC_ID_MP2,
+    CODEC_ID_NONE,
+    mkv_write_header,
+    mkv_write_packet,
+    mkv_write_trailer,
+    .codec_tag = (const AVCodecTag*[]){codec_wav_tags, 0},
+};
+// MEANX
+//
+int matroskaenc_init(void)
+{
+    av_register_output_format(&matroska_muxer);
+    return 0;
+}
+

Modified: branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavutil/crc.h
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavutil/crc.h	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_libraries/ADM_lavutil/crc.h	2007-09-08 10:54:35 UTC (rev 3582)
@@ -26,6 +26,13 @@
 
 typedef uint32_t AVCRC;
 
+#define AV_CRC_8_ATM      0x07
+#define AV_CRC_16         0x8005
+#define AV_CRC_16_CCITT   0x1021
+#define AV_CRC_32_IEEE    0x04C11DB7L
+//! reversed bitorder version of AV_CRC_32_IEEE
+#define AV_CRC_32_IEEE_LE 0xEDB88320L
+
 #if LIBAVUTIL_VERSION_INT  < (50<<16)
 extern AVCRC *av_crcEDB88320;
 extern AVCRC *av_crc04C11DB7;

Modified: branches/avidemux_2.4_branch/avidemux/ADM_outputs/oplug_mp4/oplug_mp4.cpp
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_outputs/oplug_mp4/oplug_mp4.cpp	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_outputs/oplug_mp4/oplug_mp4.cpp	2007-09-08 10:54:35 UTC (rev 3582)
@@ -125,10 +125,14 @@
 uint32_t    totalAudioSize=0;
 uint32_t sent=0;
 
-           if(type==ADM_PSP)
-               muxerType=MUXER_PSP;
-           else
-               muxerType=MUXER_MP4;
+           switch(type)
+           {
+             case ADM_PSP:muxerType=MUXER_PSP;break;
+             case ADM_MP4:muxerType=MUXER_MP4;break;
+             case ADM_MATROSKA:muxerType=MUXER_MATROSKA;break;
+             default:
+                ADM_assert(0);
+           }
         // Setup video
         
         if(videoProcessMode())

Modified: branches/avidemux_2.4_branch/avidemux/ADM_script/ADM_container.h
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_script/ADM_container.h	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_script/ADM_container.h	2007-09-08 10:54:35 UTC (rev 3582)
@@ -28,7 +28,8 @@
   MK_CONT(MP4),
   MK_CONT(PSP),
   MK_CONT(FLV),
-  MK_CONT(DUMMY)  
+  MK_CONT(DUMMY),
+  MK_CONT(MATROSKA)  
 };
 #define NB_CONT (sizeof(container)/sizeof(ADM_CONTAINER))
 #endif

Modified: branches/avidemux_2.4_branch/avidemux/ADM_video/ADM_genvideo.hxx
===================================================================
--- branches/avidemux_2.4_branch/avidemux/ADM_video/ADM_genvideo.hxx	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/ADM_video/ADM_genvideo.hxx	2007-09-08 10:54:35 UTC (rev 3582)
@@ -150,7 +150,7 @@
 #define CREATOR(x,clss)  return new clss(in,x);
 #define BUILD_CREATE(name,clss) AVDMGenericVideoStream *name(AVDMGenericVideoStream *in, CONFcouple *conf) \
 {		CREATOR(conf,clss); }
-
+#define VARIABLE_PARAMS 0xff
 #define SCRIPT_CREATE(name,clss,tmplate) \
 AVDMGenericVideoStream *name (AVDMGenericVideoStream *in, int n,Arg *args); \
 AVDMGenericVideoStream *name (AVDMGenericVideoStream *in, int n,Arg *args) \

Modified: branches/avidemux_2.4_branch/avidemux/gui_savenew.cpp
===================================================================
--- branches/avidemux_2.4_branch/avidemux/gui_savenew.cpp	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/avidemux/gui_savenew.cpp	2007-09-08 10:54:35 UTC (rev 3582)
@@ -180,6 +180,7 @@
                             			break;
                         case ADM_MP4:
                         case ADM_PSP:
+                        case ADM_MATROSKA:
                         
                                                     ret=oplug_mp4(name,UI_GetCurrentFormat());
                                                     break;

Modified: branches/avidemux_2.4_branch/config.h.cmake
===================================================================
--- branches/avidemux_2.4_branch/config.h.cmake	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/config.h.cmake	2007-09-08 10:54:35 UTC (rev 3582)
@@ -77,6 +77,7 @@
 #cmakedefine CONFIG_MJPEG_DECODER
 #cmakedefine CONFIG_MJPEG_ENCODER
 #cmakedefine CONFIG_MOV_MUXER
+#cmakedefine CONFIG_MATROSKA_MUXER
 #cmakedefine CONFIG_MP2_ENCODER
 #cmakedefine CONFIG_MP4_MUXER
 #cmakedefine CONFIG_MPEG1VIDEO_DECODER

Modified: branches/avidemux_2.4_branch/configure.in.in
===================================================================
--- branches/avidemux_2.4_branch/configure.in.in	2007-09-08 10:53:53 UTC (rev 3581)
+++ branches/avidemux_2.4_branch/configure.in.in	2007-09-08 10:54:35 UTC (rev 3582)
@@ -1414,6 +1414,7 @@
 AC_DEFINE(CONFIG_PSP_MUXER,1,[CONFIG_MUXERS])
 AC_DEFINE(CONFIG_MP4_MUXER,1,[CONFIG_MUXERS])
 AC_DEFINE(CONFIG_MOV_MUXER,1,[CONFIG_MUXERS])
+AC_DEFINE(CONFIG_MATROSKA_MUXER,1,[CONFIG_MATROSKA_MUXERS])
 AC_DEFINE(HAVE_THREADS,1,[HAVE_THREADS])
 AC_DEFINE(ENABLE_THREADS,1,[ENABLE_THREADS])
 




More information about the Avidemux-svn-commit mailing list