changeset 14757:7a2adc5e8928

initial, extremely experimental, libavformat muxer; don't expect anything to work yet
author nicodvb
date Mon, 21 Feb 2005 23:18:31 +0000
parents 0c755d34ce18
children 94456deb0624
files cfg-mencoder.h libmpdemux/Makefile libmpdemux/muxer.c libmpdemux/muxer.h libmpdemux/muxer_lavf.c mencoder.c
diffstat 6 files changed, 328 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/cfg-mencoder.h	Mon Feb 21 22:28:06 2005 +0000
+++ b/cfg-mencoder.h	Mon Feb 21 23:18:31 2005 +0000
@@ -73,6 +73,9 @@
 
 extern m_option_t nuvopts_conf[];
 extern m_option_t mpegopts_conf[];
+#ifdef USE_LIBAVFORMAT
+extern m_option_t lavfopts_conf[];
+#endif
 
 m_option_t ovc_conf[]={
 	{"copy", &out_video_codec, CONF_TYPE_FLAG, 0, 0, VCODEC_COPY, NULL},
@@ -177,6 +180,9 @@
 m_option_t of_conf[]={
 	{"avi", &out_file_format, CONF_TYPE_FLAG, 0, 0, MUXER_TYPE_AVI, NULL},
 	{"mpeg", &out_file_format, CONF_TYPE_FLAG, 0, 0, MUXER_TYPE_MPEG, NULL},
+#ifdef USE_LIBAVFORMAT
+	{"lavf", &out_file_format, CONF_TYPE_FLAG, 0, 0, MUXER_TYPE_LAVF, NULL},
+#endif
 	{"rawvideo", &out_file_format, CONF_TYPE_FLAG, 0, 0, MUXER_TYPE_RAWVIDEO, NULL},
 	{"help", "\nAvailable output formats:\n"
 	"   avi      - Microsoft Audio/Video Interleaved\n"
@@ -271,6 +277,9 @@
 
 	{"nuvopts",  nuvopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
 	{"mpegopts",  mpegopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+#ifdef USE_LIBAVFORMAT
+	{"lavfopts",  lavfopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
+#endif	
 
 #define MAIN_CONF
 #include "cfg-common.h"
--- a/libmpdemux/Makefile	Mon Feb 21 22:28:06 2005 +0000
+++ b/libmpdemux/Makefile	Mon Feb 21 23:18:31 2005 +0000
@@ -31,6 +31,7 @@
 
 ifeq ($(CONFIG_LIBAVFORMAT),yes)
 LIBAV_INC = -I../libavcodec -I../libavformat
+SRCS += muxer_lavf.c
 endif
 
 OBJS	= $(SRCS:.c=.o)
--- a/libmpdemux/muxer.c	Mon Feb 21 22:28:06 2005 +0000
+++ b/libmpdemux/muxer.c	Mon Feb 21 23:18:31 2005 +0000
@@ -31,6 +31,12 @@
         if(! muxer_init_muxer_rawvideo(muxer))
 	  return NULL;
 	break;
+#ifdef USE_LIBAVFORMAT
+      case MUXER_TYPE_LAVF:
+        if(! muxer_init_muxer_lavf(muxer))
+	  return NULL;
+        break;
+#endif
       case MUXER_TYPE_AVI:
       default:
 	if(! muxer_init_muxer_avi(muxer))
--- a/libmpdemux/muxer.h	Mon Feb 21 22:28:06 2005 +0000
+++ b/libmpdemux/muxer.h	Mon Feb 21 23:18:31 2005 +0000
@@ -7,6 +7,7 @@
 #define MUXER_TYPE_AVI 0
 #define MUXER_TYPE_MPEG 1
 #define MUXER_TYPE_RAWVIDEO 2
+#define MUXER_TYPE_LAVF 3
 
 
 typedef struct {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/muxer_lavf.c	Mon Feb 21 23:18:31 2005 +0000
@@ -0,0 +1,307 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include "config.h"
+#include "../version.h"
+#include "../mp_msg.h"
+
+#include "bswap.h"
+#include "aviheader.h"
+#include "ms_hdr.h"
+
+#include "muxer.h"
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
+#include "../m_option.h"
+#include "avformat.h"
+
+typedef struct {
+	//AVInputFormat *avif;
+	AVFormatContext *oc;
+	ByteIOContext pb;
+	int audio_streams;
+	int video_streams;
+	int64_t last_pts;
+} muxer_priv_t;
+
+typedef struct {
+	int64_t last_pts;
+	AVStream *avstream;
+} muxer_stream_priv_t;
+
+static char *conf_format = NULL;
+
+m_option_t lavfopts_conf[] = {
+	{"format", &(conf_format), CONF_TYPE_STRING, 0, 0, 0, NULL},
+	{NULL, NULL, 0, 0, 0, 0, NULL}
+};
+
+static int mp_open(URLContext *h, const char *filename, int flags)
+{
+	return 0;
+}
+
+static int mp_close(URLContext *h)
+{
+	return 0;
+}
+
+
+static int mp_read(URLContext *h, unsigned char *buf, int size)
+{
+	fprintf(stderr, "READ %d\n", size);
+	return -1;
+}
+
+static int mp_write(URLContext *h, unsigned char *buf, int size)
+{
+	muxer_t *muxer = (muxer_t*)h->priv_data;
+	return fwrite(buf, 1, size, muxer->file);
+}
+
+static offset_t mp_seek(URLContext *h, offset_t pos, int whence)
+{
+	muxer_t *muxer = (muxer_t*)h->priv_data;
+	fprintf(stderr, "SEEK %llu\n", pos);
+	return fseeko(muxer->file, pos, whence);
+}
+
+
+static URLProtocol mp_protocol = {
+	"menc",
+	mp_open,
+	mp_read,
+	mp_write,
+	mp_seek,
+	mp_close,
+};
+
+static muxer_stream_t* lavf_new_stream(muxer_t *muxer, int type)
+{
+	muxer_priv_t *priv = (muxer_priv_t*) muxer->priv;
+	muxer_stream_t *stream;
+	muxer_stream_priv_t *spriv;
+	AVCodecContext *ctx;
+
+	if(!muxer || (type != MUXER_TYPE_VIDEO && type != MUXER_TYPE_AUDIO)) 
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR, "UNKNOW TYPE %d\n", type);
+		return NULL;
+	}
+	
+	stream = (muxer_stream_t*) calloc(1, sizeof(muxer_stream_t));
+	if(!stream)
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR, "Could not alloc muxer_stream, EXIT\n");
+		return NULL;
+	}
+	stream->b_buffer = malloc(2048);
+	if(!stream->b_buffer)
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR, "Could not alloc b_buffer, EXIT\n");
+		free(stream);
+		return NULL;
+	}
+	stream->b_buffer_size = 2048;
+	stream->b_buffer_ptr = 0;
+	stream->b_buffer_len = 0;
+	
+	spriv = (muxer_stream_priv_t*) calloc(1, sizeof(muxer_stream_priv_t));
+	if(!spriv) 
+	{
+		free(stream);
+		return NULL;
+	}
+	stream->priv = spriv;
+	
+	spriv->avstream = av_new_stream(priv->oc, 1);
+	if(!spriv->avstream) 
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR, "Could not alloc avstream, EXIT\n");
+		return NULL;
+	}
+	spriv->avstream->stream_copy = 1;
+	
+	ctx = &(spriv->avstream->codec);
+	ctx->codec_id = muxer->avih.dwStreams;
+	switch(type) 
+	{
+		case MUXER_TYPE_VIDEO:
+			ctx->codec_type = CODEC_TYPE_VIDEO;
+			break;
+		case MUXER_TYPE_AUDIO:
+			ctx->codec_type = CODEC_TYPE_AUDIO;
+			break;
+	}
+
+	muxer->avih.dwStreams++;
+	stream->muxer = muxer;
+	stream->type = type;
+	mp_msg(MSGT_MUXER, MSGL_V, "ALLOCATED STREAM N. %d, type=%d\n", muxer->avih.dwStreams, type);
+	return stream;
+}
+
+
+static void fix_parameters(muxer_stream_t *stream, void *sh)
+{
+	muxer_stream_priv_t *spriv = (muxer_stream_priv_t *) stream->priv;
+	AVCodecContext *ctx;
+	
+	ctx = &(spriv->avstream->codec);
+	
+	if(stream->type == MUXER_TYPE_AUDIO)
+	{
+		ctx->codec_id = codec_get_wav_id(stream->wf->wFormatTag); 
+		ctx->codec_tag = codec_get_wav_tag(ctx->codec_id);
+		mp_msg(MSGT_MUXER, MSGL_INFO, "AUDIO CODEC ID: %x, TAG: %x\n", ctx->codec_id, (uint32_t) ctx->codec_tag);
+		ctx->bit_rate = stream->wf->nAvgBytesPerSec * 8;
+		ctx->sample_rate = stream->h.dwSampleSize;
+		ctx->channels = stream->wf->nChannels;
+		ctx->frame_size = 576;
+		ctx->block_align = stream->wf->nBlockAlign;
+	}
+	else if(stream->type == MUXER_TYPE_VIDEO)
+	{
+		ctx->codec_id = codec_get_bmp_id(stream->bih->biCompression);
+		mp_msg(MSGT_MUXER, MSGL_INFO, "VIDEO CODEC ID: %d\n", ctx->codec_id);
+		ctx->width = stream->bih->biWidth;
+		ctx->height = stream->bih->biHeight;
+		ctx->bit_rate = 800000;
+		ctx->frame_rate = (int) (10000 * stream->h.dwRate)/ stream->h.dwScale;;
+		ctx->frame_rate_base = 10000;
+	}
+}
+
+static void write_chunk(muxer_stream_t *stream, size_t len, unsigned int flags)
+{
+	muxer_t *muxer = (muxer_t*) stream->muxer;
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	muxer_stream_priv_t *spriv = (muxer_stream_priv_t *) stream->priv;
+	AVPacket pkt;
+	AVCodecContext *ctx;
+	
+	stream->size += len;
+	if(stream->type == MUXER_TYPE_VIDEO && !len)
+		return;
+	
+	av_init_packet(&pkt);
+	pkt.size = len;
+	pkt.stream_index= spriv->avstream->index;
+	pkt.data = stream->buffer;
+	
+	if((stream->type == MUXER_TYPE_VIDEO) && (flags & AVIIF_KEYFRAME))
+		pkt.flags |= PKT_FLAG_KEY;
+	else
+		pkt.flags = 0;
+	
+	
+	//pkt.pts = AV_NOPTS_VALUE; 
+	pkt.pts = AV_TIME_BASE * stream->timer;
+	
+	if(stream->h.dwSampleSize) 	// CBR
+		stream->h.dwLength += len / stream->h.dwSampleSize;
+	else				// VBR
+		stream->h.dwLength++;
+	
+	//;
+	if(av_interleaved_write_frame(priv->oc, &pkt) != 0) //av_write_frame(priv->oc, &pkt)
+	{
+		mp_msg(MSGT_MUXER, MSGL_ERR, "Error while writing frame\n");
+	}
+	
+	stream->timer = (double) stream->h.dwLength * stream->h.dwScale / stream->h.dwRate;
+	return;
+}
+
+
+static void write_header(muxer_t *muxer)
+{
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	
+	av_write_header(priv->oc);
+	muxer->cont_write_header = NULL;
+	mp_msg(MSGT_MUXER, MSGL_INFO, "WRITTEN HEADER\n");
+}
+
+
+static void write_trailer(muxer_t *muxer)
+{
+	int i;
+	muxer_priv_t *priv = (muxer_priv_t *) muxer->priv;
+	
+	av_write_trailer(priv->oc);
+	mp_msg(MSGT_MUXER, MSGL_INFO, "WRITTEN TRAILER\n");
+	for(i = 0; i < priv->oc->nb_streams; i++) 
+	{
+		av_freep(&(priv->oc->streams[i]));
+	}
+
+	url_fclose(&(priv->oc->pb));
+
+	av_free(priv->oc);
+}
+
+extern char *out_filename;
+int muxer_init_muxer_lavf(muxer_t *muxer)
+{
+	muxer_priv_t *priv;
+	AVOutputFormat *fmt = NULL;
+	char mp_filename[256] = "menc://stream.dummy";
+	
+	priv = (muxer_priv_t *) calloc(1, sizeof(muxer_priv_t));
+	if(priv == NULL)
+		return 0;
+
+	av_register_all();
+	
+	priv->oc = av_alloc_format_context();
+	if(!priv->oc) 
+	{
+		mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't get format context\n");
+		goto fail;
+	}
+
+	if(conf_format)		
+		fmt = guess_format(conf_format, NULL, NULL);
+	if(! fmt)
+		fmt = guess_format(NULL, out_filename, NULL);
+	if(! fmt)
+	{
+		mp_msg(MSGT_MUXER, MSGL_FATAL, "CAN'T GET SPECIFIED FORMAT\n");
+		goto fail;
+	}
+	priv->oc->oformat = fmt;
+
+	
+	if(av_set_parameters(priv->oc, NULL) < 0) 
+	{
+		mp_msg(MSGT_MUXER, MSGL_FATAL, "Invalid output format parameters\n");
+		goto fail;
+	}
+	
+	register_protocol(&mp_protocol);
+
+	if(url_fopen(&priv->oc->pb, mp_filename, URL_WRONLY))
+	{
+		mp_msg(MSGT_MUXER, MSGL_FATAL, "Coulnd't open outfile\n");
+		goto fail;
+        }
+	
+	((URLContext*)(priv->oc->pb.opaque))->priv_data= muxer;
+	
+	muxer->priv = (void *) priv;
+	muxer->cont_new_stream = &lavf_new_stream;
+	muxer->cont_write_chunk = &write_chunk;
+	muxer->cont_write_header = &write_header;
+	muxer->cont_write_index = &write_trailer;
+	muxer->fix_stream_parameters = &fix_parameters;
+	mp_msg(MSGT_MUXER, MSGL_INFO, "OK, exit\n");
+	return 1;
+	
+fail:
+	free(priv);
+	return 0;
+}
--- a/mencoder.c	Mon Feb 21 22:28:06 2005 +0000
+++ b/mencoder.c	Mon Feb 21 23:18:31 2005 +0000
@@ -746,6 +746,8 @@
 	mux_v->bih->biCompression, (char *)&mux_v->bih->biCompression);
 }
 
+if(muxer->fix_stream_parameters)
+	  muxer_stream_fix_parameters(muxer,mux_v);
 //if(demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf!
 
 // ============= AUDIO ===============
@@ -1062,6 +1064,8 @@
     mux_a->h.dwStart=audio_delay*mux_a->h.dwRate/mux_a->h.dwScale;
     mp_msg(MSGT_FIXME, MSGL_FIXME, MSGTR_SettingAudioDelay,mux_a->h.dwStart*mux_a->h.dwScale/(float)mux_a->h.dwRate);
 }
+if(muxer->fix_stream_parameters)
+	  muxer_stream_fix_parameters(muxer,mux_a);
 
 } // if(sh_audio)