[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11560] branches/soc-2007-hcube/intern/ tinySND/ffmpeg: prepared for implementation

Csaba Hruska csaba.hruska at gmail.com
Sun Aug 12 16:20:39 CEST 2007


Revision: 11560
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11560
Author:   hcube
Date:     2007-08-12 16:20:39 +0200 (Sun, 12 Aug 2007)

Log Message:
-----------
prepared for implementation

Modified Paths:
--------------
    branches/soc-2007-hcube/intern/tinySND/ffmpeg/ffmpegProvider.cpp
    branches/soc-2007-hcube/intern/tinySND/ffmpeg/ffmpegProvider.h

Modified: branches/soc-2007-hcube/intern/tinySND/ffmpeg/ffmpegProvider.cpp
===================================================================
--- branches/soc-2007-hcube/intern/tinySND/ffmpeg/ffmpegProvider.cpp	2007-08-12 14:18:12 UTC (rev 11559)
+++ branches/soc-2007-hcube/intern/tinySND/ffmpeg/ffmpegProvider.cpp	2007-08-12 14:20:39 UTC (rev 11560)
@@ -6,23 +6,468 @@
 
 ffmpegProvider::ffmpegProvider( char *filename )
 {
+	mIsFormatSupported = false;
+/*
+long sound_hdaudio_get_duration(struct hdaudio * hdaudio, int frame_rate)
+	return hdaudio->pFormatCtx->duration * frame_rate / AV_TIME_BASE;
+*/
+
+/*
+	struct hdaudio * rval;
+	int            i, audioStream;
+
+	AVCodec *pCodec;
+	AVFormatContext *pFormatCtx;
+	AVCodecContext *pCodecCtx;
+
+	do_init_ffmpeg();
+
+	if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0) {
+		return 0;
+	}
+
+	if(av_find_stream_info(pFormatCtx)<0) {
+		av_close_input_file(pFormatCtx);
+		return 0;
+	}
+
+	dump_format(pFormatCtx, 0, filename, 0);
+
+
+    // Find the first audio stream
+	audioStream=-1;
+	for(i=0; i<pFormatCtx->nb_streams; i++)
+		if(get_codec_from_stream(pFormatCtx->streams[i])
+		   ->codec_type == CODEC_TYPE_AUDIO)
+		{
+			audioStream=i;
+			break;
+		}
+
+	if(audioStream == -1) {
+		av_close_input_file(pFormatCtx);
+		return 0;
+	}
+
+	pCodecCtx = get_codec_from_stream(pFormatCtx->streams[audioStream]);
+
+        // Find the decoder for the audio stream 
+	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
+	if(pCodec == NULL) {
+		av_close_input_file(pFormatCtx);
+		return 0;
+	}
+
+	if(avcodec_open(pCodecCtx, pCodec)<0) {
+		av_close_input_file(pFormatCtx);
+		return 0;
+	}
+
+	rval = (struct hdaudio *)MEM_mallocN(sizeof(struct hdaudio), 
+					     "hdaudio struct");
+
+	rval->filename = strdup(filename);
+	rval->sample_rate = pCodecCtx->sample_rate;
+	rval->channels = pCodecCtx->channels;
+
+	rval->pFormatCtx = pFormatCtx;
+	rval->pCodecCtx = pCodecCtx;
+	rval->pCodec = pCodec;
+	rval->audioStream = audioStream;
+	rval->frame_position = -10;
+
+	rval->frame_duration = AV_TIME_BASE / 10;
+	rval->frame_alloc_duration = AV_TIME_BASE;
+	rval->decode_cache_size = 
+		(long long) rval->sample_rate * rval->channels
+		* rval->frame_alloc_duration / AV_TIME_BASE
+		* 2;
+
+	rval->decode_cache = (short*) MEM_mallocN(
+		rval->decode_cache_size * sizeof(short)
+		+ AVCODEC_MAX_AUDIO_FRAME_SIZE, 
+		"hdaudio decode cache");
+	rval->decode_cache_zero = rval->decode_cache;
+	rval->decode_pos = 0;
+	rval->target_channels = -1;
+	rval->target_rate = -1;
+	rval->resampler = 0;
+	rval->resample_cache = 0;
+	rval->resample_samples_written = 0;
+	rval->resample_samples_in = 0;
+	return rval;
+*/
+	mIsFormatSupported = true;
 }
 
 ffmpegProvider::~ffmpegProvider(void)
 {
+/*
+	if (hdaudio) {
+		avcodec_close(hdaudio->pCodecCtx);
+		av_close_input_file(hdaudio->pFormatCtx);
+		MEM_freeN (hdaudio->decode_cache);
+		if (hdaudio->resample_cache) {
+			MEM_freeN(hdaudio->resample_cache);
+		}
+		free(hdaudio->filename);
+		MEM_freeN (hdaudio);
+	}
+*/
 }
 
 bool ffmpegProvider::isFormatSupported(void)
 {
-	return false;
+	return mIsFormatSupported;
 }
     
 void ffmpegProvider::seek( int frameNum )
 {
 }
 
-int ffmpegProvider::fillBuffer( float *buffer, int channelIndex, int framesNum )
+int ffmpegProvider::fillBuffer( float *buffer, int framesNum )
 {
 	return 0;
 }
+/*
+static void sound_hdaudio_extract_small_block(
+	struct hdaudio * hdaudio, 
+	short * target_buffer,
+	int sample_position, // units of target_rate 
+	int target_rate,
+	int target_channels,
+	int nb_samples )// in target 
+{
+	AVPacket packet;
+	int frame_position;
+	int frame_size = (long long) target_rate 
+		* hdaudio->frame_duration / AV_TIME_BASE;
+	int in_frame_size = (long long) hdaudio->sample_rate
+		* hdaudio->frame_duration / AV_TIME_BASE;
+	int rate_conversion = 
+		(target_rate != hdaudio->sample_rate) 
+		|| (target_channels != hdaudio->channels);
+	int sample_ofs = target_channels * (sample_position % frame_size);
 
+	frame_position = sample_position / frame_size; 
+
+	if (hdaudio == 0) return;
+
+	if (rate_conversion) {
+		if (hdaudio->resampler && 
+		    (hdaudio->target_rate != target_rate
+		     || hdaudio->target_channels != target_channels)) {
+			audio_resample_close(hdaudio->resampler);
+			hdaudio->resampler = 0;
+		}
+		if (!hdaudio->resampler) {
+			hdaudio->resampler = audio_resample_init(
+				target_channels, hdaudio->channels,
+				target_rate, hdaudio->sample_rate);
+			hdaudio->target_rate = target_rate;
+			hdaudio->target_channels = target_channels;
+			if (hdaudio->resample_cache) {
+				MEM_freeN(hdaudio->resample_cache);
+			}
+			
+
+			hdaudio->resample_cache = (short*) MEM_mallocN(
+				(long long) 
+				hdaudio->target_channels 
+				* frame_size * 2
+				* sizeof(short), 
+				"hdaudio resample cache");
+			if (frame_position == hdaudio->frame_position) {
+				hdaudio->resample_samples_in = 
+					in_frame_size * 7 / 4;
+				hdaudio->resample_samples_written
+					= audio_resample(
+						hdaudio->resampler,
+						hdaudio->resample_cache,
+						hdaudio->decode_cache_zero,
+						in_frame_size * 7 / 4);
+			}
+		}
+	}
+
+	if (frame_position == hdaudio->frame_position + 1
+	    && in_frame_size * hdaudio->channels <= hdaudio->decode_pos) {
+		int bl_size = in_frame_size * hdaudio->channels;
+		int decode_pos = hdaudio->decode_pos;
+	       
+		hdaudio->frame_position = frame_position;
+
+		memmove(hdaudio->decode_cache,
+			hdaudio->decode_cache + bl_size,
+			(decode_pos - bl_size) * sizeof(short));
+		
+		decode_pos -= bl_size;
+
+		memset(hdaudio->decode_cache + decode_pos, 0,
+		       (hdaudio->decode_cache_size - decode_pos) 
+		       * sizeof(short));
+		       
+
+		while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) {
+			int data_size;
+			int len;
+			uint8_t *audio_pkt_data;
+			int audio_pkt_size;
+
+			if(packet.stream_index != hdaudio->audioStream) {
+				av_free_packet(&packet);
+				continue;
+			}
+
+			audio_pkt_data = packet.data;
+			audio_pkt_size = packet.size;
+
+			while (audio_pkt_size > 0) {
+				len = avcodec_decode_audio(
+					hdaudio->pCodecCtx, 
+					hdaudio->decode_cache 
+					+ decode_pos, 
+					&data_size, 
+					audio_pkt_data, 
+					audio_pkt_size);
+				if (len <= 0) {
+					audio_pkt_size = 0;
+					break;
+				}
+				
+				audio_pkt_size -= len;
+				audio_pkt_data += len;
+
+				if (data_size <= 0) {
+					continue;
+				}
+				
+				decode_pos += data_size / sizeof(short);
+				if (decode_pos + data_size
+				    / sizeof(short)
+				    > hdaudio->decode_cache_size) {
+					break;
+				}
+			}
+			av_free_packet(&packet);
+
+			if (decode_pos + data_size / sizeof(short)
+			    > hdaudio->decode_cache_size) {
+				break;
+			}
+		}
+
+		if (rate_conversion) {
+			int written = hdaudio->resample_samples_written
+				* target_channels;
+			int ofs = target_channels * frame_size;
+			int recycle = written - ofs;
+			int next_in = in_frame_size 
+				+ (3.0/4.0 
+				   - (double) recycle / (double) 
+				   (frame_size * target_channels)
+					) * in_frame_size;
+
+			memmove(hdaudio->resample_cache,
+				hdaudio->resample_cache + ofs,
+			        recycle * sizeof(short));
+
+			hdaudio->resample_samples_written
+			       = audio_resample(
+				       hdaudio->resampler,
+				       hdaudio->resample_cache + recycle,
+				       hdaudio->decode_cache_zero
+				       + hdaudio->resample_samples_in
+				       * hdaudio->channels
+				       - bl_size,
+				       next_in)
+				+ recycle / target_channels;
+
+			hdaudio->resample_samples_in = next_in;
+		}
+
+		hdaudio->decode_pos = decode_pos;
+	}
+
+	if (frame_position != hdaudio->frame_position) { 
+		long decode_pos = 0;
+		long long st_time = hdaudio->pFormatCtx
+			->streams[hdaudio->audioStream]->start_time;
+		double time_base = 
+			av_q2d(hdaudio->pFormatCtx
+			       ->streams[hdaudio->audioStream]->time_base);
+		long long pos = (long long) frame_position * AV_TIME_BASE
+			* hdaudio->frame_duration / AV_TIME_BASE;
+
+		long long seek_pos;
+
+		hdaudio->frame_position = frame_position;
+
+		if (st_time == AV_NOPTS_VALUE) {
+			st_time = 0;
+		}
+
+		pos += st_time * AV_TIME_BASE * time_base;
+
+		// seek a little bit before the target position,
+		//   (ffmpeg seek algorithm doesn't seem to work always as
+		//   specified...)
+		
+
+		seek_pos = pos - (AV_TIME_BASE
+				 * hdaudio->frame_duration 
+				  / AV_TIME_BASE / 10);
+		if (seek_pos < 0) {
+			seek_pos = pos;
+		}
+
+		av_seek_frame(hdaudio->pFormatCtx, -1, 
+			      seek_pos, 
+			      AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
+		avcodec_flush_buffers(hdaudio->pCodecCtx);
+
+		memset(hdaudio->decode_cache, 0,
+		       hdaudio->decode_cache_size * sizeof(short));
+
+		hdaudio->decode_cache_zero = hdaudio->decode_cache;
+
+		while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) {
+			int data_size;
+			int len;
+			uint8_t *audio_pkt_data;
+			int audio_pkt_size;
+
+			if(packet.stream_index != hdaudio->audioStream) {
+				av_free_packet(&packet);
+				continue;
+			}
+
+			audio_pkt_data = packet.data;
+			audio_pkt_size = packet.size;
+
+			if (!hdaudio->decode_cache_zero 
+			    && audio_pkt_size > 0) { 
+				long long diff;
+
+				if (packet.pts == AV_NOPTS_VALUE) {
+					fprintf(stderr,
+						"hdaudio: audio "
+						"pts=NULL audio "
+						"distortion!\n");
+					diff = 0;
+				} else {
+					long long pts = packet.pts;
+					long long spts = (long long) (
+						pos / time_base / AV_TIME_BASE 
+						+ 0.5);
+					diff = spts - pts;
+					if (diff < 0) {
+						fprintf(stderr,
+							"hdaudio: "
+							"negative seek: "
+							"%lld < %lld "
+							"(pos=%lld) "
+							"audio distortion!!\n",
+							spts, pts, pos);
+						diff = 0;
+					}
+				}
+
+
+				diff *= hdaudio->sample_rate * time_base;
+				diff *= hdaudio->channels;
+
+				if (diff > hdaudio->decode_cache_size / 2) {
+					fprintf(stderr,
+						"hdaudio: audio "
+						"diff too large!!\n");
+					diff = 0;
+				}
+
+				hdaudio->decode_cache_zero
+					= hdaudio->decode_cache + diff;
+			}
+
+			while (audio_pkt_size > 0) {
+				len = avcodec_decode_audio(
+					hdaudio->pCodecCtx, 
+					hdaudio->decode_cache 
+					+ decode_pos, 
+					&data_size, 
+					audio_pkt_data, 
+					audio_pkt_size);
+				if (len <= 0) {
+					audio_pkt_size = 0;
+					break;
+				}
+				
+				audio_pkt_size -= len;
+				audio_pkt_data += len;
+
+				if (data_size <= 0) {
+					continue;
+				}
+				
+				decode_pos += data_size / sizeof(short);
+				if (decode_pos + data_size
+				    / sizeof(short)
+				    > hdaudio->decode_cache_size) {
+					break;
+				}

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list