You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	oggvorbis support patch by (Mark Hills <mark at pogo dot org dot uk>)
Originally committed as revision 896 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
		
				
					committed by
					
						 Michael Niedermayer
						Michael Niedermayer
					
				
			
			
				
	
			
			
			
						parent
						
							ad324c9351
						
					
				
				
					commit
					81e0d0b412
				
			
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							| @@ -36,6 +36,9 @@ DEP_LIBS=libavcodec/libavcodec.a libav/libavformat.a | ||||
| ifeq ($(CONFIG_MP3LAME),yes) | ||||
| EXTRALIBS+=-lmp3lame | ||||
| endif | ||||
| ifeq ($(CONFIG_VORBIS),yes) | ||||
| EXTRALIBS+=-logg -lvorbis -lvorbisenc | ||||
| endif | ||||
| endif | ||||
|  | ||||
| OBJS = ffmpeg.o ffserver.o | ||||
|   | ||||
							
								
								
									
										10
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -48,6 +48,7 @@ audio_oss="yes" | ||||
| network="yes" | ||||
| zlib="yes" | ||||
| mp3lame="no" | ||||
| vorbis="no" | ||||
| a52="yes" | ||||
| a52bin="no" | ||||
| win32="no" | ||||
| @@ -176,6 +177,8 @@ for opt do | ||||
|   ;; | ||||
|   --enable-mp3lame) mp3lame="yes" | ||||
|   ;; | ||||
|   --enable-vorbis) vorbis="yes" | ||||
|   ;; | ||||
|   --disable-vhook) vhook="no" | ||||
|   ;; | ||||
|   --disable-simple_idct) simpleidct="no" | ||||
| @@ -305,6 +308,7 @@ echo "Standard options:" | ||||
| echo "  --help                   print this message" | ||||
| echo "  --prefix=PREFIX          install in PREFIX [$prefix]" | ||||
| echo "  --enable-mp3lame         enable mp3 encoding via libmp3lame [default=no]" | ||||
| echo "  --enable-vorbis          enable vorbis support via libvorbisenc [default=no]" | ||||
| echo "  --enable-win32           enable win32 cross compile" | ||||
| echo "  --disable-a52            disable GPL'ed A52 support [default=no]" | ||||
| echo "  --enable-a52bin          open liba52.so.0 at runtime [default=no]" | ||||
| @@ -344,6 +348,7 @@ echo "MMX enabled      $mmx" | ||||
| echo "gprof enabled    $gprof" | ||||
| echo "zlib enabled     $zlib" | ||||
| echo "mp3lame enabled  $mp3lame" | ||||
| echo "vorbis enabled   $vorbis" | ||||
| echo "a52 support      $a52" | ||||
| echo "a52 dlopened     $a52bin" | ||||
| # echo "Video hooking    $vhook" | ||||
| @@ -460,6 +465,11 @@ if test "$mp3lame" = "yes" ; then | ||||
|   echo "CONFIG_MP3LAME=yes" >> config.mak | ||||
| fi | ||||
|  | ||||
| if test "$vorbis" = "yes" ; then | ||||
|   echo "#define CONFIG_VORBIS 1" >> $TMPH | ||||
|   echo "CONFIG_VORBIS=yes" >> config.mak | ||||
| fi | ||||
|  | ||||
| if test "$win32" = "yes" ; then | ||||
|   echo "#define CONFIG_WIN32 1" >> $TMPH | ||||
|   echo "CONFIG_WIN32=yes" >> config.mak | ||||
|   | ||||
| @@ -3665,6 +3665,11 @@ int parse_ffconfig(const char *filename) | ||||
|             if (stream) { | ||||
|                 audio_enc.sample_rate = atoi(arg); | ||||
|             } | ||||
| 	} else if (!strcasecmp(cmd, "AudioQuality")) { | ||||
| 	    get_arg(arg, sizeof(arg), &p); | ||||
|             if (stream) { | ||||
|                 audio_enc.quality = atof(arg) * 1000; | ||||
|             } | ||||
|         } else if (!strcasecmp(cmd, "VideoBitRate")) { | ||||
|             get_arg(arg, sizeof(arg), &p); | ||||
|             if (stream) { | ||||
|   | ||||
| @@ -33,6 +33,10 @@ ifeq ($(CONFIG_NETWORK),yes) | ||||
| OBJS+= udp.o tcp.o http.o rtsp.o rtp.o rtpproto.o | ||||
| endif | ||||
|  | ||||
| ifeq ($(CONFIG_VORBIS),yes) | ||||
| OBJS+= ogg.o | ||||
| endif | ||||
|  | ||||
| LIB= libavformat.a | ||||
|  | ||||
| all: $(LIB) | ||||
|   | ||||
| @@ -45,6 +45,10 @@ void av_register_all(void) | ||||
|     mov_init(); | ||||
|     jpeg_init(); | ||||
|  | ||||
| #ifdef CONFIG_VORBIS | ||||
|     ogg_init(); | ||||
| #endif | ||||
|  | ||||
| #ifndef CONFIG_WIN32 | ||||
|     ffm_init(); | ||||
| #endif | ||||
|   | ||||
| @@ -213,6 +213,9 @@ int wav_init(void); | ||||
| /* raw.c */ | ||||
| int raw_init(void); | ||||
|  | ||||
| /* ogg.c */ | ||||
| int ogg_init(void); | ||||
|  | ||||
| /* ffm.c */ | ||||
| int ffm_init(void); | ||||
|  | ||||
|   | ||||
| @@ -151,6 +151,7 @@ static int ffm_write_header(AVFormatContext *s) | ||||
|         put_be32(pb, codec->codec_id); | ||||
|         put_byte(pb, codec->codec_type); | ||||
|         put_be32(pb, codec->bit_rate); | ||||
| 	put_be32(pb, codec->quality); | ||||
|         put_be32(pb, codec->flags); | ||||
|         /* specific info */ | ||||
|         switch(codec->codec_type) { | ||||
| @@ -393,6 +394,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) | ||||
|         st->codec.codec_id = get_be32(pb); | ||||
|         st->codec.codec_type = get_byte(pb); /* codec_type */ | ||||
|         codec->bit_rate = get_be32(pb); | ||||
| 	codec->quality = get_be32(pb); | ||||
|         codec->flags = get_be32(pb); | ||||
|         /* specific info */ | ||||
|         switch(codec->codec_type) { | ||||
|   | ||||
							
								
								
									
										168
									
								
								libav/ogg.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								libav/ogg.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| /* | ||||
|  * Ogg bitstream support | ||||
|  * Mark Hills <mark@pogo.org.uk> | ||||
|  * | ||||
|  * Uses libogg, but requires libvorbisenc to construct correct headers | ||||
|  * when containing Vorbis stream -- currently the only format supported | ||||
|  */ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <time.h> | ||||
|  | ||||
| #include <ogg/ogg.h> | ||||
| #include <vorbis/vorbisenc.h> | ||||
|  | ||||
| #include "avformat.h" | ||||
| #include "oggvorbis.h" | ||||
|  | ||||
|  | ||||
| typedef struct OggContext { | ||||
|     ogg_stream_state os ; | ||||
|     int header_written ; | ||||
|     ogg_int64_t base_packet_no ; | ||||
|     ogg_int64_t base_granule_pos ; | ||||
| } OggContext ; | ||||
|  | ||||
|  | ||||
| static int ogg_write_header(AVFormatContext *avfcontext) { | ||||
|     OggContext *context ; | ||||
|     AVCodecContext *avccontext ; | ||||
|     vorbis_info vi ; | ||||
|     vorbis_dsp_state vd ; | ||||
|     vorbis_comment vc ; | ||||
|     vorbis_block vb ; | ||||
|     ogg_packet header, header_comm, header_code ;  | ||||
|     int n ; | ||||
|      | ||||
|     fprintf(stderr, "ogg_write_header\n") ; | ||||
|      | ||||
|     if(!(context = malloc(sizeof(OggContext)))) | ||||
| 	return -1 ; | ||||
|     avfcontext->priv_data = context ; | ||||
|      | ||||
|     srand(time(NULL)); | ||||
|     ogg_stream_init(&context->os, rand()); | ||||
|      | ||||
|     for(n = 0 ; n < avfcontext->nb_streams ; n++) { | ||||
| 	avccontext = &avfcontext->streams[n]->codec ; | ||||
|  | ||||
| 	/* begin vorbis specific code */ | ||||
| 		 | ||||
| 	vorbis_info_init(&vi) ; | ||||
|  | ||||
| 	/* code copied from libavcodec/oggvorbis.c */ | ||||
|  | ||||
| 	if(oggvorbis_init_encoder(&vi, avccontext) < 0) { | ||||
| 	    fprintf(stderr, "ogg_write_header: init_encoder failed") ; | ||||
| 	    return -1 ; | ||||
| 	} | ||||
|  | ||||
| 	vorbis_analysis_init(&vd, &vi) ; | ||||
| 	vorbis_block_init(&vd, &vb) ; | ||||
| 	 | ||||
| 	vorbis_comment_init(&vc) ; | ||||
| 	vorbis_comment_add_tag(&vc, "encoder", "ffmpeg") ; | ||||
| 	if(*avfcontext->title) | ||||
| 	    vorbis_comment_add_tag(&vc, "title", avfcontext->title) ; | ||||
|  | ||||
| 	vorbis_analysis_headerout(&vd, &vc, &header, | ||||
| 				  &header_comm, &header_code) ; | ||||
| 	ogg_stream_packetin(&context->os, &header) ; | ||||
| 	ogg_stream_packetin(&context->os, &header_comm) ; | ||||
| 	ogg_stream_packetin(&context->os, &header_code) ;   | ||||
| 	 | ||||
| 	vorbis_comment_clear(&vc) ; | ||||
|  | ||||
| 	/* end of vorbis specific code */ | ||||
|  | ||||
| 	context->header_written = 0 ; | ||||
| 	context->base_packet_no = 0 ; | ||||
|     } | ||||
|      | ||||
|     return 0 ; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int ogg_write_packet(AVFormatContext *avfcontext, | ||||
| 			    int stream_index, | ||||
| 			    unsigned char *buf, int size, int force_pts) | ||||
| { | ||||
|     OggContext *context = avfcontext->priv_data ; | ||||
|     ogg_packet *op ; | ||||
|     ogg_page og ; | ||||
|     int l = 0 ; | ||||
|      | ||||
|     /* flush header packets so audio starts on a new page */ | ||||
|  | ||||
|     if(!context->header_written) { | ||||
| 	while(ogg_stream_flush(&context->os, &og)) { | ||||
| 	    put_buffer(&avfcontext->pb, og.header, og.header_len) ; | ||||
| 	    put_buffer(&avfcontext->pb, og.body, og.body_len) ; | ||||
| 	    put_flush_packet(&avfcontext->pb); | ||||
| 	} | ||||
| 	context->header_written = 1 ; | ||||
|     } | ||||
|  | ||||
|     while(l < size) { | ||||
| 	op = (ogg_packet*)(buf + l) ; | ||||
| 	op->packet = buf + l + sizeof(ogg_packet) ; /* fix data pointer */ | ||||
|  | ||||
| 	if(!context->base_packet_no) { /* this is the first packet */ | ||||
| 	    context->base_packet_no = op->packetno ;  | ||||
| 	    context->base_granule_pos = op->granulepos ; | ||||
| 	} | ||||
|  | ||||
| 	/* correct the fields in the packet -- essential for streaming */ | ||||
|  | ||||
| 	op->packetno -= context->base_packet_no ; | ||||
| 	op->granulepos -= context->base_granule_pos ; | ||||
|  | ||||
| 	ogg_stream_packetin(&context->os, op) ; | ||||
| 	l += sizeof(ogg_packet) + op->bytes ; | ||||
|  | ||||
| 	while(ogg_stream_pageout(&context->os, &og)) { | ||||
| 	    put_buffer(&avfcontext->pb, og.header, og.header_len) ; | ||||
| 	    put_buffer(&avfcontext->pb, og.body, og.body_len) ; | ||||
| 	    put_flush_packet(&avfcontext->pb); | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int ogg_write_trailer(AVFormatContext *avfcontext) { | ||||
|     OggContext *context = avfcontext->priv_data ; | ||||
|     ogg_page og ; | ||||
|  | ||||
|     fprintf(stderr, "ogg_write_trailer\n") ; | ||||
|  | ||||
|     while(ogg_stream_flush(&context->os, &og)) { | ||||
| 	put_buffer(&avfcontext->pb, og.header, og.header_len) ; | ||||
| 	put_buffer(&avfcontext->pb, og.body, og.body_len) ; | ||||
| 	put_flush_packet(&avfcontext->pb); | ||||
|     } | ||||
|  | ||||
|     ogg_stream_clear(&context->os) ; | ||||
|     return 0 ; | ||||
| } | ||||
|  | ||||
|  | ||||
| AVOutputFormat ogg_oformat = { | ||||
|     "ogg", | ||||
|     "Ogg Vorbis", | ||||
|     "audio/x-vorbis", | ||||
|     "ogg", | ||||
|     sizeof(OggContext), | ||||
|     CODEC_ID_VORBIS, | ||||
|     0, | ||||
|     ogg_write_header, | ||||
|     ogg_write_packet, | ||||
|     ogg_write_trailer, | ||||
| }; | ||||
|  | ||||
|  | ||||
| int ogg_init(void) { | ||||
|     av_register_output_format(&ogg_oformat) ; | ||||
|     return 0 ; | ||||
| } | ||||
| @@ -34,6 +34,11 @@ OBJS += mp3lameaudio.o | ||||
| EXTRALIBS += -lmp3lame | ||||
| endif | ||||
|  | ||||
| ifeq ($(CONFIG_VORBIS),yes) | ||||
| OBJS += oggvorbis.o | ||||
| EXTRALIBS += -lvorbis -lvorbisenc | ||||
| endif | ||||
|  | ||||
| ifeq ($(TARGET_GPROF),yes) | ||||
| CFLAGS+=-p | ||||
| LDFLAGS+=-p | ||||
|   | ||||
| @@ -38,6 +38,9 @@ void avcodec_register_all(void) | ||||
|     register_avcodec(&mp2_encoder); | ||||
| #ifdef CONFIG_MP3LAME | ||||
|     register_avcodec(&mp3lame_encoder); | ||||
| #endif | ||||
| #ifdef CONFIG_VORBIS | ||||
|     register_avcodec(&oggvorbis_encoder); | ||||
| #endif | ||||
|     register_avcodec(&mpeg1video_encoder); | ||||
|     register_avcodec(&h263_encoder); | ||||
|   | ||||
| @@ -15,6 +15,7 @@ enum CodecID { | ||||
|     CODEC_ID_RV10, | ||||
|     CODEC_ID_MP2, | ||||
|     CODEC_ID_MP3LAME, | ||||
|     CODEC_ID_VORBIS, | ||||
|     CODEC_ID_AC3, | ||||
|     CODEC_ID_MJPEG, | ||||
|     CODEC_ID_MPEG4, | ||||
| @@ -389,6 +390,7 @@ typedef struct AVPicture { | ||||
| extern AVCodec ac3_encoder; | ||||
| extern AVCodec mp2_encoder; | ||||
| extern AVCodec mp3lame_encoder; | ||||
| extern AVCodec oggvorbis_encoder; | ||||
| extern AVCodec mpeg1video_encoder; | ||||
| extern AVCodec h263_encoder; | ||||
| extern AVCodec h263p_encoder; | ||||
|   | ||||
							
								
								
									
										140
									
								
								libavcodec/oggvorbis.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								libavcodec/oggvorbis.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| /* | ||||
|  * Ogg Vorbis codec support via libvorbisenc | ||||
|  * Mark Hills <mark@pogo.org.uk> | ||||
|  */ | ||||
|  | ||||
| #include <time.h> | ||||
|  | ||||
| #include <vorbis/vorbisenc.h> | ||||
|  | ||||
| #include "avcodec.h" | ||||
| #include "oggvorbis.h" | ||||
|  | ||||
| #define OGGVORBIS_FRAME_SIZE 1024 | ||||
|  | ||||
|  | ||||
| typedef struct OggVorbisContext { | ||||
|     vorbis_info vi ; | ||||
|     vorbis_dsp_state vd ; | ||||
|     vorbis_block vb ; | ||||
| } OggVorbisContext ; | ||||
|  | ||||
|  | ||||
| int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) { | ||||
|     if(avccontext->quality) { /* VBR requested */ | ||||
|  | ||||
| 	fprintf(stderr, "init_encode: channels=%d quality=%d\n",  | ||||
| 		avccontext->channels, avccontext->quality) ; | ||||
|  | ||||
| 	return vorbis_encode_init_vbr(vi, avccontext->channels, | ||||
| 		  avccontext->sample_rate, (float)avccontext->quality / 1000) ; | ||||
|     } | ||||
|  | ||||
|     fprintf(stderr, "init_encoder: channels=%d bitrate=%d tolerance=%d\n",  | ||||
| 	    avccontext->channels, avccontext->bit_rate, | ||||
| 	    avccontext->bit_rate_tolerance) ; | ||||
|  | ||||
|     return vorbis_encode_init(vi, avccontext->channels, | ||||
| 	          avccontext->sample_rate, -1, avccontext->bit_rate, -1) ; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int oggvorbis_encode_init(AVCodecContext *avccontext) { | ||||
|     OggVorbisContext *context = avccontext->priv_data ; | ||||
|  | ||||
|     fprintf(stderr, "oggvorbis_encode_init\n") ; | ||||
|  | ||||
|     vorbis_info_init(&context->vi) ; | ||||
|  | ||||
|     if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) { | ||||
| 	fprintf(stderr, "oggvorbis_encode_init: init_encoder failed") ; | ||||
| 	return -1 ; | ||||
|     } | ||||
|  | ||||
|     vorbis_analysis_init(&context->vd, &context->vi) ; | ||||
|     vorbis_block_init(&context->vd, &context->vb) ; | ||||
|  | ||||
|     avccontext->frame_size = OGGVORBIS_FRAME_SIZE ; | ||||
|      | ||||
|     return 0 ; | ||||
| } | ||||
|  | ||||
|  | ||||
| int oggvorbis_encode_frame(AVCodecContext *avccontext, unsigned char *packets, | ||||
| 			   int buf_size, void *data) | ||||
| { | ||||
|     OggVorbisContext *context = avccontext->priv_data ; | ||||
|     float **buffer ; | ||||
|     ogg_packet op ; | ||||
|     signed char *audio = data ; | ||||
|     int l, samples = buf_size / 16 ; /* samples = OGGVORBIS_FRAME_SIZE */ ; | ||||
|  | ||||
|     buffer = vorbis_analysis_buffer(&context->vd, samples) ; | ||||
|  | ||||
|     if(context->vi.channels == 1) { | ||||
| 	for(l = 0 ; l < samples ; l++) | ||||
| 	    buffer[0][l]=((audio[l*2+1]<<8)|(0x00ff&(int)audio[l*2]))/32768.f; | ||||
|     } else { | ||||
| 	for(l = 0 ; l < samples ; l++){ | ||||
| 	    buffer[0][l]=((audio[l*4+1]<<8)|(0x00ff&(int)audio[l*4]))/32768.f; | ||||
| 	    buffer[1][l]=((audio[l*4+3]<<8)|(0x00ff&(int)audio[l*4+2]))/32768.f; | ||||
| 	} | ||||
|     } | ||||
|      | ||||
|     vorbis_analysis_wrote(&context->vd, samples) ;  | ||||
|  | ||||
|     l = 0 ; | ||||
|  | ||||
|     while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) { | ||||
| 	vorbis_analysis(&context->vb, NULL); | ||||
| 	vorbis_bitrate_addblock(&context->vb) ; | ||||
|  | ||||
| 	while(vorbis_bitrate_flushpacket(&context->vd, &op)) { | ||||
| 	    memcpy(packets + l, &op, sizeof(ogg_packet)) ; | ||||
| 	    memcpy(packets + l + sizeof(ogg_packet), op.packet, op.bytes) ; | ||||
| 	    l += sizeof(ogg_packet) + op.bytes ; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     return l ; | ||||
| } | ||||
|  | ||||
|  | ||||
| int oggvorbis_encode_close(AVCodecContext *avccontext) { | ||||
|     OggVorbisContext *context = avccontext->priv_data ; | ||||
| /*  ogg_packet op ; */ | ||||
|      | ||||
|     fprintf(stderr, "oggvorbis_encode_close\n") ; | ||||
|      | ||||
|     vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */ | ||||
|  | ||||
|     /* We need to write all the remaining packets into the stream | ||||
|      * on closing */ | ||||
|      | ||||
| /* | ||||
|     while(vorbis_bitrate_flushpacket(&context->vd, &op)) { | ||||
| 	memcpy(packets + l, &op, sizeof(ogg_packet)) ; | ||||
| 	memcpy(packets + l + sizeof(ogg_packet), op.packet, op.bytes) ; | ||||
| 	l += sizeof(ogg_packet) + op.bytes ;	 | ||||
|     } | ||||
| */ | ||||
|  | ||||
|     vorbis_block_clear(&context->vb); | ||||
|     vorbis_dsp_clear(&context->vd); | ||||
|     vorbis_info_clear(&context->vi); | ||||
|    | ||||
|     return 0 ; | ||||
| } | ||||
|  | ||||
|  | ||||
| AVCodec oggvorbis_encoder = { | ||||
|     "vorbis", | ||||
|     CODEC_TYPE_AUDIO, | ||||
|     CODEC_ID_VORBIS, | ||||
|     sizeof(OggVorbisContext), | ||||
|     oggvorbis_encode_init, | ||||
|     oggvorbis_encode_frame, | ||||
|     oggvorbis_encode_close | ||||
| }; | ||||
|  | ||||
|  | ||||
							
								
								
									
										10
									
								
								libavcodec/oggvorbis.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								libavcodec/oggvorbis.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| #ifndef AVCODEC_OGGVORBIS_H | ||||
| #define AVCODEC_OGGVORBIS_H | ||||
|  | ||||
| #include <vorbis/vorbisenc.h> | ||||
|  | ||||
| #include "avcodec.h" | ||||
|  | ||||
| int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) ; | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user