From 15318cad33835e4e2dc620d033e43cd930676cdd Mon Sep 17 00:00:00 2001 From: kergoth Date: Fri, 25 Jan 2002 22:14:26 +0000 Subject: Initial revision --- (limited to 'core/multimedia/opieplayer/libmpeg3/libmpeg3.c') diff --git a/core/multimedia/opieplayer/libmpeg3/libmpeg3.c b/core/multimedia/opieplayer/libmpeg3/libmpeg3.c new file mode 100644 index 0000000..c0fc570 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/libmpeg3.c @@ -0,0 +1,672 @@ +#include "libmpeg3.h" +#include "mpeg3protos.h" + +#include +#include + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +mpeg3_t* mpeg3_new(char *path) +{ + int i; + mpeg3_t *file = (mpeg3_t*)calloc(1, sizeof(mpeg3_t)); + file->cpus = 1; + file->fs = mpeg3_new_fs(path); + file->have_mmx = mpeg3_mmx_test(); + file->demuxer = mpeg3_new_demuxer(file, 0, 0, -1); + return file; +} + +int mpeg3_delete(mpeg3_t *file) +{ + int i; + + for(i = 0; i < file->total_vstreams; i++) + mpeg3_delete_vtrack(file, file->vtrack[i]); + + for(i = 0; i < file->total_astreams; i++) + mpeg3_delete_atrack(file, file->atrack[i]); + + mpeg3_delete_fs(file->fs); + mpeg3_delete_demuxer(file->demuxer); + free(file); +} + +int mpeg3_check_sig(char *path) +{ + mpeg3_fs_t *fs; + unsigned int bits; + char *ext; + int result = 0; + + fs = mpeg3_new_fs(path); + if(mpeg3io_open_file(fs)) + { +/* File not found */ + return 0; + } + + bits = mpeg3io_read_int32(fs); +/* Test header */ + if(bits == MPEG3_TOC_PREFIX || bits == MPEG3_TOC_PREFIXLOWER) + { + result = 1; + } + else + if((((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE) || + (bits == MPEG3_PACK_START_CODE) || + ((bits & 0xfff00000) == 0xfff00000) || + (bits == MPEG3_SEQUENCE_START_CODE) || + (bits == MPEG3_PICTURE_START_CODE) || + (((bits & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) || + ((bits >> 8) == MPEG3_ID3_PREFIX) || + (bits == MPEG3_RIFF_CODE)) + { + result = 1; + + ext = strrchr(path, '.'); + if(ext) + { +/* Test file extension. */ + if(strncasecmp(ext, ".mp2", 4) && + strncasecmp(ext, ".mp3", 4) && + strncasecmp(ext, ".m1v", 4) && + strncasecmp(ext, ".m2v", 4) && + strncasecmp(ext, ".m2s", 4) && + strncasecmp(ext, ".mpg", 4) && + strncasecmp(ext, ".vob", 4) && + strncasecmp(ext, ".mpeg", 4) && + strncasecmp(ext, ".ac3", 4)) + result = 0; + } + } + + mpeg3io_close_file(fs); + mpeg3_delete_fs(fs); + return result; +} + +mpeg3_t* mpeg3_open_copy(char *path, mpeg3_t *old_file) +{ + mpeg3_t *file = 0; + unsigned int bits; + int i, done; + +/* Initialize the file structure */ + file = mpeg3_new(path); + +/* Need to perform authentication before reading a single byte. */ + if(mpeg3io_open_file(file->fs)) + { + mpeg3_delete(file); + return 0; + } + +/* =============================== Create the title objects ========================= */ + bits = mpeg3io_read_int32(file->fs); + + if(bits == MPEG3_TOC_PREFIX || bits == MPEG3_TOC_PREFIXLOWER) /* TOCV */ + { +/* Table of contents for another file */ + if(mpeg3_read_toc(file)) + { + mpeg3_delete(file); + return 0; + } + mpeg3io_close_file(file->fs); + } + else + if(((bits >> 24) & 0xff) == MPEG3_SYNC_BYTE) + { +/* Transport stream */ + file->packet_size = MPEG3_TS_PACKET_SIZE; + file->is_transport_stream = 1; + } + else + if(bits == MPEG3_PACK_START_CODE) + { +/* Program stream */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->is_program_stream = 1; + } + else + if((bits & 0xfff00000) == 0xfff00000 || + ((bits >> 8) == MPEG3_ID3_PREFIX) || + (bits == MPEG3_RIFF_CODE)) + { +/* MPEG Audio only */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->has_audio = 1; + file->is_audio_stream = 1; + } + else + if(bits == MPEG3_SEQUENCE_START_CODE || + bits == MPEG3_PICTURE_START_CODE) + { +/* Video only */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->is_video_stream = 1; + } + else + if(((bits & 0xffff0000) >> 16) == MPEG3_AC3_START_CODE) + { +/* AC3 Audio only */ + file->packet_size = MPEG3_DVD_PACKET_SIZE; + file->has_audio = 1; + file->is_audio_stream = 1; + } + else + { +/* file->packet_size = MPEG3_DVD_PACKET_SIZE; */ +/* file->is_audio_stream = 1; */ + mpeg3_delete(file); + fprintf(stderr, "mpeg3_open: not an MPEG 2 stream\n"); + return 0; + } + +/* Create title */ +/* Copy timecodes from an old demuxer */ + if(old_file && mpeg3_get_demuxer(old_file)) + { + mpeg3demux_copy_titles(file->demuxer, mpeg3_get_demuxer(old_file)); + } + else +/* Start from scratch */ + if(!file->demuxer->total_titles) + { + mpeg3demux_create_title(file->demuxer, 0, 0); + } + +/* =============================== Get title information ========================= */ + if(file->is_transport_stream || file->is_program_stream) + { +/* Create video tracks */ +/* Video must be created before audio because audio uses the video timecode */ +/* to get its length. */ + for(i = 0; i < MPEG3_MAX_STREAMS; i++) + { + if(file->demuxer->vstream_table[i]) + { + file->vtrack[file->total_vstreams] = mpeg3_new_vtrack(file, i, file->demuxer); + if(file->vtrack[file->total_vstreams]) file->total_vstreams++; + } + } + +/* Create audio tracks */ + for(i = 0; i < MPEG3_MAX_STREAMS; i++) + { + if(file->demuxer->astream_table[i]) + { + file->atrack[file->total_astreams] = mpeg3_new_atrack(file, + i, + file->demuxer->astream_table[i], + file->demuxer); + if(file->atrack[file->total_astreams]) file->total_astreams++; + } + } + } + else + if(file->is_video_stream) + { +/* Create video tracks */ + file->vtrack[0] = mpeg3_new_vtrack(file, -1, file->demuxer); + if(file->vtrack[0]) file->total_vstreams++; + } + else + if(file->is_audio_stream) + { +/* Create audio tracks */ + file->atrack[0] = mpeg3_new_atrack(file, -1, AUDIO_UNKNOWN, file->demuxer); + if(file->atrack[0]) file->total_astreams++; + } + + if(file->total_vstreams) file->has_video = 1; + if(file->total_astreams) file->has_audio = 1; + + mpeg3io_close_file(file->fs); + return file; +} + +mpeg3_t* mpeg3_open(char *path) +{ + return mpeg3_open_copy(path, 0); +} + +int mpeg3_close(mpeg3_t *file) +{ +/* File is closed in the same procedure it is opened in. */ + mpeg3_delete(file); + return 0; +} + +int mpeg3_set_cpus(mpeg3_t *file, int cpus) +{ + int i; + file->cpus = cpus; + for(i = 0; i < file->total_vstreams; i++) + mpeg3video_set_cpus(file->vtrack[i]->video, cpus); + return 0; +} + +int mpeg3_set_mmx(mpeg3_t *file, int use_mmx) +{ + int i; + file->have_mmx = use_mmx; + for(i = 0; i < file->total_vstreams; i++) + mpeg3video_set_mmx(file->vtrack[i]->video, use_mmx); + return 0; +} + +int mpeg3_generate_toc(FILE *output, char *path, int timecode_search, int print_streams) +{ + mpeg3_t *file = mpeg3_open(path); + mpeg3_demuxer_t *demuxer; + int i; + + if(file) + { + fprintf(output, "TOCVERSION 2\n" + "PATH: %s\n", path); + demuxer = mpeg3_new_demuxer(file, 0, 0, -1); + mpeg3demux_create_title(demuxer, timecode_search, output); +/* Just print the first title's streams */ + if(print_streams) mpeg3demux_print_streams(demuxer, output); + + fprintf(output, "SIZE: %ld\n", demuxer->titles[demuxer->current_title]->total_bytes); + fprintf(output, "PACKETSIZE: %ld\n", demuxer->packet_size); + + mpeg3demux_print_timecodes(demuxer->titles[demuxer->current_title], output); + + mpeg3_delete_demuxer(demuxer); + mpeg3_close(file); + return 0; + } + return 1; +} + +int mpeg3_read_toc(mpeg3_t *file) +{ + char string[MPEG3_STRLEN]; + int number1; + +/* Test version number */ + file->is_program_stream = 1; + mpeg3io_seek(file->fs, 0); + fscanf(file->fs->fd, "%s %d", string, &number1); + if(number1 > 2 || number1 < 2) return 1; + +/* Read titles */ + mpeg3demux_read_titles(file->demuxer); + return 0; +} + +int mpeg3_has_audio(mpeg3_t *file) +{ + return file->has_audio; +} + +int mpeg3_total_astreams(mpeg3_t *file) +{ + return file->total_astreams; +} + +int mpeg3_audio_channels(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->channels; + return -1; +} + +int mpeg3_sample_rate(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->sample_rate; + return -1; +} + +long mpeg3_get_sample(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->current_position; + return -1; +} + +int mpeg3_set_sample(mpeg3_t *file, + long sample, + int stream) +{ + if(file->has_audio) + { + file->atrack[stream]->current_position = sample; + mpeg3audio_seek_sample(file->atrack[stream]->audio, sample); + return 0; + } + return -1; +} + +long mpeg3_audio_samples(mpeg3_t *file, + int stream) +{ + if(file->has_audio) + return file->atrack[stream]->total_samples; + return -1; +} + +int mpeg3_has_video(mpeg3_t *file) +{ + return file->has_video; +} + +int mpeg3_total_vstreams(mpeg3_t *file) +{ + return file->total_vstreams; +} + +int mpeg3_video_width(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->width; + return -1; +} + +int mpeg3_video_height(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->height; + return -1; +} + +float mpeg3_frame_rate(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->frame_rate; + return -1; +} + +long mpeg3_video_frames(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->total_frames; + return -1; +} + +long mpeg3_get_frame(mpeg3_t *file, + int stream) +{ + if(file->has_video) + return file->vtrack[stream]->current_position; + return -1; +} + +int mpeg3_set_frame(mpeg3_t *file, + long frame, + int stream) +{ + if(file->has_video) + { + file->vtrack[stream]->current_position = frame; + mpeg3video_seek_frame(file->vtrack[stream]->video, frame); + return 0; + } + return -1; +} + +int mpeg3_seek_percentage(mpeg3_t *file, double percentage) +{ + int i; + for(i = 0; i < file->total_astreams; i++) + { + mpeg3audio_seek_percentage(file->atrack[i]->audio, percentage); + } + + for(i = 0; i < file->total_vstreams; i++) + { + mpeg3video_seek_percentage(file->vtrack[i]->video, percentage); + } + return 0; +} + +int mpeg3_previous_frame(mpeg3_t *file, int stream) +{ + file->last_type_read = 2; + file->last_stream_read = stream; + + if(file->has_video) + return mpeg3video_previous_frame(file->vtrack[stream]->video); +} + +double mpeg3_tell_percentage(mpeg3_t *file) +{ + double percent = 0; + if(file->last_type_read == 1) + { + percent = mpeg3demux_tell_percentage(file->atrack[file->last_stream_read]->demuxer); + } + + if(file->last_type_read == 2) + { + percent = mpeg3demux_tell_percentage(file->vtrack[file->last_stream_read]->demuxer); + } + return percent; +} + +double mpeg3_get_time(mpeg3_t *file) +{ + double atime = 0, vtime = 0; + + if(file->is_transport_stream || file->is_program_stream) + { +/* Timecode only available in transport stream */ + if(file->last_type_read == 1) + { + atime = mpeg3demux_get_time(file->atrack[file->last_stream_read]->demuxer); + } + else + if(file->last_type_read == 2) + { + vtime = mpeg3demux_get_time(file->vtrack[file->last_stream_read]->demuxer); + } + } + else + { +/* Use percentage and total time */ + if(file->has_audio) + { + atime = mpeg3demux_tell_percentage(file->atrack[0]->demuxer) * + mpeg3_audio_samples(file, 0) / mpeg3_sample_rate(file, 0); + } + + if(file->has_video) + { + vtime = mpeg3demux_tell_percentage(file->vtrack[0]->demuxer) * + mpeg3_video_frames(file, 0) / mpeg3_frame_rate(file, 0); + } + } + + return MAX(atime, vtime); +} + +int mpeg3_end_of_audio(mpeg3_t *file, int stream) +{ + int result = 0; + result = mpeg3demux_eof(file->atrack[stream]->demuxer); + return result; +} + +int mpeg3_end_of_video(mpeg3_t *file, int stream) +{ + int result = 0; + result = mpeg3demux_eof(file->vtrack[stream]->demuxer); + return result; +} + + +int mpeg3_read_frame(mpeg3_t *file, + unsigned char **output_rows, + int in_x, + int in_y, + int in_w, + int in_h, + int out_w, + int out_h, + int color_model, + int stream) +{ + int result = -1; + + if(file->has_video) + { + result = mpeg3video_read_frame(file->vtrack[stream]->video, + file->vtrack[stream]->current_position, + output_rows, + in_x, + in_y, + in_w, + in_h, + out_w, + out_h, + color_model); + file->last_type_read = 2; + file->last_stream_read = stream; + file->vtrack[stream]->current_position++; + } + return result; +} + +int mpeg3_drop_frames(mpeg3_t *file, long frames, int stream) +{ + int result = -1; + + if(file->has_video) + { + result = mpeg3video_drop_frames(file->vtrack[stream]->video, + frames); + if(frames > 0) file->vtrack[stream]->current_position += frames; + file->last_type_read = 2; + file->last_stream_read = stream; + } + return result; +} + +int mpeg3_read_yuvframe(mpeg3_t *file, + char *y_output, + char *u_output, + char *v_output, + int in_x, + int in_y, + int in_w, + int in_h, + int stream) +{ + int result = -1; + +//printf("mpeg3_read_yuvframe 1 %d %d\n", mpeg3demux_tell(file->vtrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->vtrack[stream]->demuxer)); + if(file->has_video) + { + result = mpeg3video_read_yuvframe(file->vtrack[stream]->video, + file->vtrack[stream]->current_position, + y_output, + u_output, + v_output, + in_x, + in_y, + in_w, + in_h); + file->last_type_read = 2; + file->last_stream_read = stream; + file->vtrack[stream]->current_position++; + } +//printf("mpeg3_read_yuvframe 2 %d %d\n", mpeg3demux_tell(file->vtrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->vtrack[stream]->demuxer)); + return result; +} + + +int mpeg3_read_audio(mpeg3_t *file, + mpeg3_real_t *output_f, + short *output_i, int sampleSpacing, + int channel, + long samples, + int stream) +{ + int result = -1; + +//printf("mpeg3_read_audio 1 %d %d\n", mpeg3demux_tell(file->atrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->atrack[stream]->demuxer)); + if(file->has_audio) + { + result = mpeg3audio_decode_audio(file->atrack[stream]->audio, + output_f, + output_i, sampleSpacing, + channel, + file->atrack[stream]->current_position, + samples); + file->last_type_read = 1; + file->last_stream_read = stream; + file->atrack[stream]->current_position += samples; + } +//printf("mpeg3_read_audio 2 %d %d\n", mpeg3demux_tell(file->atrack[stream]->demuxer), mpeg3demuxer_total_bytes(file->atrack[stream]->demuxer)); + + return result; +} + +int mpeg3_reread_audio(mpeg3_t *file, + mpeg3_real_t *output_f, + short *output_i, int sampleSpacing, + int channel, + long samples, + int stream) +{ + if(file->has_audio) + { + mpeg3_set_sample(file, + file->atrack[stream]->current_position - samples, + stream); + file->last_type_read = 1; + file->last_stream_read = stream; + return mpeg3_read_audio(file, + output_f, + output_i, sampleSpacing, + channel, + samples, + stream); + } + return -1; +} + +int mpeg3_read_audio_chunk(mpeg3_t *file, + unsigned char *output, + long *size, + long max_size, + int stream) +{ + int result = 0; + if(file->has_audio) + { + result = mpeg3audio_read_raw(file->atrack[stream]->audio, output, size, max_size); + file->last_type_read = 1; + file->last_stream_read = stream; + } + return result; +} + +int mpeg3_read_video_chunk(mpeg3_t *file, + unsigned char *output, + long *size, + long max_size, + int stream) +{ + int result = 0; + if(file->has_video) + { + result = mpeg3video_read_raw(file->vtrack[stream]->video, output, size, max_size); + file->last_type_read = 2; + file->last_stream_read = stream; + } + return result; +} -- cgit v0.9.0.2