⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkv_decode.c.svn-base

📁 psp播放器PPA源码,在MSYS/CYGWIN环境下编译(GNU-C)
💻 SVN-BASE
字号:
/*  *	Copyright (C) 2009 cooleyes *	eyes.cooleyes@gmail.com  * *  This Program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  This Program 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 General Public License for more details. *    *  You should have received a copy of the GNU General Public License *  along with GNU Make; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *  http://www.gnu.org/copyleft/gpl.html * */#include "mkv_decode.h"#include "me_boot_start.h"#include "audio_util.h"static int in_mkv_timestamp_queue(int* queue, unsigned int* queue_size, unsigned int queue_max, int timestamp) {	if ( *queue_size+1 > queue_max )		return 0;	int i,j;	for(i=0; i<*queue_size; i++) {		if ( timestamp < queue[i] ) {			for(j=*queue_size-1; j>=i; j--) {				queue[j+1] = queue[j];			}					break;		}	}	queue[i] = timestamp;	*queue_size += 1;	return 1;}static int out_mkv_timestamp_queue(int* queue, unsigned int* queue_size, unsigned int queue_max, int* timestamp) {	if ( *queue_size == 0 )		return 0;	*timestamp  = queue[0];	int i;	for(i=1; i<*queue_size; i++)		queue[i-1] = queue[i];	queue[i-1] = -1;	*queue_size -= 1;	return 1;}static void clear_mkv_timestamp_queue(int* queue, unsigned int* queue_size, unsigned int queue_max) {	int i;	for(i=0; i<queue_max; i++) {		queue[i] = -1;	}	*queue_size = 0;}void mkv_decode_safe_constructor(struct mkv_decode_struct *p) {	mkv_read_safe_constructor(&p->reader);	mp4_avc_safe_constructor(&p->avc);	mp4v_safe_constructor(&p->mp4v);	int i = 0;	for (; i < mkv_maximum_frame_buffers; i++) {		p->video_frame_buffers[i] = 0;		p->audio_frame_buffers[i] = 0;	}		clear_mkv_timestamp_queue(p->timestamp_queue, &p->timestamp_queue_size, mkv_timestamp_queue_max);	p->last_audio_timestamp = 0;	p->last_video_timestamp = 0;	p->is_eof = 0;}void mkv_decode_close(struct mkv_decode_struct *p, int pspType) {	mkv_read_close(&p->reader);		if (p->video_format == 0x61766331 /*avc1*/)		mp4_avc_close(&p->avc);	else		mp4v_close(&p->mp4v);	if (p->audio_decoder == 0 )		audio_decoder_close();	int i = 0;	if (m33IsTVOutSupported(pspType)) {		for (; i < mkv_maximum_frame_buffers; i++) {			if (p->audio_frame_buffers[i] != 0) 				free_64(p->audio_frame_buffers[i]);		}	}	else {		for (; i < mkv_maximum_frame_buffers; i++) {			if (p->video_frame_buffers[i] != 0) 				free_64(p->video_frame_buffers[i]);			if (p->audio_frame_buffers[i] != 0) 				free_64(p->audio_frame_buffers[i]);		}	}	mkv_decode_safe_constructor(p);}char *mkv_decode_open(struct mkv_decode_struct *p, char *s, int pspType, int tvAspectRatio, int tvWidth, int tvHeight, int videoMode) {		mkv_decode_safe_constructor(p);		cpu_clock_set_maximum();	char *result = mkv_read_open(&p->reader, s);	if (result != 0) {		mkv_decode_close(p, pspType);		return(result);	}	p->audio_frame_size = (p->reader.file.audio_resample_scale << 1) << p->reader.file.audio_stereo;	p->video_format = p->reader.file.video_type;		if ( p->video_format == 0x61766331 /*avc1*/ ) {		if ( p->reader.file.video_width > 480 || p->reader.file.video_height > 272 ) {			me_boot_start(1);		}		else if ( p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data[1] == 0x42 ) {			me_boot_start(4);		}		else {			me_boot_start(3);		}	}	else {		me_boot_start(3);	}	if ( p->video_format == 0x61766331 /*avc1*/ ) {		int avc_profile = p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data[1];		int avc_nal_prefix_size = ( p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data[4] & 0x03 ) + 1;		int avc_sps_size = p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data[6];		avc_sps_size = (avc_sps_size << 8) | p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data[7];		int avc_pps_size = p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data[9+avc_sps_size];		avc_pps_size = (avc_pps_size << 8) | p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data[10+avc_sps_size];				result = mp4_avc_open(&p->avc, 			avc_profile,			((p->reader.file.video_width > 480 || p->reader.file.video_height > 272) ? 5 : 4), 			p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data+8, 			avc_sps_size,			p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data+8+avc_sps_size+3, 			avc_pps_size,			avc_nal_prefix_size);	}	else {		result = "mp4v_open: no supported";//		result = mp4v_open_ex(&p->mp4v,//			p->reader.file.info->tracks[p->reader.file.video_track_id]->private_data,//			p->reader.file.info->tracks[p->reader.file.video_track_id]->private_size,//			p->reader.file.maximum_video_sample_size);	}	if (result != 0) {		mkv_decode_close(p, pspType);		return(result);	}	aspect_ratio_struct_init(p->reader.file.video_width, p->reader.file.video_height, p->reader.file.display_width, p->reader.file.display_height, pspType, tvAspectRatio, tvWidth, tvHeight, videoMode);		//*/	if ( p->reader.file.audio_type == 0x6D703461 /*mp4a*/ )		p->audio_decoder = audio_decoder_open(0x1003, p->reader.file.audio_actual_rate, p->reader.file.audio_scale, 0);	else		p->audio_decoder = -1;	if (p->audio_decoder == -1) {		mkv_decode_close(p, pspType);		return("mkv_decode_open: can not find audio decoder");	}	//*/		cpu_clock_set_minimum();	int i = 0;	if (m33IsTVOutSupported(pspType)) {		p->output_texture_width = 768;		p->number_of_frame_buffers = 8;				i = 0;		for (; i < p->number_of_frame_buffers; i++) {			p->video_frame_size = 1572864;			p->video_frame_buffers[i] = (void*)(0x0a000000 + (i+1)*p->video_frame_size);			//p->video_frame_buffers[i] = (void*)(0x0a000000 + i*p->video_frame_size);			memset(p->video_frame_buffers[i], 0, p->video_frame_size);		}	}	else {		p->output_texture_width = 512;		p->number_of_frame_buffers = 0;		p->video_frame_size = 557056;		i = 0;		for (; i < mkv_maximum_frame_buffers; i++) {			p->video_frame_buffers[i] = malloc_64(p->video_frame_size);				if (p->video_frame_buffers[i] == 0) {				break;			}				memset(p->video_frame_buffers[i], 0, p->video_frame_size);				p->number_of_frame_buffers ++;		}				if (p->number_of_frame_buffers < (mkv_number_of_free_video_frame_buffers + 4)) {			mkv_decode_close(p, pspType);			return("mkv_decode_open: number_of_frame_buffers < 4");		}				p->number_of_frame_buffers -= mkv_number_of_free_video_frame_buffers;			i = 0;		for (; i < mkv_number_of_free_video_frame_buffers; i++) {			free_64(p->video_frame_buffers[p->number_of_frame_buffers + i]);				p->video_frame_buffers[p->number_of_frame_buffers + i] = 0;		}	}	i = 0;	for (; i <= p->number_of_frame_buffers; i++) {		// p->audio_frame_buffers[p->number_of_frame_buffers] is a null buffer			p->audio_frame_buffers[i] = malloc_64(p->audio_frame_size);		if (p->audio_frame_buffers[i] == 0) {			mkv_decode_close(p, pspType);			return("mkv_decode_open: malloc_64 failed on audio_frame_buffers");		}		memset(p->audio_frame_buffers[i], 0, p->audio_frame_size);	}	sceDisplayWaitVblankStart();	sceDisplaySetFrameBuf(p->video_frame_buffers[0], p->output_texture_width, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_IMMEDIATE);	p->current_video_buffer_number = 0;	p->current_audio_buffer_number = 0;		uint64_t duration = 1000LL;	duration *= p->reader.file.video_scale;	duration /= p->reader.file.video_rate;	p->video_frame_duration = duration;		duration = 1000LL;	duration *= p->reader.file.audio_resample_scale;	duration /= p->reader.file.audio_rate;	p->audio_frame_duration = duration;		pmp_gu_init_previous_values();		return(0);}int   mkv_decode_is_eof(struct mkv_decode_struct *p) {	return (p->is_eof);}void  mkv_decode_reset(struct mkv_decode_struct *p) {	mkv_read_seek(&p->reader, 0);	p->is_eof = 0;}char *mkv_decode_seek(struct mkv_decode_struct *p, int timestamp) {	return mkv_read_seek(&p->reader, timestamp);}char *mkv_decode_get_audio(struct mkv_decode_struct *p, unsigned int audio_stream, int audio_channel, int decode_audio, unsigned int volume_boost) {	char *result;	struct mkv_read_output_struct a_packet;	memset(&a_packet, 0, sizeof(struct mkv_read_output_struct));		result = mkv_read_get_audio(&p->reader, audio_stream, &a_packet);	if (result != 0) {		a_packet.timestamp = p->last_audio_timestamp + p->audio_frame_duration;	}		if (a_packet.data == 0 || decode_audio == 0) {		p->output_audio_frame_buffers[p->current_audio_buffer_number].data = p->audio_frame_buffers[p->number_of_frame_buffers];	}	else {		p->output_audio_frame_buffers[p->current_audio_buffer_number].data = p->audio_frame_buffers[p->current_audio_buffer_number];				int audio_output_length;					if (p->reader.file.audio_double_sample) {			audio_decoder_decode(p->audio_frame_buffers[p->number_of_frame_buffers], &audio_output_length, a_packet.data, a_packet.size);			pcm_double_sample(p->audio_frame_buffers[p->current_audio_buffer_number], 				p->audio_frame_buffers[p->number_of_frame_buffers],				p->reader.file.audio_resample_scale / 2);			memset(p->audio_frame_buffers[p->number_of_frame_buffers], 0, p->audio_frame_size);		}		else			audio_decoder_decode(p->audio_frame_buffers[p->current_audio_buffer_number], &audio_output_length, a_packet.data, a_packet.size);						pcm_normalize(p->audio_frame_buffers[p->current_audio_buffer_number], p->reader.file.audio_resample_scale << p->reader.file.audio_stereo);		pcm_select_channel(p->audio_frame_buffers[p->current_audio_buffer_number], p->reader.file.audio_resample_scale << p->reader.file.audio_stereo, audio_channel);					free_64( a_packet.data );	}		p->output_audio_frame_buffers[p->current_audio_buffer_number].timestamp = a_packet.timestamp;	p->last_audio_timestamp = a_packet.timestamp;	p->current_audio_buffer_number = (p->current_audio_buffer_number + 1) % p->number_of_frame_buffers;		return(0);}char *mkv_decode_get_cached_video(struct mkv_decode_struct *p, unsigned int pic_num, unsigned int audio_stream, unsigned int volume_boost, unsigned int aspect_ratio, unsigned int zoom, unsigned int luminosity_boost, unsigned int show_interface, unsigned int show_subtitle, unsigned int subtitle_format, unsigned int loop) {	char *result;	sceKernelDcacheWritebackInvalidateAll();	result = mp4_avc_get_cache(&p->avc, pmp_gu_rgb_buffer, pic_num);	if (result != 0) {		return(result);	}	int timestamp;	out_mkv_timestamp_queue(p->timestamp_queue, &p->timestamp_queue_size, mkv_timestamp_queue_max, &timestamp);	double tmp ;	tmp = 1.0f*timestamp;	tmp *= p->reader.file.video_rate;	tmp /= p->reader.file.video_scale;	tmp /= 1000.0f;	if (show_interface == 1){		draw_interface(			p->reader.file.video_scale,			p->reader.file.video_rate,			p->reader.file.number_of_video_frames,			(unsigned int)tmp,			aspect_ratio,			zoom,			luminosity_boost,			audio_stream,			volume_boost,			loop);	}	sceKernelDcacheWritebackInvalidateAll();		pmp_gu_draw(aspect_ratio, zoom, luminosity_boost, show_interface, show_subtitle, subtitle_format, (unsigned int)tmp, p->video_frame_buffers[p->current_video_buffer_number]);		p->output_video_frame_buffers[p->current_video_buffer_number].data            = p->video_frame_buffers[p->current_video_buffer_number];	pmp_gu_wait();		p->output_video_frame_buffers[p->current_video_buffer_number].timestamp = timestamp;	p->last_video_timestamp = timestamp;	p->current_video_buffer_number = (p->current_video_buffer_number + 1) % p->number_of_frame_buffers;	sceKernelDcacheWritebackInvalidateAll();	return(0);}char *mkv_decode_get_video(struct mkv_decode_struct *p, unsigned int audio_stream, unsigned int volume_boost, unsigned int aspect_ratio, unsigned int zoom, unsigned int luminosity_boost, unsigned int show_interface, unsigned int show_subtitle, unsigned int subtitle_format, unsigned int loop, int* pic_num) {		char *result;	struct mkv_read_output_struct v_packet;	memset(&v_packet, 0, sizeof(struct mkv_read_output_struct));		if (p->is_eof) {		*pic_num = 1;		in_mkv_timestamp_queue(p->timestamp_queue, &p->timestamp_queue_size, mkv_timestamp_queue_max, p->last_video_timestamp + p->video_frame_duration);	}	else {		result = mkv_read_get_video(&p->reader, &v_packet);		if (result != 0) {			if ( strcmp(result, "mkv_read_fill_buffer: eof") == 0 ) {				*pic_num = 1;				p->is_eof = 1;				in_mkv_timestamp_queue(p->timestamp_queue, &p->timestamp_queue_size, mkv_timestamp_queue_max, p->last_video_timestamp + p->video_frame_duration);			}			else				return result;		}		else {			sceKernelDcacheWritebackInvalidateAll();						in_mkv_timestamp_queue(p->timestamp_queue, &p->timestamp_queue_size, mkv_timestamp_queue_max, v_packet.timestamp);					if (p->video_format == 0x61766331 /*avc1*/)				result = mp4_avc_get(&p->avc, (v_packet.timestamp==0?3:0), v_packet.data, v_packet.size, pmp_gu_rgb_buffer, pic_num);			else {				result = mp4v_get_rgb(&p->mp4v, v_packet.data, v_packet.size, pmp_gu_rgb_buffer);				*pic_num = 1;			}			if( v_packet.data )				free_64(v_packet.data);			if (result != 0)				return(result);		}	}	*pic_num = *pic_num - 1;		if ( *pic_num >= 0 ) {				int timestamp;		out_mkv_timestamp_queue(p->timestamp_queue, &p->timestamp_queue_size, mkv_timestamp_queue_max, &timestamp);				double tmp ;		tmp = 1.0f*timestamp;		tmp *= p->reader.file.video_rate;		tmp /= p->reader.file.video_scale;		tmp /= 1000.0f;			if (show_interface == 1){			draw_interface(				p->reader.file.video_scale,				p->reader.file.video_rate,				p->reader.file.number_of_video_frames,				(unsigned int)tmp,				aspect_ratio,				zoom,				luminosity_boost,				audio_stream,				volume_boost,				loop);		}				sceKernelDcacheWritebackInvalidateAll();				pmp_gu_draw(aspect_ratio, zoom, luminosity_boost, show_interface, show_subtitle, subtitle_format, (unsigned int)tmp, p->video_frame_buffers[p->current_video_buffer_number]);				p->output_video_frame_buffers[p->current_video_buffer_number].data            = p->video_frame_buffers[p->current_video_buffer_number];			pmp_gu_wait();				p->output_video_frame_buffers[p->current_video_buffer_number].timestamp = timestamp;		p->last_video_timestamp = timestamp;			p->current_video_buffer_number = (p->current_video_buffer_number + 1) % p->number_of_frame_buffers;		sceKernelDcacheWritebackInvalidateAll();	}	return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -