mirror of
				https://github.com/ioacademy-jikim/multimedia
				synced 2025-11-04 03:27:11 +00:00 
			
		
		
		
	멀티미디어 예제
This commit is contained in:
		
						commit
						a87c18f77d
					
				
							
								
								
									
										17
									
								
								multimedia/01_day/test-audio/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								multimedia/01_day/test-audio/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := liblog libutils  libmedia
 | 
			
		||||
LOCAL_SRC_FILES :=  my_audio_play.cpp
 | 
			
		||||
LOCAL_MODULE := my_audio_play
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := liblog libutils  libmedia
 | 
			
		||||
LOCAL_SRC_FILES :=  my_audio_record.cpp
 | 
			
		||||
LOCAL_MODULE := my_audio_record
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								multimedia/01_day/test-audio/a.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								multimedia/01_day/test-audio/a.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										98
									
								
								multimedia/01_day/test-audio/my_audio_play.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								multimedia/01_day/test-audio/my_audio_play.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,98 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <media/AudioTrack.h>
 | 
			
		||||
#include <media/IAudioTrack.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
#define ID_RIFF 0x46464952
 | 
			
		||||
#define ID_WAVE 0x45564157
 | 
			
		||||
#define ID_FMT  0x20746d66
 | 
			
		||||
#define ID_DATA 0x61746164
 | 
			
		||||
 | 
			
		||||
struct riff_wave_header {
 | 
			
		||||
	uint32_t riff_id;
 | 
			
		||||
	uint32_t riff_sz;
 | 
			
		||||
	uint32_t wave_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct chunk_header {
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
	uint32_t sz;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct chunk_fmt {
 | 
			
		||||
	uint16_t audio_format;
 | 
			
		||||
	uint16_t num_channels;
 | 
			
		||||
	uint32_t sample_rate;
 | 
			
		||||
	uint32_t byte_rate;
 | 
			
		||||
	uint16_t block_align;
 | 
			
		||||
	uint16_t bits_per_sample;
 | 
			
		||||
};
 | 
			
		||||
// ./myapp a.wav
 | 
			
		||||
//         argv[1]
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	FILE *file;
 | 
			
		||||
	struct riff_wave_header riff_wave_header;
 | 
			
		||||
	struct chunk_header chunk_header;
 | 
			
		||||
	struct chunk_fmt chunk_fmt;
 | 
			
		||||
	char *filename;
 | 
			
		||||
	int more_chunks = 1;
 | 
			
		||||
	char buff[4096];
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	filename = argv[1];
 | 
			
		||||
	file = fopen(filename, "rb");
 | 
			
		||||
 | 
			
		||||
	fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
 | 
			
		||||
	if ((riff_wave_header.riff_id != ID_RIFF) ||
 | 
			
		||||
			(riff_wave_header.wave_id != ID_WAVE)) {
 | 
			
		||||
		fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
 | 
			
		||||
		fclose(file);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		fread(&chunk_header, sizeof(chunk_header), 1, file);
 | 
			
		||||
 | 
			
		||||
		switch (chunk_header.id) {
 | 
			
		||||
			case ID_FMT:
 | 
			
		||||
				fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
 | 
			
		||||
				/* If the format header is larger, skip the rest */
 | 
			
		||||
				if (chunk_header.sz > sizeof(chunk_fmt))
 | 
			
		||||
					fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
 | 
			
		||||
				break;
 | 
			
		||||
			case ID_DATA:
 | 
			
		||||
				/* Stop looking for chunks */
 | 
			
		||||
				more_chunks = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				/* Unknown chunk, skip bytes */
 | 
			
		||||
				fseek(file, chunk_header.sz, SEEK_CUR);
 | 
			
		||||
		}
 | 
			
		||||
	} while (more_chunks);
 | 
			
		||||
 | 
			
		||||
	sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_MUSIC,// stream type
 | 
			
		||||
			44100,
 | 
			
		||||
			AUDIO_FORMAT_PCM_16_BIT,// word length, PCM
 | 
			
		||||
			AUDIO_CHANNEL_OUT_STEREO,
 | 
			
		||||
			0);
 | 
			
		||||
 | 
			
		||||
	status_t status = track->initCheck();
 | 
			
		||||
	if(status != NO_ERROR) {
 | 
			
		||||
		track.clear();
 | 
			
		||||
		printf("Failed for initCheck()\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// PlaybackThread 생성 , createTrack, 공유메모리 공유 
 | 
			
		||||
	track->start();  // Track => ActiveTrack
 | 
			
		||||
	while( ret = fread( buff, 1, sizeof buff,  file ))
 | 
			
		||||
		track->write( buff, ret );  // 음원 전송 
 | 
			
		||||
 | 
			
		||||
	fclose(file);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										156
									
								
								multimedia/01_day/test-audio/my_audio_record.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								multimedia/01_day/test-audio/my_audio_record.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,156 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <media/AudioRecord.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
#define ID_RIFF 0x46464952
 | 
			
		||||
#define ID_WAVE 0x45564157
 | 
			
		||||
#define ID_FMT  0x20746d66
 | 
			
		||||
#define ID_DATA 0x61746164
 | 
			
		||||
 | 
			
		||||
#define FORMAT_PCM 1
 | 
			
		||||
 | 
			
		||||
struct wav_header {
 | 
			
		||||
    uint32_t riff_id;
 | 
			
		||||
    uint32_t riff_sz;
 | 
			
		||||
    uint32_t riff_fmt;
 | 
			
		||||
    uint32_t fmt_id;
 | 
			
		||||
    uint32_t fmt_sz;
 | 
			
		||||
    uint16_t audio_format;
 | 
			
		||||
    uint16_t num_channels;
 | 
			
		||||
    uint32_t sample_rate;
 | 
			
		||||
    uint32_t byte_rate;
 | 
			
		||||
    uint16_t block_align;
 | 
			
		||||
    uint16_t bits_per_sample;
 | 
			
		||||
    uint32_t data_id;
 | 
			
		||||
    uint32_t data_sz;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int capturing = 1;
 | 
			
		||||
 | 
			
		||||
unsigned int capture_sample(FILE *file, 
 | 
			
		||||
                            unsigned int channels, 
 | 
			
		||||
							unsigned int rate,
 | 
			
		||||
                            unsigned int period_size,
 | 
			
		||||
                            unsigned int period_count);
 | 
			
		||||
 | 
			
		||||
void sigint_handler(int sig)
 | 
			
		||||
{
 | 
			
		||||
	printf("sigint_handler(%d)\n", sig );
 | 
			
		||||
    capturing = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    FILE *file;
 | 
			
		||||
    struct wav_header header;
 | 
			
		||||
    unsigned int channels = 2;
 | 
			
		||||
    unsigned int rate = 44100;
 | 
			
		||||
    unsigned int bits = 16;
 | 
			
		||||
    unsigned int frames;
 | 
			
		||||
    unsigned int period_size = 1024;
 | 
			
		||||
    unsigned int period_count = 4;
 | 
			
		||||
 | 
			
		||||
	printf("argc=%d\n", argc );
 | 
			
		||||
    file = fopen(argv[1], "wb");
 | 
			
		||||
    if (!file) {
 | 
			
		||||
        fprintf(stderr, "Unable to create file '%s'\n", argv[1]);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    header.riff_id = ID_RIFF;
 | 
			
		||||
    header.riff_sz = 0;
 | 
			
		||||
    header.riff_fmt = ID_WAVE;
 | 
			
		||||
    header.fmt_id = ID_FMT;
 | 
			
		||||
    header.fmt_sz = 16;
 | 
			
		||||
    header.audio_format = FORMAT_PCM;
 | 
			
		||||
    header.num_channels = channels;
 | 
			
		||||
    header.sample_rate = rate;
 | 
			
		||||
 | 
			
		||||
    header.bits_per_sample = 16;
 | 
			
		||||
    header.byte_rate = (header.bits_per_sample / 8) * channels * rate;
 | 
			
		||||
    header.block_align = channels * (header.bits_per_sample / 8);
 | 
			
		||||
    header.data_id = ID_DATA;
 | 
			
		||||
 | 
			
		||||
    fseek(file, sizeof(struct wav_header), SEEK_SET);
 | 
			
		||||
 | 
			
		||||
    signal(SIGINT, sigint_handler);
 | 
			
		||||
    frames = capture_sample(file, 
 | 
			
		||||
			                header.num_channels,
 | 
			
		||||
                            header.sample_rate, 
 | 
			
		||||
                            period_size, 
 | 
			
		||||
							period_count);
 | 
			
		||||
    printf("Captured %d frames\n", frames);
 | 
			
		||||
 | 
			
		||||
    header.data_sz = frames * header.block_align;
 | 
			
		||||
    header.riff_sz = header.data_sz + sizeof(header) - 8;
 | 
			
		||||
    fseek(file, 0, SEEK_SET);
 | 
			
		||||
    fwrite(&header, sizeof(struct wav_header), 1, file);
 | 
			
		||||
 | 
			
		||||
    fclose(file);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int capture_sample(FILE *file, 
 | 
			
		||||
                            unsigned int channels, 
 | 
			
		||||
							unsigned int rate,
 | 
			
		||||
                            unsigned int period_size,
 | 
			
		||||
                            unsigned int period_count)
 | 
			
		||||
{
 | 
			
		||||
	char *buffer;
 | 
			
		||||
	unsigned int size;
 | 
			
		||||
	unsigned int bytes_read=0;
 | 
			
		||||
	int kMaxBufferSize = 2048;
 | 
			
		||||
	size_t minFrameCount;
 | 
			
		||||
	status_t status = AudioRecord::getMinFrameCount(&minFrameCount,
 | 
			
		||||
			rate,
 | 
			
		||||
			AUDIO_FORMAT_PCM_16_BIT,
 | 
			
		||||
			audio_channel_in_mask_from_count(channels));
 | 
			
		||||
	if (status == OK) {
 | 
			
		||||
		uint32_t frameCount = kMaxBufferSize / sizeof(int16_t) / channels;
 | 
			
		||||
 | 
			
		||||
		size_t bufCount = 2;
 | 
			
		||||
		while ((bufCount * frameCount) < minFrameCount) {
 | 
			
		||||
			bufCount++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sp<AudioRecord> record = new AudioRecord(
 | 
			
		||||
				AUDIO_SOURCE_DEFAULT, rate, AUDIO_FORMAT_PCM_16_BIT,
 | 
			
		||||
				audio_channel_in_mask_from_count(channels),
 | 
			
		||||
				(size_t) (bufCount * frameCount)	
 | 
			
		||||
				);
 | 
			
		||||
		status = record->initCheck();
 | 
			
		||||
		if(status != NO_ERROR) {
 | 
			
		||||
			record.clear();
 | 
			
		||||
			printf("Failed for initCheck()");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate,
 | 
			
		||||
				16);
 | 
			
		||||
 | 
			
		||||
		size = period_count * period_size * channels * 2; 
 | 
			
		||||
		buffer = (char*)malloc(size); 
 | 
			
		||||
 | 
			
		||||
		record->start();
 | 
			
		||||
 | 
			
		||||
		while (capturing) {
 | 
			
		||||
			size = record->read( buffer, size);
 | 
			
		||||
			if (fwrite(buffer, 1, size, file) != size) {
 | 
			
		||||
				fprintf(stderr,"Error capturing sample\n");
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			bytes_read += size;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		free(buffer);
 | 
			
		||||
	}
 | 
			
		||||
	return bytes_read/4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								multimedia/01_day/test-ndk/jni/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								multimedia/01_day/test-ndk/jni/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_CFLAGS += -fPIE
 | 
			
		||||
LOCAL_LDFLAGS += -fPIE -pie
 | 
			
		||||
LOCAL_MODULE    := myapp
 | 
			
		||||
LOCAL_SRC_FILES := myapp.c
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
							
								
								
									
										8
									
								
								multimedia/01_day/test-ndk/jni/myapp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								multimedia/01_day/test-ndk/jni/myapp.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	printf("Hello Android\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								multimedia/01_day/test-pdk/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								multimedia/01_day/test-pdk/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE    := myapp
 | 
			
		||||
LOCAL_SRC_FILES := myapp.c
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
							
								
								
									
										8
									
								
								multimedia/01_day/test-pdk/myapp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								multimedia/01_day/test-pdk/myapp.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	printf("Hello Android\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								multimedia/02_day/b.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								multimedia/02_day/b.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										20
									
								
								multimedia/02_day/test-HAL/atoi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								multimedia/02_day/test-HAL/atoi.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
#include "main.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int my_atoi(char *buff)
 | 
			
		||||
{
 | 
			
		||||
	int i, sum=0;
 | 
			
		||||
	for(i=0; buff[i]; i++ )
 | 
			
		||||
		sum = sum*10 + buff[i] - '0';
 | 
			
		||||
 | 
			
		||||
	return sum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int my_add(int a, int b )
 | 
			
		||||
{
 | 
			
		||||
	return a+b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct _HMI HMI = { my_atoi, my_add, 10 };
 | 
			
		||||
							
								
								
									
										26
									
								
								multimedia/02_day/test-HAL/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								multimedia/02_day/test-HAL/main.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int *global;
 | 
			
		||||
	int (*func)(char*);
 | 
			
		||||
	int (*add)(int,int);
 | 
			
		||||
	int data;
 | 
			
		||||
	void *handle = dlopen("libatoi.so", RTLD_LAZY);
 | 
			
		||||
 | 
			
		||||
	func = dlsym( handle, "my_atoi" );
 | 
			
		||||
	data = func("123");
 | 
			
		||||
	printf("data=%d\n", data );
 | 
			
		||||
 | 
			
		||||
	add  = dlsym( handle, "my_add" );
 | 
			
		||||
	data = add(1,2);
 | 
			
		||||
	printf("data=%d\n", data );
 | 
			
		||||
 | 
			
		||||
	*global  = dlsym( handle, "global" );
 | 
			
		||||
	data = add(1,2);
 | 
			
		||||
	printf("data=%d\n", data );
 | 
			
		||||
	dlclose(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								multimedia/02_day/test-HAL/main.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								multimedia/02_day/test-HAL/main.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
 | 
			
		||||
int my_atoi(char *buff);
 | 
			
		||||
int my_add(int a, int b);
 | 
			
		||||
 | 
			
		||||
struct _HMI
 | 
			
		||||
{
 | 
			
		||||
	int (*atoi)(char *buff);
 | 
			
		||||
	int (*add)(int , int );
 | 
			
		||||
	int global;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										14
									
								
								multimedia/02_day/test-ashmem1/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								multimedia/02_day/test-ashmem1/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SRC_FILES:= server.cpp
 | 
			
		||||
LOCAL_MODULE := my_server
 | 
			
		||||
LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SRC_FILES:= client.cpp
 | 
			
		||||
LOCAL_MODULE := my_client
 | 
			
		||||
LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
							
								
								
									
										17
									
								
								multimedia/02_day/test-ashmem1/client.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								multimedia/02_day/test-ashmem1/client.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
#include <binder/IServiceManager.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
#include <binder/MemoryHeapBase.h>
 | 
			
		||||
#include <binder/IPCThreadState.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	sp<IServiceManager> sm = defaultServiceManager();
 | 
			
		||||
	sp<IBinder> binder = sm->getService( String16("my.ashmem1") );
 | 
			
		||||
	sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(binder); 
 | 
			
		||||
	char *p = (char*)heap->getBase();
 | 
			
		||||
	printf("[%s]\n", p );
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								multimedia/02_day/test-ashmem1/server.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								multimedia/02_day/test-ashmem1/server.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
#include <binder/IServiceManager.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
#include <binder/MemoryHeapBase.h>
 | 
			
		||||
#include <binder/IPCThreadState.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	sp<IServiceManager> sm = defaultServiceManager();
 | 
			
		||||
	sp<MemoryHeapBase>  heap = new MemoryHeapBase(4096);
 | 
			
		||||
	sm->addService( String16("my.ashmem1") , heap );
 | 
			
		||||
 | 
			
		||||
	char *p = (char*)heap->getBase();
 | 
			
		||||
	sprintf(p, "Hello Client!!\n" );
 | 
			
		||||
	IPCThreadState::self()->joinThreadPool();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								multimedia/02_day/test-ashmem2/.client.cpp.swp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								multimedia/02_day/test-ashmem2/.client.cpp.swp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										14
									
								
								multimedia/02_day/test-ashmem2/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								multimedia/02_day/test-ashmem2/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SRC_FILES:= server.cpp
 | 
			
		||||
LOCAL_MODULE := my_server
 | 
			
		||||
LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SRC_FILES:= client.cpp
 | 
			
		||||
LOCAL_MODULE := my_client
 | 
			
		||||
LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
							
								
								
									
										21
									
								
								multimedia/02_day/test-ashmem2/client.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								multimedia/02_day/test-ashmem2/client.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
#include <binder/IServiceManager.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
#include <binder/MemoryHeapBase.h>
 | 
			
		||||
#include <binder/IPCThreadState.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	sp<IServiceManager> sm = defaultServiceManager();
 | 
			
		||||
	sp<IBinder> binder = sm->getService( String16("my.ashmem1") );
 | 
			
		||||
	sp<IMemory> memory = interface_cast<IMemory>(binder); 
 | 
			
		||||
	ssize_t offset=0;
 | 
			
		||||
	size_t size=0;
 | 
			
		||||
    sp<IMemoryHeap> heap = memory->getMemory(&offset, &size);
 | 
			
		||||
 | 
			
		||||
	char *p = (char*)heap->getBase();
 | 
			
		||||
	printf("[%s]\n", p+offset );
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								multimedia/02_day/test-ashmem2/server.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								multimedia/02_day/test-ashmem2/server.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
#include <binder/IServiceManager.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
#include <binder/MemoryHeapBase.h>
 | 
			
		||||
#include <binder/MemoryBase.h>
 | 
			
		||||
#include <binder/IPCThreadState.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	sp<IServiceManager> sm = defaultServiceManager();
 | 
			
		||||
	sp<MemoryHeapBase>  heap = new MemoryHeapBase(4096);
 | 
			
		||||
	sm->addService( String16("my.ashmem1") , new MemoryBase(heap, 100, 100) );
 | 
			
		||||
 | 
			
		||||
	char *p = (char*)heap->getBase();
 | 
			
		||||
	sprintf(p+100, "Hello Client!!\n" );
 | 
			
		||||
	IPCThreadState::self()->joinThreadPool();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								multimedia/02_day/test-mixer/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								multimedia/02_day/test-mixer/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES:= \
 | 
			
		||||
	test-mixer.cpp \
 | 
			
		||||
	AudioMixer.cpp.arm \
 | 
			
		||||
 | 
			
		||||
LOCAL_C_INCLUDES := \
 | 
			
		||||
	bionic \
 | 
			
		||||
	bionic/libstdc++/include \
 | 
			
		||||
	external/stlport/stlport \
 | 
			
		||||
	$(call include-path-for, audio-effects) \
 | 
			
		||||
	$(call include-path-for, audio-utils) \
 | 
			
		||||
	frameworks/av/services/audioflinger
 | 
			
		||||
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := \
 | 
			
		||||
	libsndfile
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := \
 | 
			
		||||
	libstlport \
 | 
			
		||||
	libeffects \
 | 
			
		||||
	libnbaio \
 | 
			
		||||
	libcommon_time_client \
 | 
			
		||||
	libaudioresampler \
 | 
			
		||||
	libaudioutils \
 | 
			
		||||
	libdl \
 | 
			
		||||
	libcutils \
 | 
			
		||||
	libutils \
 | 
			
		||||
	liblog
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE:= test-mixer
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
							
								
								
									
										2239
									
								
								multimedia/02_day/test-mixer/AudioMixer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2239
									
								
								multimedia/02_day/test-mixer/AudioMixer.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										470
									
								
								multimedia/02_day/test-mixer/AudioMixer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										470
									
								
								multimedia/02_day/test-mixer/AudioMixer.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,470 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2007, The Android Open Source Project
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef ANDROID_AUDIO_MIXER_H
 | 
			
		||||
#define ANDROID_AUDIO_MIXER_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <utils/threads.h>
 | 
			
		||||
 | 
			
		||||
#include <media/AudioBufferProvider.h>
 | 
			
		||||
#include "AudioResampler.h"
 | 
			
		||||
 | 
			
		||||
#include <hardware/audio_effect.h>
 | 
			
		||||
#include <system/audio.h>
 | 
			
		||||
#include <media/nbaio/NBLog.h>
 | 
			
		||||
 | 
			
		||||
// FIXME This is actually unity gain, which might not be max in future, expressed in U.12
 | 
			
		||||
#define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT
 | 
			
		||||
 | 
			
		||||
namespace android {
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class AudioMixer
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
                            AudioMixer(size_t frameCount, uint32_t sampleRate,
 | 
			
		||||
                                       uint32_t maxNumTracks = MAX_NUM_TRACKS);
 | 
			
		||||
 | 
			
		||||
    /*virtual*/             ~AudioMixer();  // non-virtual saves a v-table, restore if sub-classed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // This mixer has a hard-coded upper limit of 32 active track inputs.
 | 
			
		||||
    // Adding support for > 32 tracks would require more than simply changing this value.
 | 
			
		||||
    static const uint32_t MAX_NUM_TRACKS = 32;
 | 
			
		||||
    // maximum number of channels supported by the mixer
 | 
			
		||||
 | 
			
		||||
    // This mixer has a hard-coded upper limit of 8 channels for output.
 | 
			
		||||
    static const uint32_t MAX_NUM_CHANNELS = 8;
 | 
			
		||||
    static const uint32_t MAX_NUM_VOLUMES = 2; // stereo volume only
 | 
			
		||||
    // maximum number of channels supported for the content
 | 
			
		||||
    static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = AUDIO_CHANNEL_COUNT_MAX;
 | 
			
		||||
 | 
			
		||||
    static const uint16_t UNITY_GAIN_INT = 0x1000;
 | 
			
		||||
    static const float    UNITY_GAIN_FLOAT = 1.0f;
 | 
			
		||||
 | 
			
		||||
    enum { // names
 | 
			
		||||
 | 
			
		||||
        // track names (MAX_NUM_TRACKS units)
 | 
			
		||||
        TRACK0          = 0x1000,
 | 
			
		||||
 | 
			
		||||
        // 0x2000 is unused
 | 
			
		||||
 | 
			
		||||
        // setParameter targets
 | 
			
		||||
        TRACK           = 0x3000,
 | 
			
		||||
        RESAMPLE        = 0x3001,
 | 
			
		||||
        RAMP_VOLUME     = 0x3002, // ramp to new volume
 | 
			
		||||
        VOLUME          = 0x3003, // don't ramp
 | 
			
		||||
 | 
			
		||||
        // set Parameter names
 | 
			
		||||
        // for target TRACK
 | 
			
		||||
        CHANNEL_MASK    = 0x4000,
 | 
			
		||||
        FORMAT          = 0x4001,
 | 
			
		||||
        MAIN_BUFFER     = 0x4002,
 | 
			
		||||
        AUX_BUFFER      = 0x4003,
 | 
			
		||||
        DOWNMIX_TYPE    = 0X4004,
 | 
			
		||||
        MIXER_FORMAT    = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
 | 
			
		||||
        MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
 | 
			
		||||
        // for target RESAMPLE
 | 
			
		||||
        SAMPLE_RATE     = 0x4100, // Configure sample rate conversion on this track name;
 | 
			
		||||
                                  // parameter 'value' is the new sample rate in Hz.
 | 
			
		||||
                                  // Only creates a sample rate converter the first time that
 | 
			
		||||
                                  // the track sample rate is different from the mix sample rate.
 | 
			
		||||
                                  // If the new sample rate is the same as the mix sample rate,
 | 
			
		||||
                                  // and a sample rate converter already exists,
 | 
			
		||||
                                  // then the sample rate converter remains present but is a no-op.
 | 
			
		||||
        RESET           = 0x4101, // Reset sample rate converter without changing sample rate.
 | 
			
		||||
                                  // This clears out the resampler's input buffer.
 | 
			
		||||
        REMOVE          = 0x4102, // Remove the sample rate converter on this track name;
 | 
			
		||||
                                  // the track is restored to the mix sample rate.
 | 
			
		||||
        // for target RAMP_VOLUME and VOLUME (8 channels max)
 | 
			
		||||
        // FIXME use float for these 3 to improve the dynamic range
 | 
			
		||||
        VOLUME0         = 0x4200,
 | 
			
		||||
        VOLUME1         = 0x4201,
 | 
			
		||||
        AUXLEVEL        = 0x4210,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // For all APIs with "name": TRACK0 <= name < TRACK0 + MAX_NUM_TRACKS
 | 
			
		||||
 | 
			
		||||
    // Allocate a track name.  Returns new track name if successful, -1 on failure.
 | 
			
		||||
    // The failure could be because of an invalid channelMask or format, or that
 | 
			
		||||
    // the track capacity of the mixer is exceeded.
 | 
			
		||||
    int         getTrackName(audio_channel_mask_t channelMask,
 | 
			
		||||
                             audio_format_t format, int sessionId);
 | 
			
		||||
 | 
			
		||||
    // Free an allocated track by name
 | 
			
		||||
    void        deleteTrackName(int name);
 | 
			
		||||
 | 
			
		||||
    // Enable or disable an allocated track by name
 | 
			
		||||
    void        enable(int name);
 | 
			
		||||
    void        disable(int name);
 | 
			
		||||
 | 
			
		||||
    void        setParameter(int name, int target, int param, void *value);
 | 
			
		||||
 | 
			
		||||
    void        setBufferProvider(int name, AudioBufferProvider* bufferProvider);
 | 
			
		||||
    void        process(int64_t pts);
 | 
			
		||||
 | 
			
		||||
    uint32_t    trackNames() const { return mTrackNames; }
 | 
			
		||||
 | 
			
		||||
    size_t      getUnreleasedFrames(int name) const;
 | 
			
		||||
 | 
			
		||||
    static inline bool isValidPcmTrackFormat(audio_format_t format) {
 | 
			
		||||
        return format == AUDIO_FORMAT_PCM_16_BIT ||
 | 
			
		||||
                format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
 | 
			
		||||
                format == AUDIO_FORMAT_PCM_32_BIT ||
 | 
			
		||||
                format == AUDIO_FORMAT_PCM_FLOAT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    enum {
 | 
			
		||||
        // FIXME this representation permits up to 8 channels
 | 
			
		||||
        NEEDS_CHANNEL_COUNT__MASK   = 0x00000007,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum {
 | 
			
		||||
        NEEDS_CHANNEL_1             = 0x00000000,   // mono
 | 
			
		||||
        NEEDS_CHANNEL_2             = 0x00000001,   // stereo
 | 
			
		||||
 | 
			
		||||
        // sample format is not explicitly specified, and is assumed to be AUDIO_FORMAT_PCM_16_BIT
 | 
			
		||||
 | 
			
		||||
        NEEDS_MUTE                  = 0x00000100,
 | 
			
		||||
        NEEDS_RESAMPLE              = 0x00001000,
 | 
			
		||||
        NEEDS_AUX                   = 0x00010000,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct state_t;
 | 
			
		||||
    struct track_t;
 | 
			
		||||
    class CopyBufferProvider;
 | 
			
		||||
 | 
			
		||||
    typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp,
 | 
			
		||||
                           int32_t* aux);
 | 
			
		||||
    static const int BLOCKSIZE = 16; // 4 cache lines
 | 
			
		||||
 | 
			
		||||
    struct track_t {
 | 
			
		||||
        uint32_t    needs;
 | 
			
		||||
 | 
			
		||||
        // TODO: Eventually remove legacy integer volume settings
 | 
			
		||||
        union {
 | 
			
		||||
        int16_t     volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero)
 | 
			
		||||
        int32_t     volumeRL;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        int32_t     prevVolume[MAX_NUM_VOLUMES];
 | 
			
		||||
 | 
			
		||||
        // 16-byte boundary
 | 
			
		||||
 | 
			
		||||
        int32_t     volumeInc[MAX_NUM_VOLUMES];
 | 
			
		||||
        int32_t     auxInc;
 | 
			
		||||
        int32_t     prevAuxLevel;
 | 
			
		||||
 | 
			
		||||
        // 16-byte boundary
 | 
			
		||||
 | 
			
		||||
        int16_t     auxLevel;       // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance
 | 
			
		||||
        uint16_t    frameCount;
 | 
			
		||||
 | 
			
		||||
        uint8_t     channelCount;   // 1 or 2, redundant with (needs & NEEDS_CHANNEL_COUNT__MASK)
 | 
			
		||||
        uint8_t     unused_padding; // formerly format, was always 16
 | 
			
		||||
        uint16_t    enabled;        // actually bool
 | 
			
		||||
        audio_channel_mask_t channelMask;
 | 
			
		||||
 | 
			
		||||
        // actual buffer provider used by the track hooks, see DownmixerBufferProvider below
 | 
			
		||||
        //  for how the Track buffer provider is wrapped by another one when dowmixing is required
 | 
			
		||||
        AudioBufferProvider*                bufferProvider;
 | 
			
		||||
 | 
			
		||||
        // 16-byte boundary
 | 
			
		||||
 | 
			
		||||
        mutable AudioBufferProvider::Buffer buffer; // 8 bytes
 | 
			
		||||
 | 
			
		||||
        hook_t      hook;
 | 
			
		||||
        const void* in;             // current location in buffer
 | 
			
		||||
 | 
			
		||||
        // 16-byte boundary
 | 
			
		||||
 | 
			
		||||
        AudioResampler*     resampler;
 | 
			
		||||
        uint32_t            sampleRate;
 | 
			
		||||
        int32_t*           mainBuffer;
 | 
			
		||||
        int32_t*           auxBuffer;
 | 
			
		||||
 | 
			
		||||
        // 16-byte boundary
 | 
			
		||||
        AudioBufferProvider*     mInputBufferProvider;    // externally provided buffer provider.
 | 
			
		||||
        CopyBufferProvider*      mReformatBufferProvider; // provider wrapper for reformatting.
 | 
			
		||||
        CopyBufferProvider*      downmixerBufferProvider; // wrapper for channel conversion.
 | 
			
		||||
 | 
			
		||||
        int32_t     sessionId;
 | 
			
		||||
 | 
			
		||||
        // 16-byte boundary
 | 
			
		||||
        audio_format_t mMixerFormat;     // output mix format: AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
 | 
			
		||||
        audio_format_t mFormat;          // input track format
 | 
			
		||||
        audio_format_t mMixerInFormat;   // mix internal format AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
 | 
			
		||||
                                         // each track must be converted to this format.
 | 
			
		||||
 | 
			
		||||
        float          mVolume[MAX_NUM_VOLUMES];     // floating point set volume
 | 
			
		||||
        float          mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume
 | 
			
		||||
        float          mVolumeInc[MAX_NUM_VOLUMES];  // floating point volume increment
 | 
			
		||||
 | 
			
		||||
        float          mAuxLevel;                     // floating point set aux level
 | 
			
		||||
        float          mPrevAuxLevel;                 // floating point prev aux level
 | 
			
		||||
        float          mAuxInc;                       // floating point aux increment
 | 
			
		||||
 | 
			
		||||
        // 16-byte boundary
 | 
			
		||||
        audio_channel_mask_t mMixerChannelMask;
 | 
			
		||||
        uint32_t             mMixerChannelCount;
 | 
			
		||||
 | 
			
		||||
        bool        needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; }
 | 
			
		||||
        bool        setResampler(uint32_t trackSampleRate, uint32_t devSampleRate);
 | 
			
		||||
        bool        doesResample() const { return resampler != NULL; }
 | 
			
		||||
        void        resetResampler() { if (resampler != NULL) resampler->reset(); }
 | 
			
		||||
        void        adjustVolumeRamp(bool aux, bool useFloat = false);
 | 
			
		||||
        size_t      getUnreleasedFrames() const { return resampler != NULL ?
 | 
			
		||||
                                                    resampler->getUnreleasedFrames() : 0; };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    typedef void (*process_hook_t)(state_t* state, int64_t pts);
 | 
			
		||||
 | 
			
		||||
    // pad to 32-bytes to fill cache line
 | 
			
		||||
    struct state_t {
 | 
			
		||||
        uint32_t        enabledTracks;
 | 
			
		||||
        uint32_t        needsChanged;
 | 
			
		||||
        size_t          frameCount;
 | 
			
		||||
        process_hook_t  hook;   // one of process__*, never NULL
 | 
			
		||||
        int32_t         *outputTemp;
 | 
			
		||||
        int32_t         *resampleTemp;
 | 
			
		||||
        NBLog::Writer*  mLog;
 | 
			
		||||
        int32_t         reserved[1];
 | 
			
		||||
        // FIXME allocate dynamically to save some memory when maxNumTracks < MAX_NUM_TRACKS
 | 
			
		||||
        track_t         tracks[MAX_NUM_TRACKS] __attribute__((aligned(32)));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Base AudioBufferProvider class used for DownMixerBufferProvider, RemixBufferProvider,
 | 
			
		||||
    // and ReformatBufferProvider.
 | 
			
		||||
    // It handles a private buffer for use in converting format or channel masks from the
 | 
			
		||||
    // input data to a form acceptable by the mixer.
 | 
			
		||||
    // TODO: Make a ResamplerBufferProvider when integers are entirely removed from the
 | 
			
		||||
    // processing pipeline.
 | 
			
		||||
    class CopyBufferProvider : public AudioBufferProvider {
 | 
			
		||||
    public:
 | 
			
		||||
        // Use a private buffer of bufferFrameCount frames (each frame is outputFrameSize bytes).
 | 
			
		||||
        // If bufferFrameCount is 0, no private buffer is created and in-place modification of
 | 
			
		||||
        // the upstream buffer provider's buffers is performed by copyFrames().
 | 
			
		||||
        CopyBufferProvider(size_t inputFrameSize, size_t outputFrameSize,
 | 
			
		||||
                size_t bufferFrameCount);
 | 
			
		||||
        virtual ~CopyBufferProvider();
 | 
			
		||||
 | 
			
		||||
        // Overrides AudioBufferProvider methods
 | 
			
		||||
        virtual status_t getNextBuffer(Buffer* buffer, int64_t pts);
 | 
			
		||||
        virtual void releaseBuffer(Buffer* buffer);
 | 
			
		||||
 | 
			
		||||
        // Other public methods
 | 
			
		||||
 | 
			
		||||
        // call this to release the buffer to the upstream provider.
 | 
			
		||||
        // treat it as an audio discontinuity for future samples.
 | 
			
		||||
        virtual void reset();
 | 
			
		||||
 | 
			
		||||
        // this function should be supplied by the derived class.  It converts
 | 
			
		||||
        // #frames in the *src pointer to the *dst pointer.  It is public because
 | 
			
		||||
        // some providers will allow this to work on arbitrary buffers outside
 | 
			
		||||
        // of the internal buffers.
 | 
			
		||||
        virtual void copyFrames(void *dst, const void *src, size_t frames) = 0;
 | 
			
		||||
 | 
			
		||||
        // set the upstream buffer provider. Consider calling "reset" before this function.
 | 
			
		||||
        void setBufferProvider(AudioBufferProvider *p) {
 | 
			
		||||
            mTrackBufferProvider = p;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        AudioBufferProvider* mTrackBufferProvider;
 | 
			
		||||
        const size_t         mInputFrameSize;
 | 
			
		||||
        const size_t         mOutputFrameSize;
 | 
			
		||||
    private:
 | 
			
		||||
        AudioBufferProvider::Buffer mBuffer;
 | 
			
		||||
        const size_t         mLocalBufferFrameCount;
 | 
			
		||||
        void*                mLocalBufferData;
 | 
			
		||||
        size_t               mConsumed;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // DownmixerBufferProvider wraps a track AudioBufferProvider to provide
 | 
			
		||||
    // position dependent downmixing by an Audio Effect.
 | 
			
		||||
    class DownmixerBufferProvider : public CopyBufferProvider {
 | 
			
		||||
    public:
 | 
			
		||||
        DownmixerBufferProvider(audio_channel_mask_t inputChannelMask,
 | 
			
		||||
                audio_channel_mask_t outputChannelMask, audio_format_t format,
 | 
			
		||||
                uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount);
 | 
			
		||||
        virtual ~DownmixerBufferProvider();
 | 
			
		||||
        virtual void copyFrames(void *dst, const void *src, size_t frames);
 | 
			
		||||
        bool isValid() const { return mDownmixHandle != NULL; }
 | 
			
		||||
 | 
			
		||||
        static status_t init();
 | 
			
		||||
        static bool isMultichannelCapable() { return sIsMultichannelCapable; }
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        effect_handle_t    mDownmixHandle;
 | 
			
		||||
        effect_config_t    mDownmixConfig;
 | 
			
		||||
 | 
			
		||||
        // effect descriptor for the downmixer used by the mixer
 | 
			
		||||
        static effect_descriptor_t sDwnmFxDesc;
 | 
			
		||||
        // indicates whether a downmix effect has been found and is usable by this mixer
 | 
			
		||||
        static bool                sIsMultichannelCapable;
 | 
			
		||||
        // FIXME: should we allow effects outside of the framework?
 | 
			
		||||
        // We need to here. A special ioId that must be <= -2 so it does not map to a session.
 | 
			
		||||
        static const int32_t SESSION_ID_INVALID_AND_IGNORED = -2;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // RemixBufferProvider wraps a track AudioBufferProvider to perform an
 | 
			
		||||
    // upmix or downmix to the proper channel count and mask.
 | 
			
		||||
    class RemixBufferProvider : public CopyBufferProvider {
 | 
			
		||||
    public:
 | 
			
		||||
        RemixBufferProvider(audio_channel_mask_t inputChannelMask,
 | 
			
		||||
                audio_channel_mask_t outputChannelMask, audio_format_t format,
 | 
			
		||||
                size_t bufferFrameCount);
 | 
			
		||||
        virtual void copyFrames(void *dst, const void *src, size_t frames);
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        const audio_format_t mFormat;
 | 
			
		||||
        const size_t         mSampleSize;
 | 
			
		||||
        const size_t         mInputChannels;
 | 
			
		||||
        const size_t         mOutputChannels;
 | 
			
		||||
        int8_t               mIdxAry[sizeof(uint32_t)*8]; // 32 bits => channel indices
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // ReformatBufferProvider wraps a track AudioBufferProvider to convert the input data
 | 
			
		||||
    // to an acceptable mixer input format type.
 | 
			
		||||
    class ReformatBufferProvider : public CopyBufferProvider {
 | 
			
		||||
    public:
 | 
			
		||||
        ReformatBufferProvider(int32_t channels,
 | 
			
		||||
                audio_format_t inputFormat, audio_format_t outputFormat,
 | 
			
		||||
                size_t bufferFrameCount);
 | 
			
		||||
        virtual void copyFrames(void *dst, const void *src, size_t frames);
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        const int32_t        mChannels;
 | 
			
		||||
        const audio_format_t mInputFormat;
 | 
			
		||||
        const audio_format_t mOutputFormat;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // bitmask of allocated track names, where bit 0 corresponds to TRACK0 etc.
 | 
			
		||||
    uint32_t        mTrackNames;
 | 
			
		||||
 | 
			
		||||
    // bitmask of configured track names; ~0 if maxNumTracks == MAX_NUM_TRACKS,
 | 
			
		||||
    // but will have fewer bits set if maxNumTracks < MAX_NUM_TRACKS
 | 
			
		||||
    const uint32_t  mConfiguredNames;
 | 
			
		||||
 | 
			
		||||
    const uint32_t  mSampleRate;
 | 
			
		||||
 | 
			
		||||
    NBLog::Writer   mDummyLog;
 | 
			
		||||
public:
 | 
			
		||||
    void            setLog(NBLog::Writer* log);
 | 
			
		||||
private:
 | 
			
		||||
    state_t         mState __attribute__((aligned(32)));
 | 
			
		||||
 | 
			
		||||
    // Call after changing either the enabled status of a track, or parameters of an enabled track.
 | 
			
		||||
    // OK to call more often than that, but unnecessary.
 | 
			
		||||
    void invalidateState(uint32_t mask);
 | 
			
		||||
 | 
			
		||||
    bool setChannelMasks(int name,
 | 
			
		||||
            audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask);
 | 
			
		||||
 | 
			
		||||
    // TODO: remove unused trackName/trackNum from functions below.
 | 
			
		||||
    static status_t initTrackDownmix(track_t* pTrack, int trackName);
 | 
			
		||||
    static status_t prepareTrackForDownmix(track_t* pTrack, int trackNum);
 | 
			
		||||
    static void unprepareTrackForDownmix(track_t* pTrack, int trackName);
 | 
			
		||||
    static status_t prepareTrackForReformat(track_t* pTrack, int trackNum);
 | 
			
		||||
    static void unprepareTrackForReformat(track_t* pTrack, int trackName);
 | 
			
		||||
    static void reconfigureBufferProviders(track_t* pTrack);
 | 
			
		||||
 | 
			
		||||
    static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp,
 | 
			
		||||
            int32_t* aux);
 | 
			
		||||
    static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
 | 
			
		||||
    static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp,
 | 
			
		||||
            int32_t* aux);
 | 
			
		||||
    static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp,
 | 
			
		||||
            int32_t* aux);
 | 
			
		||||
    static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
 | 
			
		||||
            int32_t* aux);
 | 
			
		||||
    static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
 | 
			
		||||
            int32_t* aux);
 | 
			
		||||
 | 
			
		||||
    static void process__validate(state_t* state, int64_t pts);
 | 
			
		||||
    static void process__nop(state_t* state, int64_t pts);
 | 
			
		||||
    static void process__genericNoResampling(state_t* state, int64_t pts);
 | 
			
		||||
    static void process__genericResampling(state_t* state, int64_t pts);
 | 
			
		||||
    static void process__OneTrack16BitsStereoNoResampling(state_t* state,
 | 
			
		||||
                                                          int64_t pts);
 | 
			
		||||
 | 
			
		||||
    static int64_t calculateOutputPTS(const track_t& t, int64_t basePTS,
 | 
			
		||||
                                      int outputFrameIndex);
 | 
			
		||||
 | 
			
		||||
    static uint64_t         sLocalTimeFreq;
 | 
			
		||||
    static pthread_once_t   sOnceControl;
 | 
			
		||||
    static void             sInitRoutine();
 | 
			
		||||
 | 
			
		||||
    /* multi-format volume mixing function (calls template functions
 | 
			
		||||
     * in AudioMixerOps.h).  The template parameters are as follows:
 | 
			
		||||
     *
 | 
			
		||||
     *   MIXTYPE     (see AudioMixerOps.h MIXTYPE_* enumeration)
 | 
			
		||||
     *   USEFLOATVOL (set to true if float volume is used)
 | 
			
		||||
     *   ADJUSTVOL   (set to true if volume ramp parameters needs adjustment afterwards)
 | 
			
		||||
     *   TO: int32_t (Q4.27) or float
 | 
			
		||||
     *   TI: int32_t (Q4.27) or int16_t (Q0.15) or float
 | 
			
		||||
     *   TA: int32_t (Q4.27)
 | 
			
		||||
     */
 | 
			
		||||
    template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL,
 | 
			
		||||
        typename TO, typename TI, typename TA>
 | 
			
		||||
    static void volumeMix(TO *out, size_t outFrames,
 | 
			
		||||
            const TI *in, TA *aux, bool ramp, AudioMixer::track_t *t);
 | 
			
		||||
 | 
			
		||||
    // multi-format process hooks
 | 
			
		||||
    template <int MIXTYPE, typename TO, typename TI, typename TA>
 | 
			
		||||
    static void process_NoResampleOneTrack(state_t* state, int64_t pts);
 | 
			
		||||
 | 
			
		||||
    // multi-format track hooks
 | 
			
		||||
    template <int MIXTYPE, typename TO, typename TI, typename TA>
 | 
			
		||||
    static void track__Resample(track_t* t, TO* out, size_t frameCount,
 | 
			
		||||
            TO* temp __unused, TA* aux);
 | 
			
		||||
    template <int MIXTYPE, typename TO, typename TI, typename TA>
 | 
			
		||||
    static void track__NoResample(track_t* t, TO* out, size_t frameCount,
 | 
			
		||||
            TO* temp __unused, TA* aux);
 | 
			
		||||
 | 
			
		||||
    static void convertMixerFormat(void *out, audio_format_t mixerOutFormat,
 | 
			
		||||
            void *in, audio_format_t mixerInFormat, size_t sampleCount);
 | 
			
		||||
 | 
			
		||||
    // hook types
 | 
			
		||||
    enum {
 | 
			
		||||
        PROCESSTYPE_NORESAMPLEONETRACK,
 | 
			
		||||
    };
 | 
			
		||||
    enum {
 | 
			
		||||
        TRACKTYPE_NOP,
 | 
			
		||||
        TRACKTYPE_RESAMPLE,
 | 
			
		||||
        TRACKTYPE_NORESAMPLE,
 | 
			
		||||
        TRACKTYPE_NORESAMPLEMONO,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // functions for determining the proper process and track hooks.
 | 
			
		||||
    static process_hook_t getProcessHook(int processType, uint32_t channelCount,
 | 
			
		||||
            audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
 | 
			
		||||
    static hook_t getTrackHook(int trackType, uint32_t channelCount,
 | 
			
		||||
            audio_format_t mixerInFormat, audio_format_t mixerOutFormat);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
}; // namespace android
 | 
			
		||||
 | 
			
		||||
#endif // ANDROID_AUDIO_MIXER_H
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								multimedia/02_day/test-mixer/c.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								multimedia/02_day/test-mixer/c.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										306
									
								
								multimedia/02_day/test-mixer/test-mixer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								multimedia/02_day/test-mixer/test-mixer.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,306 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <audio_utils/primitives.h>
 | 
			
		||||
#include <audio_utils/sndfile.h>
 | 
			
		||||
#include <media/AudioBufferProvider.h>
 | 
			
		||||
#include "AudioMixer.h"
 | 
			
		||||
#include "test_utils.h"
 | 
			
		||||
 | 
			
		||||
/* Testing is typically through creation of an output WAV file from several
 | 
			
		||||
 * source inputs, to be later analyzed by an audio program such as Audacity.
 | 
			
		||||
 *
 | 
			
		||||
 * Sine or chirp functions are typically more useful as input to the mixer
 | 
			
		||||
 * as they show up as straight lines on a spectrogram if successfully mixed.
 | 
			
		||||
 *
 | 
			
		||||
 * A sample shell script is provided: mixer_to_wave_tests.sh
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
static void usage(const char* name) {
 | 
			
		||||
    fprintf(stderr, "Usage: %s [-f] [-m] [-c channels]"
 | 
			
		||||
                    " [-s sample-rate] [-o <output-file>] [-a <aux-buffer-file>] [-P csv]"
 | 
			
		||||
                    " (<input-file> | <command>)+\n", name);
 | 
			
		||||
    fprintf(stderr, "    -f    enable floating point input track\n");
 | 
			
		||||
    fprintf(stderr, "    -m    enable floating point mixer output\n");
 | 
			
		||||
    fprintf(stderr, "    -c    number of mixer output channels\n");
 | 
			
		||||
    fprintf(stderr, "    -s    mixer sample-rate\n");
 | 
			
		||||
    fprintf(stderr, "    -o    <output-file> WAV file, pcm16 (or float if -m specified)\n");
 | 
			
		||||
    fprintf(stderr, "    -a    <aux-buffer-file>\n");
 | 
			
		||||
    fprintf(stderr, "    -P    # frames provided per call to resample() in CSV format\n");
 | 
			
		||||
    fprintf(stderr, "    <input-file> is a WAV file\n");
 | 
			
		||||
    fprintf(stderr, "    <command> can be 'sine:<channels>,<frequency>,<samplerate>'\n");
 | 
			
		||||
    fprintf(stderr, "                     'chirp:<channels>,<samplerate>'\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int writeFile(const char *filename, const void *buffer,
 | 
			
		||||
        uint32_t sampleRate, uint32_t channels, size_t frames, bool isBufferFloat) {
 | 
			
		||||
    if (filename == NULL) {
 | 
			
		||||
        return 0; // ok to pass in NULL filename
 | 
			
		||||
    }
 | 
			
		||||
    // write output to file.
 | 
			
		||||
    SF_INFO info;
 | 
			
		||||
    info.frames = 0;
 | 
			
		||||
    info.samplerate = sampleRate;
 | 
			
		||||
    info.channels = channels;
 | 
			
		||||
    info.format = SF_FORMAT_WAV | (isBufferFloat ? SF_FORMAT_FLOAT : SF_FORMAT_PCM_16);
 | 
			
		||||
    printf("saving file:%s  channels:%u  samplerate:%u  frames:%zu\n",
 | 
			
		||||
            filename, info.channels, info.samplerate, frames);
 | 
			
		||||
    SNDFILE *sf = sf_open(filename, SFM_WRITE, &info);
 | 
			
		||||
    if (sf == NULL) {
 | 
			
		||||
        perror(filename);
 | 
			
		||||
        return EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
    if (isBufferFloat) {
 | 
			
		||||
        (void) sf_writef_float(sf, (float*)buffer, frames);
 | 
			
		||||
    } else {
 | 
			
		||||
        (void) sf_writef_short(sf, (short*)buffer, frames);
 | 
			
		||||
    }
 | 
			
		||||
    sf_close(sf);
 | 
			
		||||
    return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
    const char* const progname = argv[0];
 | 
			
		||||
    bool useInputFloat = false;
 | 
			
		||||
    bool useMixerFloat = false;
 | 
			
		||||
    bool useRamp = true;
 | 
			
		||||
    uint32_t outputSampleRate = 48000;
 | 
			
		||||
    uint32_t outputChannels = 2; // stereo for now
 | 
			
		||||
    std::vector<int> Pvalues;
 | 
			
		||||
    const char* outputFilename = NULL;
 | 
			
		||||
    const char* auxFilename = NULL;
 | 
			
		||||
    std::vector<int32_t> Names;
 | 
			
		||||
    std::vector<SignalProvider> Providers;
 | 
			
		||||
 | 
			
		||||
    for (int ch; (ch = getopt(argc, argv, "fmc:s:o:a:P:")) != -1;) {
 | 
			
		||||
        switch (ch) {
 | 
			
		||||
        case 'f':
 | 
			
		||||
            useInputFloat = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'm':
 | 
			
		||||
            useMixerFloat = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'c':
 | 
			
		||||
            outputChannels = atoi(optarg);
 | 
			
		||||
            break;
 | 
			
		||||
        case 's':
 | 
			
		||||
            outputSampleRate = atoi(optarg);
 | 
			
		||||
            break;
 | 
			
		||||
        case 'o':
 | 
			
		||||
            outputFilename = optarg;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'a':
 | 
			
		||||
            auxFilename = optarg;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'P':
 | 
			
		||||
            if (parseCSV(optarg, Pvalues) < 0) {
 | 
			
		||||
                fprintf(stderr, "incorrect syntax for -P option\n");
 | 
			
		||||
                return EXIT_FAILURE;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case '?':
 | 
			
		||||
        default:
 | 
			
		||||
            usage(progname);
 | 
			
		||||
            return EXIT_FAILURE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    argc -= optind;
 | 
			
		||||
    argv += optind;
 | 
			
		||||
 | 
			
		||||
    if (argc == 0) {
 | 
			
		||||
        usage(progname);
 | 
			
		||||
        return EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
    if ((unsigned)argc > AudioMixer::MAX_NUM_TRACKS) {
 | 
			
		||||
        fprintf(stderr, "too many tracks: %d > %u", argc, AudioMixer::MAX_NUM_TRACKS);
 | 
			
		||||
        return EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t outputFrames = 0;
 | 
			
		||||
 | 
			
		||||
    // create providers for each track
 | 
			
		||||
    Providers.resize(argc);
 | 
			
		||||
    for (int i = 0; i < argc; ++i) {
 | 
			
		||||
        static const char chirp[] = "chirp:";
 | 
			
		||||
        static const char sine[] = "sine:";
 | 
			
		||||
        static const double kSeconds = 10;
 | 
			
		||||
 | 
			
		||||
        if (!strncmp(argv[i], chirp, strlen(chirp))) {
 | 
			
		||||
            std::vector<int> v;
 | 
			
		||||
 | 
			
		||||
            parseCSV(argv[i] + strlen(chirp), v);
 | 
			
		||||
            if (v.size() == 2) {
 | 
			
		||||
                printf("creating chirp(%d %d)\n", v[0], v[1]);
 | 
			
		||||
                if (useInputFloat) {
 | 
			
		||||
                    Providers[i].setChirp<float>(v[0], 0, v[1]/2, v[1], kSeconds);
 | 
			
		||||
                } else {
 | 
			
		||||
                    Providers[i].setChirp<int16_t>(v[0], 0, v[1]/2, v[1], kSeconds);
 | 
			
		||||
                }
 | 
			
		||||
                Providers[i].setIncr(Pvalues);
 | 
			
		||||
            } else {
 | 
			
		||||
                fprintf(stderr, "malformed input '%s'\n", argv[i]);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (!strncmp(argv[i], sine, strlen(sine))) {
 | 
			
		||||
            std::vector<int> v;
 | 
			
		||||
 | 
			
		||||
            parseCSV(argv[i] + strlen(sine), v);
 | 
			
		||||
            if (v.size() == 3) {
 | 
			
		||||
                printf("creating sine(%d %d %d)\n", v[0], v[1], v[2]);
 | 
			
		||||
                if (useInputFloat) {
 | 
			
		||||
                    Providers[i].setSine<float>(v[0], v[1], v[2], kSeconds);
 | 
			
		||||
                } else {
 | 
			
		||||
                    Providers[i].setSine<int16_t>(v[0], v[1], v[2], kSeconds);
 | 
			
		||||
                }
 | 
			
		||||
                Providers[i].setIncr(Pvalues);
 | 
			
		||||
            } else {
 | 
			
		||||
                fprintf(stderr, "malformed input '%s'\n", argv[i]);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            printf("creating filename(%s)\n", argv[i]);
 | 
			
		||||
            if (useInputFloat) {
 | 
			
		||||
                Providers[i].setFile<float>(argv[i]);
 | 
			
		||||
            } else {
 | 
			
		||||
                Providers[i].setFile<short>(argv[i]);
 | 
			
		||||
            }
 | 
			
		||||
            Providers[i].setIncr(Pvalues);
 | 
			
		||||
        }
 | 
			
		||||
        // calculate the number of output frames
 | 
			
		||||
        size_t nframes = (int64_t) Providers[i].getNumFrames() * outputSampleRate
 | 
			
		||||
                / Providers[i].getSampleRate();
 | 
			
		||||
        if (i == 0 || outputFrames > nframes) { // choose minimum for outputFrames
 | 
			
		||||
            outputFrames = nframes;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // create the output buffer.
 | 
			
		||||
    const size_t outputFrameSize = outputChannels
 | 
			
		||||
            * (useMixerFloat ? sizeof(float) : sizeof(int16_t));
 | 
			
		||||
    const size_t outputSize = outputFrames * outputFrameSize;
 | 
			
		||||
    const audio_channel_mask_t outputChannelMask =
 | 
			
		||||
            audio_channel_out_mask_from_count(outputChannels);
 | 
			
		||||
    void *outputAddr = NULL;
 | 
			
		||||
    (void) posix_memalign(&outputAddr, 32, outputSize);
 | 
			
		||||
    memset(outputAddr, 0, outputSize);
 | 
			
		||||
 | 
			
		||||
    // create the aux buffer, if needed.
 | 
			
		||||
    const size_t auxFrameSize = sizeof(int32_t); // Q4.27 always
 | 
			
		||||
    const size_t auxSize = outputFrames * auxFrameSize;
 | 
			
		||||
    void *auxAddr = NULL;
 | 
			
		||||
    if (auxFilename) {
 | 
			
		||||
        (void) posix_memalign(&auxAddr, 32, auxSize);
 | 
			
		||||
        memset(auxAddr, 0, auxSize);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // create the mixer.
 | 
			
		||||
    const size_t mixerFrameCount = 320; // typical numbers may range from 240 or 960
 | 
			
		||||
    AudioMixer *mixer = new AudioMixer(mixerFrameCount, outputSampleRate);
 | 
			
		||||
    audio_format_t inputFormat = useInputFloat
 | 
			
		||||
            ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
 | 
			
		||||
    audio_format_t mixerFormat = useMixerFloat
 | 
			
		||||
            ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
 | 
			
		||||
    float f = AudioMixer::UNITY_GAIN_FLOAT / Providers.size(); // normalize volume by # tracks
 | 
			
		||||
    static float f0; // zero
 | 
			
		||||
 | 
			
		||||
    // set up the tracks.
 | 
			
		||||
    for (size_t i = 0; i < Providers.size(); ++i) {
 | 
			
		||||
        //printf("track %d out of %d\n", i, Providers.size());
 | 
			
		||||
        uint32_t channelMask = audio_channel_out_mask_from_count(Providers[i].getNumChannels());
 | 
			
		||||
        int32_t name = mixer->getTrackName(channelMask,
 | 
			
		||||
                inputFormat, AUDIO_SESSION_OUTPUT_MIX);
 | 
			
		||||
        ALOG_ASSERT(name >= 0);
 | 
			
		||||
        Names.push_back(name);
 | 
			
		||||
        mixer->setBufferProvider(name, &Providers[i]);
 | 
			
		||||
        mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
 | 
			
		||||
                (void *)outputAddr);
 | 
			
		||||
        mixer->setParameter(
 | 
			
		||||
                name,
 | 
			
		||||
                AudioMixer::TRACK,
 | 
			
		||||
                AudioMixer::MIXER_FORMAT,
 | 
			
		||||
                (void *)(uintptr_t)mixerFormat);
 | 
			
		||||
        mixer->setParameter(
 | 
			
		||||
                name,
 | 
			
		||||
                AudioMixer::TRACK,
 | 
			
		||||
                AudioMixer::FORMAT,
 | 
			
		||||
                (void *)(uintptr_t)inputFormat);
 | 
			
		||||
        mixer->setParameter(
 | 
			
		||||
                name,
 | 
			
		||||
                AudioMixer::TRACK,
 | 
			
		||||
                AudioMixer::MIXER_CHANNEL_MASK,
 | 
			
		||||
                (void *)(uintptr_t)outputChannelMask);
 | 
			
		||||
        mixer->setParameter(
 | 
			
		||||
                name,
 | 
			
		||||
                AudioMixer::TRACK,
 | 
			
		||||
                AudioMixer::CHANNEL_MASK,
 | 
			
		||||
                (void *)(uintptr_t)channelMask);
 | 
			
		||||
        mixer->setParameter(
 | 
			
		||||
                name,
 | 
			
		||||
                AudioMixer::RESAMPLE,
 | 
			
		||||
                AudioMixer::SAMPLE_RATE,
 | 
			
		||||
                (void *)(uintptr_t)Providers[i].getSampleRate());
 | 
			
		||||
        if (useRamp) {
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f0);
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f0);
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::RAMP_VOLUME, AudioMixer::VOLUME0, &f);
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::RAMP_VOLUME, AudioMixer::VOLUME1, &f);
 | 
			
		||||
        } else {
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f);
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f);
 | 
			
		||||
        }
 | 
			
		||||
        if (auxFilename) {
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::AUX_BUFFER,
 | 
			
		||||
                    (void *) auxAddr);
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::AUXLEVEL, &f0);
 | 
			
		||||
            mixer->setParameter(name, AudioMixer::RAMP_VOLUME, AudioMixer::AUXLEVEL, &f);
 | 
			
		||||
        }
 | 
			
		||||
        mixer->enable(name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // pump the mixer to process data.
 | 
			
		||||
    size_t i;
 | 
			
		||||
    for (i = 0; i < outputFrames - mixerFrameCount; i += mixerFrameCount) {
 | 
			
		||||
        for (size_t j = 0; j < Names.size(); ++j) {
 | 
			
		||||
            mixer->setParameter(Names[j], AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
 | 
			
		||||
                    (char *) outputAddr + i * outputFrameSize);
 | 
			
		||||
            if (auxFilename) {
 | 
			
		||||
                mixer->setParameter(Names[j], AudioMixer::TRACK, AudioMixer::AUX_BUFFER,
 | 
			
		||||
                        (char *) auxAddr + i * auxFrameSize);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        mixer->process(AudioBufferProvider::kInvalidPTS);
 | 
			
		||||
    }
 | 
			
		||||
    outputFrames = i; // reset output frames to the data actually produced.
 | 
			
		||||
 | 
			
		||||
    // write to files
 | 
			
		||||
    writeFile(outputFilename, outputAddr,
 | 
			
		||||
            outputSampleRate, outputChannels, outputFrames, useMixerFloat);
 | 
			
		||||
    if (auxFilename) {
 | 
			
		||||
        // Aux buffer is always in q4_27 format for now.
 | 
			
		||||
        // memcpy_to_i16_from_q4_27(), but with stereo frame count (not sample count)
 | 
			
		||||
        ditherAndClamp((int32_t*)auxAddr, (int32_t*)auxAddr, outputFrames >> 1);
 | 
			
		||||
        writeFile(auxFilename, auxAddr, outputSampleRate, 1, outputFrames, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    delete mixer;
 | 
			
		||||
    free(outputAddr);
 | 
			
		||||
    free(auxAddr);
 | 
			
		||||
    return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										307
									
								
								multimedia/02_day/test-mixer/test_utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								multimedia/02_day/test-mixer/test_utils.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,307 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ANDROID_AUDIO_TEST_UTILS_H
 | 
			
		||||
#define ANDROID_AUDIO_TEST_UTILS_H
 | 
			
		||||
 | 
			
		||||
#include <audio_utils/sndfile.h>
 | 
			
		||||
 | 
			
		||||
#ifndef ARRAY_SIZE
 | 
			
		||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
struct is_same
 | 
			
		||||
{
 | 
			
		||||
    static const bool value = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct is_same<T, T>  // partial specialization
 | 
			
		||||
{
 | 
			
		||||
    static const bool value = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
static inline T convertValue(double val)
 | 
			
		||||
{
 | 
			
		||||
    if (is_same<T, int16_t>::value) {
 | 
			
		||||
        return floor(val * 32767.0 + 0.5);
 | 
			
		||||
    } else if (is_same<T, int32_t>::value) {
 | 
			
		||||
        return floor(val * (1UL<<31) + 0.5);
 | 
			
		||||
    }
 | 
			
		||||
    return val; // assume float or double
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert a list of integers in CSV format to a Vector of those values.
 | 
			
		||||
// Returns the number of elements in the list, or -1 on error.
 | 
			
		||||
static inline int parseCSV(const char *string, std::vector<int>& values)
 | 
			
		||||
{
 | 
			
		||||
    // pass 1: count the number of values and do syntax check
 | 
			
		||||
    size_t numValues = 0;
 | 
			
		||||
    bool hadDigit = false;
 | 
			
		||||
    for (const char *p = string; ; ) {
 | 
			
		||||
        switch (*p++) {
 | 
			
		||||
        case '0': case '1': case '2': case '3': case '4':
 | 
			
		||||
        case '5': case '6': case '7': case '8': case '9':
 | 
			
		||||
            hadDigit = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case '\0':
 | 
			
		||||
            if (hadDigit) {
 | 
			
		||||
                // pass 2: allocate and initialize vector of values
 | 
			
		||||
                values.resize(++numValues);
 | 
			
		||||
                values[0] = atoi(p = string);
 | 
			
		||||
                for (size_t i = 1; i < numValues; ) {
 | 
			
		||||
                    if (*p++ == ',') {
 | 
			
		||||
                        values[i++] = atoi(p);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return numValues;
 | 
			
		||||
            }
 | 
			
		||||
            // fall through
 | 
			
		||||
        case ',':
 | 
			
		||||
            if (hadDigit) {
 | 
			
		||||
                hadDigit = false;
 | 
			
		||||
                numValues++;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            // fall through
 | 
			
		||||
        default:
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Creates a type-independent audio buffer provider from
 | 
			
		||||
 * a buffer base address, size, framesize, and input increment array.
 | 
			
		||||
 *
 | 
			
		||||
 * No allocation or deallocation of the provided buffer is done.
 | 
			
		||||
 */
 | 
			
		||||
class TestProvider : public android::AudioBufferProvider {
 | 
			
		||||
public:
 | 
			
		||||
    TestProvider(void* addr, size_t frames, size_t frameSize,
 | 
			
		||||
            const std::vector<int>& inputIncr)
 | 
			
		||||
    : mAddr(addr),
 | 
			
		||||
      mNumFrames(frames),
 | 
			
		||||
      mFrameSize(frameSize),
 | 
			
		||||
      mNextFrame(0), mUnrel(0), mInputIncr(inputIncr), mNextIdx(0)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TestProvider()
 | 
			
		||||
    : mAddr(NULL), mNumFrames(0), mFrameSize(0),
 | 
			
		||||
      mNextFrame(0), mUnrel(0), mNextIdx(0)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setIncr(const std::vector<int>& inputIncr) {
 | 
			
		||||
        mInputIncr = inputIncr;
 | 
			
		||||
        mNextIdx = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual android::status_t getNextBuffer(Buffer* buffer, int64_t pts __unused = kInvalidPTS)
 | 
			
		||||
    {
 | 
			
		||||
        size_t requestedFrames = buffer->frameCount;
 | 
			
		||||
        if (requestedFrames > mNumFrames - mNextFrame) {
 | 
			
		||||
            buffer->frameCount = mNumFrames - mNextFrame;
 | 
			
		||||
        }
 | 
			
		||||
        if (!mInputIncr.empty()) {
 | 
			
		||||
            size_t provided = mInputIncr[mNextIdx++];
 | 
			
		||||
            ALOGV("getNextBuffer() mValue[%zu]=%zu not %zu",
 | 
			
		||||
                    mNextIdx-1, provided, buffer->frameCount);
 | 
			
		||||
            if (provided < buffer->frameCount) {
 | 
			
		||||
                buffer->frameCount = provided;
 | 
			
		||||
            }
 | 
			
		||||
            if (mNextIdx >= mInputIncr.size()) {
 | 
			
		||||
                mNextIdx = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        ALOGV("getNextBuffer() requested %zu frames out of %zu frames available"
 | 
			
		||||
                " and returned %zu frames",
 | 
			
		||||
                requestedFrames, mNumFrames - mNextFrame, buffer->frameCount);
 | 
			
		||||
        mUnrel = buffer->frameCount;
 | 
			
		||||
        if (buffer->frameCount > 0) {
 | 
			
		||||
            buffer->raw = (char *)mAddr + mFrameSize * mNextFrame;
 | 
			
		||||
            return android::NO_ERROR;
 | 
			
		||||
        } else {
 | 
			
		||||
            buffer->raw = NULL;
 | 
			
		||||
            return android::NOT_ENOUGH_DATA;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void releaseBuffer(Buffer* buffer)
 | 
			
		||||
    {
 | 
			
		||||
        if (buffer->frameCount > mUnrel) {
 | 
			
		||||
            ALOGE("releaseBuffer() released %zu frames but only %zu available "
 | 
			
		||||
                    "to release", buffer->frameCount, mUnrel);
 | 
			
		||||
            mNextFrame += mUnrel;
 | 
			
		||||
            mUnrel = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
            ALOGV("releaseBuffer() released %zu frames out of %zu frames available "
 | 
			
		||||
                    "to release", buffer->frameCount, mUnrel);
 | 
			
		||||
            mNextFrame += buffer->frameCount;
 | 
			
		||||
            mUnrel -= buffer->frameCount;
 | 
			
		||||
        }
 | 
			
		||||
        buffer->frameCount = 0;
 | 
			
		||||
        buffer->raw = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset()
 | 
			
		||||
    {
 | 
			
		||||
        mNextFrame = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t getNumFrames()
 | 
			
		||||
    {
 | 
			
		||||
        return mNumFrames;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void* mAddr;   // base address
 | 
			
		||||
    size_t mNumFrames;   // total frames
 | 
			
		||||
    int mFrameSize;      // frame size (# channels * bytes per sample)
 | 
			
		||||
    size_t mNextFrame;   // index of next frame to provide
 | 
			
		||||
    size_t mUnrel;       // number of frames not yet released
 | 
			
		||||
    std::vector<int> mInputIncr; // number of frames provided per call
 | 
			
		||||
    size_t mNextIdx;     // index of next entry in mInputIncr to use
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Creates a buffer filled with a sine wave.
 | 
			
		||||
 */
 | 
			
		||||
template<typename T>
 | 
			
		||||
static void createSine(void *vbuffer, size_t frames,
 | 
			
		||||
        size_t channels, double sampleRate, double freq)
 | 
			
		||||
{
 | 
			
		||||
    double tscale = 1. / sampleRate;
 | 
			
		||||
    T* buffer = reinterpret_cast<T*>(vbuffer);
 | 
			
		||||
    for (size_t i = 0; i < frames; ++i) {
 | 
			
		||||
        double t = i * tscale;
 | 
			
		||||
        double y = sin(2. * M_PI * freq * t);
 | 
			
		||||
        T yt = convertValue<T>(y);
 | 
			
		||||
 | 
			
		||||
        for (size_t j = 0; j < channels; ++j) {
 | 
			
		||||
            buffer[i*channels + j] = yt / T(j + 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Creates a buffer filled with a chirp signal (a sine wave sweep).
 | 
			
		||||
 *
 | 
			
		||||
 * When creating the Chirp, note that the frequency is the true sinusoidal
 | 
			
		||||
 * frequency not the sampling rate.
 | 
			
		||||
 *
 | 
			
		||||
 * http://en.wikipedia.org/wiki/Chirp
 | 
			
		||||
 */
 | 
			
		||||
template<typename T>
 | 
			
		||||
static void createChirp(void *vbuffer, size_t frames,
 | 
			
		||||
        size_t channels, double sampleRate,  double minfreq, double maxfreq)
 | 
			
		||||
{
 | 
			
		||||
    double tscale = 1. / sampleRate;
 | 
			
		||||
    T *buffer = reinterpret_cast<T*>(vbuffer);
 | 
			
		||||
    // note the chirp constant k has a divide-by-two.
 | 
			
		||||
    double k = (maxfreq - minfreq) / (2. * tscale * frames);
 | 
			
		||||
    for (size_t i = 0; i < frames; ++i) {
 | 
			
		||||
        double t = i * tscale;
 | 
			
		||||
        double y = sin(2. * M_PI * (k * t + minfreq) * t);
 | 
			
		||||
        T yt = convertValue<T>(y);
 | 
			
		||||
 | 
			
		||||
        for (size_t j = 0; j < channels; ++j) {
 | 
			
		||||
            buffer[i*channels + j] = yt / T(j + 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This derived class creates a buffer provider of datatype T,
 | 
			
		||||
 * consisting of an input signal, e.g. from createChirp().
 | 
			
		||||
 * The number of frames can be obtained from the base class
 | 
			
		||||
 * TestProvider::getNumFrames().
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class SignalProvider : public TestProvider {
 | 
			
		||||
public:
 | 
			
		||||
    SignalProvider()
 | 
			
		||||
    : mSampleRate(0),
 | 
			
		||||
      mChannels(0)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual ~SignalProvider()
 | 
			
		||||
    {
 | 
			
		||||
        free(mAddr);
 | 
			
		||||
        mAddr = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    void setChirp(size_t channels, double minfreq, double maxfreq, double sampleRate, double time)
 | 
			
		||||
    {
 | 
			
		||||
        createBufferByFrames<T>(channels, sampleRate, sampleRate*time);
 | 
			
		||||
        createChirp<T>(mAddr, mNumFrames, mChannels, mSampleRate, minfreq, maxfreq);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    void setSine(size_t channels,
 | 
			
		||||
            double freq, double sampleRate, double time)
 | 
			
		||||
    {
 | 
			
		||||
        createBufferByFrames<T>(channels, sampleRate, sampleRate*time);
 | 
			
		||||
        createSine<T>(mAddr, mNumFrames,  mChannels, mSampleRate, freq);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    void setFile(const char *file_in)
 | 
			
		||||
    {
 | 
			
		||||
        SF_INFO info;
 | 
			
		||||
        info.format = 0;
 | 
			
		||||
        SNDFILE *sf = sf_open(file_in, SFM_READ, &info);
 | 
			
		||||
        if (sf == NULL) {
 | 
			
		||||
            perror(file_in);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        createBufferByFrames<T>(info.channels, info.samplerate, info.frames);
 | 
			
		||||
        if (is_same<T, float>::value) {
 | 
			
		||||
            (void) sf_readf_float(sf, (float *) mAddr, mNumFrames);
 | 
			
		||||
        } else if (is_same<T, short>::value) {
 | 
			
		||||
            (void) sf_readf_short(sf, (short *) mAddr, mNumFrames);
 | 
			
		||||
        }
 | 
			
		||||
        sf_close(sf);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    void createBufferByFrames(size_t channels, uint32_t sampleRate, size_t frames)
 | 
			
		||||
    {
 | 
			
		||||
        mNumFrames = frames;
 | 
			
		||||
        mChannels = channels;
 | 
			
		||||
        mFrameSize = mChannels * sizeof(T);
 | 
			
		||||
        free(mAddr);
 | 
			
		||||
        mAddr = malloc(mFrameSize * mNumFrames);
 | 
			
		||||
        mSampleRate = sampleRate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t getSampleRate() const {
 | 
			
		||||
        return mSampleRate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint32_t getNumChannels() const {
 | 
			
		||||
        return mChannels;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    uint32_t mSampleRate;
 | 
			
		||||
    uint32_t mChannels;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // ANDROID_AUDIO_TEST_UTILS_H
 | 
			
		||||
							
								
								
									
										27
									
								
								multimedia/02_day/test-resample/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								multimedia/02_day/test-resample/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES:=               \
 | 
			
		||||
    test-resample.cpp           \
 | 
			
		||||
 | 
			
		||||
LOCAL_C_INCLUDES := \
 | 
			
		||||
    $(call include-path-for, audio-utils)
 | 
			
		||||
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := \
 | 
			
		||||
    libsndfile
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := \
 | 
			
		||||
    libaudioresampler \
 | 
			
		||||
    libaudioutils \
 | 
			
		||||
    libdl \
 | 
			
		||||
    libcutils \
 | 
			
		||||
    libutils \
 | 
			
		||||
    liblog
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE:= test-resample
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
							
								
								
									
										174
									
								
								multimedia/02_day/test-resample/AudioResampler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								multimedia/02_day/test-resample/AudioResampler.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,174 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2007 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef ANDROID_AUDIO_RESAMPLER_H
 | 
			
		||||
#define ANDROID_AUDIO_RESAMPLER_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <cutils/compiler.h>
 | 
			
		||||
 | 
			
		||||
#include <media/AudioBufferProvider.h>
 | 
			
		||||
#include <system/audio.h>
 | 
			
		||||
 | 
			
		||||
namespace android {
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class ANDROID_API AudioResampler {
 | 
			
		||||
public:
 | 
			
		||||
    // Determines quality of SRC.
 | 
			
		||||
    //  LOW_QUALITY: linear interpolator (1st order)
 | 
			
		||||
    //  MED_QUALITY: cubic interpolator (3rd order)
 | 
			
		||||
    //  HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz)
 | 
			
		||||
    // NOTE: high quality SRC will only be supported for
 | 
			
		||||
    // certain fixed rate conversions. Sample rate cannot be
 | 
			
		||||
    // changed dynamically.
 | 
			
		||||
    enum src_quality {
 | 
			
		||||
        DEFAULT_QUALITY=0,
 | 
			
		||||
        LOW_QUALITY=1,
 | 
			
		||||
        MED_QUALITY=2,
 | 
			
		||||
        HIGH_QUALITY=3,
 | 
			
		||||
        VERY_HIGH_QUALITY=4,
 | 
			
		||||
        DYN_LOW_QUALITY=5,
 | 
			
		||||
        DYN_MED_QUALITY=6,
 | 
			
		||||
        DYN_HIGH_QUALITY=7,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const float UNITY_GAIN_FLOAT = 1.0f;
 | 
			
		||||
 | 
			
		||||
    static AudioResampler* create(audio_format_t format, int inChannelCount,
 | 
			
		||||
            int32_t sampleRate, src_quality quality=DEFAULT_QUALITY);
 | 
			
		||||
 | 
			
		||||
    virtual ~AudioResampler();
 | 
			
		||||
 | 
			
		||||
    virtual void init() = 0;
 | 
			
		||||
    virtual void setSampleRate(int32_t inSampleRate);
 | 
			
		||||
    virtual void setVolume(float left, float right);
 | 
			
		||||
    virtual void setLocalTimeFreq(uint64_t freq);
 | 
			
		||||
 | 
			
		||||
    // set the PTS of the next buffer output by the resampler
 | 
			
		||||
    virtual void setPTS(int64_t pts);
 | 
			
		||||
 | 
			
		||||
    // Resample int16_t samples from provider and accumulate into 'out'.
 | 
			
		||||
    // A mono provider delivers a sequence of samples.
 | 
			
		||||
    // A stereo provider delivers a sequence of interleaved pairs of samples.
 | 
			
		||||
    // Multi-channel providers are not supported.
 | 
			
		||||
    // In either case, 'out' holds interleaved pairs of fixed-point Q4.27.
 | 
			
		||||
    // That is, for a mono provider, there is an implicit up-channeling.
 | 
			
		||||
    // Since this method accumulates, the caller is responsible for clearing 'out' initially.
 | 
			
		||||
    // FIXME assumes provider is always successful; it should return the actual frame count.
 | 
			
		||||
    virtual void resample(int32_t* out, size_t outFrameCount,
 | 
			
		||||
            AudioBufferProvider* provider) = 0;
 | 
			
		||||
 | 
			
		||||
    virtual void reset();
 | 
			
		||||
    virtual size_t getUnreleasedFrames() const { return mInputIndex; }
 | 
			
		||||
 | 
			
		||||
    // called from destructor, so must not be virtual
 | 
			
		||||
    src_quality getQuality() const { return mQuality; }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    // number of bits for phase fraction - 30 bits allows nearly 2x downsampling
 | 
			
		||||
    static const int kNumPhaseBits = 30;
 | 
			
		||||
 | 
			
		||||
    // phase mask for fraction
 | 
			
		||||
    static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;
 | 
			
		||||
 | 
			
		||||
    // multiplier to calculate fixed point phase increment
 | 
			
		||||
    static const double kPhaseMultiplier;
 | 
			
		||||
 | 
			
		||||
    AudioResampler(int inChannelCount, int32_t sampleRate, src_quality quality);
 | 
			
		||||
 | 
			
		||||
    // prevent copying
 | 
			
		||||
    AudioResampler(const AudioResampler&);
 | 
			
		||||
    AudioResampler& operator=(const AudioResampler&);
 | 
			
		||||
 | 
			
		||||
    int64_t calculateOutputPTS(int outputFrameIndex);
 | 
			
		||||
 | 
			
		||||
    const int32_t mChannelCount;
 | 
			
		||||
    const int32_t mSampleRate;
 | 
			
		||||
    int32_t mInSampleRate;
 | 
			
		||||
    AudioBufferProvider::Buffer mBuffer;
 | 
			
		||||
    union {
 | 
			
		||||
        int16_t mVolume[2];
 | 
			
		||||
        uint32_t mVolumeRL;
 | 
			
		||||
    };
 | 
			
		||||
    int16_t mTargetVolume[2];
 | 
			
		||||
    size_t mInputIndex;
 | 
			
		||||
    int32_t mPhaseIncrement;
 | 
			
		||||
    uint32_t mPhaseFraction;
 | 
			
		||||
    uint64_t mLocalTimeFreq;
 | 
			
		||||
    int64_t mPTS;
 | 
			
		||||
 | 
			
		||||
    // returns the inFrameCount required to generate outFrameCount frames.
 | 
			
		||||
    //
 | 
			
		||||
    // Placed here to be a consistent for all resamplers.
 | 
			
		||||
    //
 | 
			
		||||
    // Right now, we use the upper bound without regards to the current state of the
 | 
			
		||||
    // input buffer using integer arithmetic, as follows:
 | 
			
		||||
    //
 | 
			
		||||
    // (static_cast<uint64_t>(outFrameCount)*mInSampleRate + (mSampleRate - 1))/mSampleRate;
 | 
			
		||||
    //
 | 
			
		||||
    // The double precision equivalent (float may not be precise enough):
 | 
			
		||||
    // ceil(static_cast<double>(outFrameCount) * mInSampleRate / mSampleRate);
 | 
			
		||||
    //
 | 
			
		||||
    // this relies on the fact that the mPhaseIncrement is rounded down from
 | 
			
		||||
    // #phases * mInSampleRate/mSampleRate and the fact that Sum(Floor(x)) <= Floor(Sum(x)).
 | 
			
		||||
    // http://www.proofwiki.org/wiki/Sum_of_Floors_Not_Greater_Than_Floor_of_Sums
 | 
			
		||||
    //
 | 
			
		||||
    // (so long as double precision is computed accurately enough to be considered
 | 
			
		||||
    // greater than or equal to the Floor(x) value in int32_t arithmetic; thus this
 | 
			
		||||
    // will not necessarily hold for floats).
 | 
			
		||||
    //
 | 
			
		||||
    // TODO:
 | 
			
		||||
    // Greater accuracy and a tight bound is obtained by:
 | 
			
		||||
    // 1) subtract and adjust for the current state of the AudioBufferProvider buffer.
 | 
			
		||||
    // 2) using the exact integer formula where (ignoring 64b casting)
 | 
			
		||||
    //  inFrameCount = (mPhaseIncrement * (outFrameCount - 1) + mPhaseFraction) / phaseWrapLimit;
 | 
			
		||||
    //  phaseWrapLimit is the wraparound (1 << kNumPhaseBits), if not specified explicitly.
 | 
			
		||||
    //
 | 
			
		||||
    inline size_t getInFrameCountRequired(size_t outFrameCount) {
 | 
			
		||||
        return (static_cast<uint64_t>(outFrameCount)*mInSampleRate
 | 
			
		||||
                + (mSampleRate - 1))/mSampleRate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline float clampFloatVol(float volume) {
 | 
			
		||||
        if (volume > UNITY_GAIN_FLOAT) {
 | 
			
		||||
            return UNITY_GAIN_FLOAT;
 | 
			
		||||
        } else if (volume >= 0.) {
 | 
			
		||||
            return volume;
 | 
			
		||||
        }
 | 
			
		||||
        return 0.;  // NaN or negative volume maps to 0.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const src_quality mQuality;
 | 
			
		||||
 | 
			
		||||
    // Return 'true' if the quality level is supported without explicit request
 | 
			
		||||
    static bool qualityIsSupported(src_quality quality);
 | 
			
		||||
 | 
			
		||||
    // For pthread_once()
 | 
			
		||||
    static void init_routine();
 | 
			
		||||
 | 
			
		||||
    // Return the estimated CPU load for specific resampler in MHz.
 | 
			
		||||
    // The absolute number is irrelevant, it's the relative values that matter.
 | 
			
		||||
    static uint32_t qualityMHz(src_quality quality);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
}
 | 
			
		||||
; // namespace android
 | 
			
		||||
 | 
			
		||||
#endif // ANDROID_AUDIO_RESAMPLER_H
 | 
			
		||||
							
								
								
									
										509
									
								
								multimedia/02_day/test-resample/test-resample.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										509
									
								
								multimedia/02_day/test-resample/test-resample.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,509 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <audio_utils/primitives.h>
 | 
			
		||||
#include <audio_utils/sndfile.h>
 | 
			
		||||
#include <utils/Vector.h>
 | 
			
		||||
#include <media/AudioBufferProvider.h>
 | 
			
		||||
#include "AudioResampler.h"
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
static bool gVerbose = false;
 | 
			
		||||
 | 
			
		||||
static int usage(const char* name) {
 | 
			
		||||
    fprintf(stderr,"Usage: %s [-p] [-f] [-F] [-v] [-c channels]"
 | 
			
		||||
                   " [-q {dq|lq|mq|hq|vhq|dlq|dmq|dhq}]"
 | 
			
		||||
                   " [-i input-sample-rate] [-o output-sample-rate]"
 | 
			
		||||
                   " [-O csv] [-P csv] [<input-file>]"
 | 
			
		||||
                   " <output-file>\n", name);
 | 
			
		||||
    fprintf(stderr,"    -p    enable profiling\n");
 | 
			
		||||
    fprintf(stderr,"    -f    enable filter profiling\n");
 | 
			
		||||
    fprintf(stderr,"    -F    enable floating point -q {dlq|dmq|dhq} only");
 | 
			
		||||
    fprintf(stderr,"    -v    verbose : log buffer provider calls\n");
 | 
			
		||||
    fprintf(stderr,"    -c    # channels (1-2 for lq|mq|hq; 1-8 for dlq|dmq|dhq)\n");
 | 
			
		||||
    fprintf(stderr,"    -q    resampler quality\n");
 | 
			
		||||
    fprintf(stderr,"              dq  : default quality\n");
 | 
			
		||||
    fprintf(stderr,"              lq  : low quality\n");
 | 
			
		||||
    fprintf(stderr,"              mq  : medium quality\n");
 | 
			
		||||
    fprintf(stderr,"              hq  : high quality\n");
 | 
			
		||||
    fprintf(stderr,"              vhq : very high quality\n");
 | 
			
		||||
    fprintf(stderr,"              dlq : dynamic low quality\n");
 | 
			
		||||
    fprintf(stderr,"              dmq : dynamic medium quality\n");
 | 
			
		||||
    fprintf(stderr,"              dhq : dynamic high quality\n");
 | 
			
		||||
    fprintf(stderr,"    -i    input file sample rate (ignored if input file is specified)\n");
 | 
			
		||||
    fprintf(stderr,"    -o    output file sample rate\n");
 | 
			
		||||
    fprintf(stderr,"    -O    # frames output per call to resample() in CSV format\n");
 | 
			
		||||
    fprintf(stderr,"    -P    # frames provided per call to resample() in CSV format\n");
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert a list of integers in CSV format to a Vector of those values.
 | 
			
		||||
// Returns the number of elements in the list, or -1 on error.
 | 
			
		||||
int parseCSV(const char *string, Vector<int>& values)
 | 
			
		||||
{
 | 
			
		||||
    // pass 1: count the number of values and do syntax check
 | 
			
		||||
    size_t numValues = 0;
 | 
			
		||||
    bool hadDigit = false;
 | 
			
		||||
    for (const char *p = string; ; ) {
 | 
			
		||||
        switch (*p++) {
 | 
			
		||||
        case '0': case '1': case '2': case '3': case '4':
 | 
			
		||||
        case '5': case '6': case '7': case '8': case '9':
 | 
			
		||||
            hadDigit = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case '\0':
 | 
			
		||||
            if (hadDigit) {
 | 
			
		||||
                // pass 2: allocate and initialize vector of values
 | 
			
		||||
                values.resize(++numValues);
 | 
			
		||||
                values.editItemAt(0) = atoi(p = optarg);
 | 
			
		||||
                for (size_t i = 1; i < numValues; ) {
 | 
			
		||||
                    if (*p++ == ',') {
 | 
			
		||||
                        values.editItemAt(i++) = atoi(p);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return numValues;
 | 
			
		||||
            }
 | 
			
		||||
            // fall through
 | 
			
		||||
        case ',':
 | 
			
		||||
            if (hadDigit) {
 | 
			
		||||
                hadDigit = false;
 | 
			
		||||
                numValues++;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            // fall through
 | 
			
		||||
        default:
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
    const char* const progname = argv[0];
 | 
			
		||||
    bool profileResample = false;
 | 
			
		||||
    bool profileFilter = false;
 | 
			
		||||
    bool useFloat = false;
 | 
			
		||||
    int channels = 1;
 | 
			
		||||
    int input_freq = 0;
 | 
			
		||||
    int output_freq = 0;
 | 
			
		||||
    AudioResampler::src_quality quality = AudioResampler::DEFAULT_QUALITY;
 | 
			
		||||
    Vector<int> Ovalues;
 | 
			
		||||
    Vector<int> Pvalues;
 | 
			
		||||
 | 
			
		||||
    int ch;
 | 
			
		||||
    while ((ch = getopt(argc, argv, "pfFvc:q:i:o:O:P:")) != -1) {
 | 
			
		||||
        switch (ch) {
 | 
			
		||||
        case 'p':
 | 
			
		||||
            profileResample = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'f':
 | 
			
		||||
            profileFilter = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'F':
 | 
			
		||||
            useFloat = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'v':
 | 
			
		||||
            gVerbose = true;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'c':
 | 
			
		||||
            channels = atoi(optarg);
 | 
			
		||||
            break;
 | 
			
		||||
        case 'q':
 | 
			
		||||
            if (!strcmp(optarg, "dq"))
 | 
			
		||||
                quality = AudioResampler::DEFAULT_QUALITY;
 | 
			
		||||
            else if (!strcmp(optarg, "lq"))
 | 
			
		||||
                quality = AudioResampler::LOW_QUALITY;
 | 
			
		||||
            else if (!strcmp(optarg, "mq"))
 | 
			
		||||
                quality = AudioResampler::MED_QUALITY;
 | 
			
		||||
            else if (!strcmp(optarg, "hq"))
 | 
			
		||||
                quality = AudioResampler::HIGH_QUALITY;
 | 
			
		||||
            else if (!strcmp(optarg, "vhq"))
 | 
			
		||||
                quality = AudioResampler::VERY_HIGH_QUALITY;
 | 
			
		||||
            else if (!strcmp(optarg, "dlq"))
 | 
			
		||||
                quality = AudioResampler::DYN_LOW_QUALITY;
 | 
			
		||||
            else if (!strcmp(optarg, "dmq"))
 | 
			
		||||
                quality = AudioResampler::DYN_MED_QUALITY;
 | 
			
		||||
            else if (!strcmp(optarg, "dhq"))
 | 
			
		||||
                quality = AudioResampler::DYN_HIGH_QUALITY;
 | 
			
		||||
            else {
 | 
			
		||||
                usage(progname);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case 'i':
 | 
			
		||||
            input_freq = atoi(optarg);
 | 
			
		||||
            break;
 | 
			
		||||
        case 'o':
 | 
			
		||||
            output_freq = atoi(optarg);
 | 
			
		||||
            break;
 | 
			
		||||
        case 'O':
 | 
			
		||||
            if (parseCSV(optarg, Ovalues) < 0) {
 | 
			
		||||
                fprintf(stderr, "incorrect syntax for -O option\n");
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case 'P':
 | 
			
		||||
            if (parseCSV(optarg, Pvalues) < 0) {
 | 
			
		||||
                fprintf(stderr, "incorrect syntax for -P option\n");
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case '?':
 | 
			
		||||
        default:
 | 
			
		||||
            usage(progname);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (channels < 1
 | 
			
		||||
            || channels > (quality < AudioResampler::DYN_LOW_QUALITY ? 2 : 8)) {
 | 
			
		||||
        fprintf(stderr, "invalid number of audio channels %d\n", channels);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    if (useFloat && quality < AudioResampler::DYN_LOW_QUALITY) {
 | 
			
		||||
        fprintf(stderr, "float processing is only possible for dynamic resamplers\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    argc -= optind;
 | 
			
		||||
    argv += optind;
 | 
			
		||||
 | 
			
		||||
    const char* file_in = NULL;
 | 
			
		||||
    const char* file_out = NULL;
 | 
			
		||||
    if (argc == 1) {
 | 
			
		||||
        file_out = argv[0];
 | 
			
		||||
    } else if (argc == 2) {
 | 
			
		||||
        file_in = argv[0];
 | 
			
		||||
        file_out = argv[1];
 | 
			
		||||
    } else {
 | 
			
		||||
        usage(progname);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // ----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    size_t input_size;
 | 
			
		||||
    void* input_vaddr;
 | 
			
		||||
    if (argc == 2) {
 | 
			
		||||
        SF_INFO info;
 | 
			
		||||
        info.format = 0;
 | 
			
		||||
        SNDFILE *sf = sf_open(file_in, SFM_READ, &info);
 | 
			
		||||
        if (sf == NULL) {
 | 
			
		||||
            perror(file_in);
 | 
			
		||||
            return EXIT_FAILURE;
 | 
			
		||||
        }
 | 
			
		||||
        input_size = info.frames * info.channels * sizeof(short);
 | 
			
		||||
        input_vaddr = malloc(input_size);
 | 
			
		||||
        (void) sf_readf_short(sf, (short *) input_vaddr, info.frames);
 | 
			
		||||
        sf_close(sf);
 | 
			
		||||
        channels = info.channels;
 | 
			
		||||
        input_freq = info.samplerate;
 | 
			
		||||
    } else {
 | 
			
		||||
        // data for testing is exactly (input sampling rate/1000)/2 seconds
 | 
			
		||||
        // so 44.1khz input is 22.05 seconds
 | 
			
		||||
        double k = 1000; // Hz / s
 | 
			
		||||
        double time = (input_freq / 2) / k;
 | 
			
		||||
        size_t input_frames = size_t(input_freq * time);
 | 
			
		||||
        input_size = channels * sizeof(int16_t) * input_frames;
 | 
			
		||||
        input_vaddr = malloc(input_size);
 | 
			
		||||
        int16_t* in = (int16_t*)input_vaddr;
 | 
			
		||||
        for (size_t i=0 ; i<input_frames ; i++) {
 | 
			
		||||
            double t = double(i) / input_freq;
 | 
			
		||||
            double y = sin(M_PI * k * t * t);
 | 
			
		||||
            int16_t yi = floor(y * 32767.0 + 0.5);
 | 
			
		||||
            for (int j = 0; j < channels; j++) {
 | 
			
		||||
                in[i*channels + j] = yi / (1 + j);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    size_t input_framesize = channels * sizeof(int16_t);
 | 
			
		||||
    size_t input_frames = input_size / input_framesize;
 | 
			
		||||
 | 
			
		||||
    // For float processing, convert input int16_t to float array
 | 
			
		||||
    if (useFloat) {
 | 
			
		||||
        void *new_vaddr;
 | 
			
		||||
 | 
			
		||||
        input_framesize = channels * sizeof(float);
 | 
			
		||||
        input_size = input_frames * input_framesize;
 | 
			
		||||
        new_vaddr = malloc(input_size);
 | 
			
		||||
        memcpy_to_float_from_i16(reinterpret_cast<float*>(new_vaddr),
 | 
			
		||||
                reinterpret_cast<int16_t*>(input_vaddr), input_frames * channels);
 | 
			
		||||
        free(input_vaddr);
 | 
			
		||||
        input_vaddr = new_vaddr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // ----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
    class Provider: public AudioBufferProvider {
 | 
			
		||||
        const void*     mAddr;      // base address
 | 
			
		||||
        const size_t    mNumFrames; // total frames
 | 
			
		||||
        const size_t    mFrameSize; // size of each frame in bytes
 | 
			
		||||
        size_t          mNextFrame; // index of next frame to provide
 | 
			
		||||
        size_t          mUnrel;     // number of frames not yet released
 | 
			
		||||
        const Vector<int> mPvalues; // number of frames provided per call
 | 
			
		||||
        size_t          mNextPidx;  // index of next entry in mPvalues to use
 | 
			
		||||
    public:
 | 
			
		||||
        Provider(const void* addr, size_t frames, size_t frameSize, const Vector<int>& Pvalues)
 | 
			
		||||
          : mAddr(addr),
 | 
			
		||||
            mNumFrames(frames),
 | 
			
		||||
            mFrameSize(frameSize),
 | 
			
		||||
            mNextFrame(0), mUnrel(0), mPvalues(Pvalues), mNextPidx(0) {
 | 
			
		||||
        }
 | 
			
		||||
        virtual status_t getNextBuffer(Buffer* buffer,
 | 
			
		||||
                int64_t pts = kInvalidPTS) {
 | 
			
		||||
            (void)pts; // suppress warning
 | 
			
		||||
            size_t requestedFrames = buffer->frameCount;
 | 
			
		||||
            if (requestedFrames > mNumFrames - mNextFrame) {
 | 
			
		||||
                buffer->frameCount = mNumFrames - mNextFrame;
 | 
			
		||||
            }
 | 
			
		||||
            if (!mPvalues.isEmpty()) {
 | 
			
		||||
                size_t provided = mPvalues[mNextPidx++];
 | 
			
		||||
                printf("mPvalue[%zu]=%zu not %zu\n", mNextPidx-1, provided, buffer->frameCount);
 | 
			
		||||
                if (provided < buffer->frameCount) {
 | 
			
		||||
                    buffer->frameCount = provided;
 | 
			
		||||
                }
 | 
			
		||||
                if (mNextPidx >= mPvalues.size()) {
 | 
			
		||||
                    mNextPidx = 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (gVerbose) {
 | 
			
		||||
                printf("getNextBuffer() requested %zu frames out of %zu frames available,"
 | 
			
		||||
                        " and returned %zu frames\n",
 | 
			
		||||
                        requestedFrames, (size_t) (mNumFrames - mNextFrame), buffer->frameCount);
 | 
			
		||||
            }
 | 
			
		||||
            mUnrel = buffer->frameCount;
 | 
			
		||||
            if (buffer->frameCount > 0) {
 | 
			
		||||
                buffer->raw = (char *)mAddr + mFrameSize * mNextFrame;
 | 
			
		||||
                return NO_ERROR;
 | 
			
		||||
            } else {
 | 
			
		||||
                buffer->raw = NULL;
 | 
			
		||||
                return NOT_ENOUGH_DATA;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        virtual void releaseBuffer(Buffer* buffer) {
 | 
			
		||||
            if (buffer->frameCount > mUnrel) {
 | 
			
		||||
                fprintf(stderr, "ERROR releaseBuffer() released %zu frames but only %zu available "
 | 
			
		||||
                        "to release\n", buffer->frameCount, mUnrel);
 | 
			
		||||
                mNextFrame += mUnrel;
 | 
			
		||||
                mUnrel = 0;
 | 
			
		||||
            } else {
 | 
			
		||||
                if (gVerbose) {
 | 
			
		||||
                    printf("releaseBuffer() released %zu frames out of %zu frames available "
 | 
			
		||||
                            "to release\n", buffer->frameCount, mUnrel);
 | 
			
		||||
                }
 | 
			
		||||
                mNextFrame += buffer->frameCount;
 | 
			
		||||
                mUnrel -= buffer->frameCount;
 | 
			
		||||
            }
 | 
			
		||||
            buffer->frameCount = 0;
 | 
			
		||||
            buffer->raw = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        void reset() {
 | 
			
		||||
            mNextFrame = 0;
 | 
			
		||||
        }
 | 
			
		||||
    } provider(input_vaddr, input_frames, input_framesize, Pvalues);
 | 
			
		||||
 | 
			
		||||
    if (gVerbose) {
 | 
			
		||||
        printf("%zu input frames\n", input_frames);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    audio_format_t format = useFloat ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
 | 
			
		||||
    int output_channels = channels > 2 ? channels : 2; // output is at least stereo samples
 | 
			
		||||
    size_t output_framesize = output_channels * (useFloat ? sizeof(float) : sizeof(int32_t));
 | 
			
		||||
    size_t output_frames = ((int64_t) input_frames * output_freq) / input_freq;
 | 
			
		||||
    size_t output_size = output_frames * output_framesize;
 | 
			
		||||
 | 
			
		||||
    if (profileFilter) {
 | 
			
		||||
        // Check how fast sample rate changes are that require filter changes.
 | 
			
		||||
        // The delta sample rate changes must indicate a downsampling ratio,
 | 
			
		||||
        // and must be larger than 10% changes.
 | 
			
		||||
        //
 | 
			
		||||
        // On fast devices, filters should be generated between 0.1ms - 1ms.
 | 
			
		||||
        // (single threaded).
 | 
			
		||||
        AudioResampler* resampler = AudioResampler::create(format, channels,
 | 
			
		||||
                8000, quality);
 | 
			
		||||
        int looplimit = 100;
 | 
			
		||||
        timespec start, end;
 | 
			
		||||
        clock_gettime(CLOCK_MONOTONIC, &start);
 | 
			
		||||
        for (int i = 0; i < looplimit; ++i) {
 | 
			
		||||
            resampler->setSampleRate(9000);
 | 
			
		||||
            resampler->setSampleRate(12000);
 | 
			
		||||
            resampler->setSampleRate(20000);
 | 
			
		||||
            resampler->setSampleRate(30000);
 | 
			
		||||
        }
 | 
			
		||||
        clock_gettime(CLOCK_MONOTONIC, &end);
 | 
			
		||||
        int64_t start_ns = start.tv_sec * 1000000000LL + start.tv_nsec;
 | 
			
		||||
        int64_t end_ns = end.tv_sec * 1000000000LL + end.tv_nsec;
 | 
			
		||||
        int64_t time = end_ns - start_ns;
 | 
			
		||||
        printf("%.2f sample rate changes with filter calculation/sec\n",
 | 
			
		||||
                looplimit * 4 / (time / 1e9));
 | 
			
		||||
 | 
			
		||||
        // Check how fast sample rate changes are without filter changes.
 | 
			
		||||
        // This should be very fast, probably 0.1us - 1us per sample rate
 | 
			
		||||
        // change.
 | 
			
		||||
        resampler->setSampleRate(1000);
 | 
			
		||||
        looplimit = 1000;
 | 
			
		||||
        clock_gettime(CLOCK_MONOTONIC, &start);
 | 
			
		||||
        for (int i = 0; i < looplimit; ++i) {
 | 
			
		||||
            resampler->setSampleRate(1000+i);
 | 
			
		||||
        }
 | 
			
		||||
        clock_gettime(CLOCK_MONOTONIC, &end);
 | 
			
		||||
        start_ns = start.tv_sec * 1000000000LL + start.tv_nsec;
 | 
			
		||||
        end_ns = end.tv_sec * 1000000000LL + end.tv_nsec;
 | 
			
		||||
        time = end_ns - start_ns;
 | 
			
		||||
        printf("%.2f sample rate changes without filter calculation/sec\n",
 | 
			
		||||
                looplimit / (time / 1e9));
 | 
			
		||||
        resampler->reset();
 | 
			
		||||
        delete resampler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void* output_vaddr = malloc(output_size);
 | 
			
		||||
    AudioResampler* resampler = AudioResampler::create(format, channels,
 | 
			
		||||
            output_freq, quality);
 | 
			
		||||
 | 
			
		||||
    resampler->setSampleRate(input_freq);
 | 
			
		||||
    resampler->setVolume(AudioResampler::UNITY_GAIN_FLOAT, AudioResampler::UNITY_GAIN_FLOAT);
 | 
			
		||||
 | 
			
		||||
    if (profileResample) {
 | 
			
		||||
        /*
 | 
			
		||||
         * For profiling on mobile devices, upon experimentation
 | 
			
		||||
         * it is better to run a few trials with a shorter loop limit,
 | 
			
		||||
         * and take the minimum time.
 | 
			
		||||
         *
 | 
			
		||||
         * Long tests can cause CPU temperature to build up and thermal throttling
 | 
			
		||||
         * to reduce CPU frequency.
 | 
			
		||||
         *
 | 
			
		||||
         * For frequency checks (index=0, or 1, etc.):
 | 
			
		||||
         * "cat /sys/devices/system/cpu/cpu${index}/cpufreq/scaling_*_freq"
 | 
			
		||||
         *
 | 
			
		||||
         * For temperature checks (index=0, or 1, etc.):
 | 
			
		||||
         * "cat /sys/class/thermal/thermal_zone${index}/temp"
 | 
			
		||||
         *
 | 
			
		||||
         * Another way to avoid thermal throttling is to fix the CPU frequency
 | 
			
		||||
         * at a lower level which prevents excessive temperatures.
 | 
			
		||||
         */
 | 
			
		||||
        const int trials = 4;
 | 
			
		||||
        const int looplimit = 4;
 | 
			
		||||
        timespec start, end;
 | 
			
		||||
        int64_t time = 0;
 | 
			
		||||
 | 
			
		||||
        for (int n = 0; n < trials; ++n) {
 | 
			
		||||
            clock_gettime(CLOCK_MONOTONIC, &start);
 | 
			
		||||
            for (int i = 0; i < looplimit; ++i) {
 | 
			
		||||
                resampler->resample((int*) output_vaddr, output_frames, &provider);
 | 
			
		||||
                provider.reset(); //  during benchmarking reset only the provider
 | 
			
		||||
            }
 | 
			
		||||
            clock_gettime(CLOCK_MONOTONIC, &end);
 | 
			
		||||
            int64_t start_ns = start.tv_sec * 1000000000LL + start.tv_nsec;
 | 
			
		||||
            int64_t end_ns = end.tv_sec * 1000000000LL + end.tv_nsec;
 | 
			
		||||
            int64_t diff_ns = end_ns - start_ns;
 | 
			
		||||
            if (n == 0 || diff_ns < time) {
 | 
			
		||||
                time = diff_ns;   // save the best out of our trials.
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Mfrms/s is "Millions of output frames per second".
 | 
			
		||||
        printf("quality: %d  channels: %d  msec: %" PRId64 "  Mfrms/s: %.2lf\n",
 | 
			
		||||
                quality, channels, time/1000000, output_frames * looplimit / (time / 1e9) / 1e6);
 | 
			
		||||
        resampler->reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(output_vaddr, 0, output_size);
 | 
			
		||||
    if (gVerbose) {
 | 
			
		||||
        printf("resample() %zu output frames\n", output_frames);
 | 
			
		||||
    }
 | 
			
		||||
    if (Ovalues.isEmpty()) {
 | 
			
		||||
        Ovalues.push(output_frames);
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t i = 0, j = 0; i < output_frames; ) {
 | 
			
		||||
        size_t thisFrames = Ovalues[j++];
 | 
			
		||||
        if (j >= Ovalues.size()) {
 | 
			
		||||
            j = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (thisFrames == 0 || thisFrames > output_frames - i) {
 | 
			
		||||
            thisFrames = output_frames - i;
 | 
			
		||||
        }
 | 
			
		||||
        resampler->resample((int*) output_vaddr + output_channels*i, thisFrames, &provider);
 | 
			
		||||
        i += thisFrames;
 | 
			
		||||
    }
 | 
			
		||||
    if (gVerbose) {
 | 
			
		||||
        printf("resample() complete\n");
 | 
			
		||||
    }
 | 
			
		||||
    resampler->reset();
 | 
			
		||||
    if (gVerbose) {
 | 
			
		||||
        printf("reset() complete\n");
 | 
			
		||||
    }
 | 
			
		||||
    delete resampler;
 | 
			
		||||
    resampler = NULL;
 | 
			
		||||
 | 
			
		||||
    // For float processing, convert output format from float to Q4.27,
 | 
			
		||||
    // which is then converted to int16_t for final storage.
 | 
			
		||||
    if (useFloat) {
 | 
			
		||||
        memcpy_to_q4_27_from_float(reinterpret_cast<int32_t*>(output_vaddr),
 | 
			
		||||
                reinterpret_cast<float*>(output_vaddr), output_frames * output_channels);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // mono takes left channel only (out of stereo output pair)
 | 
			
		||||
    // stereo and multichannel preserve all channels.
 | 
			
		||||
    int32_t* out = (int32_t*) output_vaddr;
 | 
			
		||||
    int16_t* convert = (int16_t*) malloc(output_frames * channels * sizeof(int16_t));
 | 
			
		||||
 | 
			
		||||
    const int volumeShift = 12; // shift requirement for Q4.27 to Q.15
 | 
			
		||||
    // round to half towards zero and saturate at int16 (non-dithered)
 | 
			
		||||
    const int roundVal = (1<<(volumeShift-1)) - 1; // volumePrecision > 0
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < output_frames; i++) {
 | 
			
		||||
        for (int j = 0; j < channels; j++) {
 | 
			
		||||
            int32_t s = out[i * output_channels + j] + roundVal; // add offset here
 | 
			
		||||
            if (s < 0) {
 | 
			
		||||
                s = (s + 1) >> volumeShift; // round to 0
 | 
			
		||||
                if (s < -32768) {
 | 
			
		||||
                    s = -32768;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                s = s >> volumeShift;
 | 
			
		||||
                if (s > 32767) {
 | 
			
		||||
                    s = 32767;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            convert[i * channels + j] = int16_t(s);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // write output to disk
 | 
			
		||||
    SF_INFO info;
 | 
			
		||||
    info.frames = 0;
 | 
			
		||||
    info.samplerate = output_freq;
 | 
			
		||||
    info.channels = channels;
 | 
			
		||||
    info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
 | 
			
		||||
    SNDFILE *sf = sf_open(file_out, SFM_WRITE, &info);
 | 
			
		||||
    if (sf == NULL) {
 | 
			
		||||
        perror(file_out);
 | 
			
		||||
        return EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
    (void) sf_writef_short(sf, convert, output_frames);
 | 
			
		||||
    sf_close(sf);
 | 
			
		||||
 | 
			
		||||
    return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								multimedia/02_day/test-thread/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								multimedia/02_day/test-thread/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SRC_FILES:= thread.cpp
 | 
			
		||||
LOCAL_MODULE := my_thread
 | 
			
		||||
LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								multimedia/02_day/test-thread/thread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								multimedia/02_day/test-thread/thread.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
#include <binder/IServiceManager.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
#include <utils/Thread.h>
 | 
			
		||||
#include <binder/MemoryHeapBase.h>
 | 
			
		||||
#include <binder/IPCThreadState.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MyThread : public Thread 
 | 
			
		||||
{
 | 
			
		||||
	public : 
 | 
			
		||||
		bool threadLoop()
 | 
			
		||||
		{
 | 
			
		||||
			printf("MyThread::threadLoop()\n"); 
 | 
			
		||||
			sleep(1);
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	sp<Thread> thread = new MyThread;
 | 
			
		||||
	thread->run();
 | 
			
		||||
	getchar();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								multimedia/03_day/test-bitmap/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								multimedia/03_day/test-bitmap/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES:=  test-bitmap.cpp
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := libutils  libgui libui
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE:= test-bitmap
 | 
			
		||||
LOCAL_CFLAGS:= -g -O0
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE_TAGS := optional
 | 
			
		||||
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								multimedia/03_day/test-bitmap/bbb.bmp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								multimedia/03_day/test-bitmap/bbb.bmp
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 145 KiB  | 
							
								
								
									
										133
									
								
								multimedia/03_day/test-bitmap/test-bitmap.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								multimedia/03_day/test-bitmap/test-bitmap.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,133 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <linux/fb.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <ui/PixelFormat.h>
 | 
			
		||||
#include <media/mediaplayer.h>
 | 
			
		||||
#include <media/IMediaPlayer.h>
 | 
			
		||||
#include <binder/ProcessState.h>
 | 
			
		||||
#include <binder/IPCThreadState.h>
 | 
			
		||||
#include <gui/SurfaceComposerClient.h>
 | 
			
		||||
#include <gui/ISurfaceComposer.h>
 | 
			
		||||
#include <utils/String8.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <utils/RefBase.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
#include <gui/Surface.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
typedef unsigned char u8;
 | 
			
		||||
typedef unsigned short u16;
 | 
			
		||||
typedef unsigned int u32;
 | 
			
		||||
 | 
			
		||||
struct BITMAPFILEHEADER {
 | 
			
		||||
	u16 bfType;
 | 
			
		||||
	u32 bfSize;
 | 
			
		||||
	u16 bfReserved1;
 | 
			
		||||
	u16 bfReserved2;
 | 
			
		||||
	u32 bfOffBits;
 | 
			
		||||
} __attribute((packed));
 | 
			
		||||
 | 
			
		||||
struct BITMAPINFOHEADER {
 | 
			
		||||
	u32 biSize;
 | 
			
		||||
	u32 biWidth;
 | 
			
		||||
	u32 biHeight;
 | 
			
		||||
	u16 biPlanes;
 | 
			
		||||
	u16 biBitCount;
 | 
			
		||||
	u32 biCompression;
 | 
			
		||||
	u32 biSizeImage;
 | 
			
		||||
	u32 biXPelsPerMeter;
 | 
			
		||||
	u32 biYPelsPerMeter;
 | 
			
		||||
	u32 biClrUsed;
 | 
			
		||||
	u32 biClrImportant;
 | 
			
		||||
} __attribute((packed));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void fillRGBA8BMP(uint8_t* dst, uint8_t* src, int w, int h, int stride, int bpp) 
 | 
			
		||||
{
 | 
			
		||||
	const size_t PIXEL_SIZE = 4;
 | 
			
		||||
	src = src+w*h*bpp;
 | 
			
		||||
	for (int y = 0; y < h; y++) {
 | 
			
		||||
		src -= w*bpp;
 | 
			
		||||
		for (int x = 0; x < w; x++) {
 | 
			
		||||
			off_t offset = (y * stride + x) * PIXEL_SIZE;
 | 
			
		||||
			dst[offset + 0] = src[x*bpp+2];
 | 
			
		||||
			dst[offset + 1] = src[x*bpp+1];
 | 
			
		||||
			dst[offset + 2] = src[x*bpp+0];
 | 
			
		||||
			dst[offset + 3] = 255;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int fd;
 | 
			
		||||
	int w,h;
 | 
			
		||||
	BITMAPFILEHEADER  file_header;
 | 
			
		||||
	BITMAPINFOHEADER  DIB; 
 | 
			
		||||
 | 
			
		||||
	fd = open("bbb.bmp", O_RDONLY);
 | 
			
		||||
	printf("fd=%d\n", fd );
 | 
			
		||||
	read( fd, &file_header, sizeof file_header );
 | 
			
		||||
	read( fd, &DIB, sizeof DIB );
 | 
			
		||||
	w = DIB.biWidth;
 | 
			
		||||
	h = DIB.biHeight;
 | 
			
		||||
	printf("size=%u\n", file_header.bfSize );
 | 
			
		||||
	printf("BitCount=%u\n", DIB.biBitCount );
 | 
			
		||||
	int bpp = DIB.biBitCount/8;
 | 
			
		||||
	uint8_t *src = (uint8_t*)malloc( DIB.biSizeImage*bpp );
 | 
			
		||||
	read( fd, src,  DIB.biSizeImage*bpp );
 | 
			
		||||
	sp <Surface> gsf;
 | 
			
		||||
	status_t nState;
 | 
			
		||||
 | 
			
		||||
	printf("create SurfaceComposerClient\n");
 | 
			
		||||
 | 
			
		||||
	sp<SurfaceComposerClient> composerClient;
 | 
			
		||||
	sp<SurfaceControl> control;
 | 
			
		||||
 | 
			
		||||
	composerClient = new SurfaceComposerClient;
 | 
			
		||||
	composerClient->initCheck();
 | 
			
		||||
 | 
			
		||||
	printf("create video surface\n");
 | 
			
		||||
 | 
			
		||||
	control = composerClient->createSurface(
 | 
			
		||||
			String8("A Surface"),
 | 
			
		||||
			w,
 | 
			
		||||
			h,
 | 
			
		||||
			PIXEL_FORMAT_RGBA_8888,
 | 
			
		||||
			0);
 | 
			
		||||
 | 
			
		||||
	SurfaceComposerClient::openGlobalTransaction();
 | 
			
		||||
	control->setLayer(INT_MAX);
 | 
			
		||||
	control->show();
 | 
			
		||||
	SurfaceComposerClient::closeGlobalTransaction();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	sp<ANativeWindow> window;
 | 
			
		||||
	window = control->getSurface();
 | 
			
		||||
 | 
			
		||||
	ANativeWindowBuffer *anb;
 | 
			
		||||
	native_window_dequeue_buffer_and_wait(window.get(), &anb);
 | 
			
		||||
 | 
			
		||||
	sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
 | 
			
		||||
 | 
			
		||||
	uint8_t* img = NULL;
 | 
			
		||||
	buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
 | 
			
		||||
	printf("width=%d, height=%d, stride=%d\n", 
 | 
			
		||||
			buf->getWidth(), buf->getHeight(), buf->getStride());
 | 
			
		||||
 | 
			
		||||
	fillRGBA8BMP(img, src, w, h, buf->getStride(), bpp);
 | 
			
		||||
	buf->unlock();
 | 
			
		||||
	window->queueBuffer(window.get(), buf->getNativeBuffer(), -1);
 | 
			
		||||
	getchar();
 | 
			
		||||
 | 
			
		||||
	free(src);
 | 
			
		||||
	close(fd);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								multimedia/03_day/test-looper/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								multimedia/03_day/test-looper/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := liblog libutils  libmedia
 | 
			
		||||
LOCAL_SRC_FILES :=  my_looper.cpp
 | 
			
		||||
LOCAL_MODULE := my_looper
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										263
									
								
								multimedia/03_day/test-looper/my_looper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								multimedia/03_day/test-looper/my_looper.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,263 @@
 | 
			
		||||
#if 1
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <utils/Looper.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
class MyThread : public Thread {
 | 
			
		||||
	    sp<Looper> mLooper;
 | 
			
		||||
	    sp<MessageHandler> mHandler;
 | 
			
		||||
	public : 
 | 
			
		||||
		MyThread( sp<Looper> &looper , sp<MessageHandler> &handler ) 
 | 
			
		||||
			: mLooper(looper),mHandler(handler){}
 | 
			
		||||
		bool threadLoop() {
 | 
			
		||||
			mLooper->sendMessageDelayed( s2ns(3),  mHandler, Message(3) );
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class MyMessageHandler : public MessageHandler
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	virtual void handleMessage(const Message& message)
 | 
			
		||||
	{
 | 
			
		||||
		printf("MyMessageHandler::handleMessage(%d)\n", message.what );
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	sp<Looper> looper = new Looper(true);
 | 
			
		||||
	sp<MessageHandler> handler = new MyMessageHandler;
 | 
			
		||||
	sp<Thread> thread = new MyThread( looper, handler );
 | 
			
		||||
 | 
			
		||||
	thread->run();
 | 
			
		||||
 | 
			
		||||
	while( 1)
 | 
			
		||||
	{
 | 
			
		||||
		ret = looper->pollOnce(-1);
 | 
			
		||||
 | 
			
		||||
		if( ret == Looper::POLL_WAKE ) 
 | 
			
		||||
			printf("Looper::POLL_WAKE\n");
 | 
			
		||||
		if( ret == Looper::POLL_CALLBACK ) 
 | 
			
		||||
			printf("Looper::POLL_CALLBACK\n");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#if 0
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <utils/Looper.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
class MyThread : public Thread {
 | 
			
		||||
	    sp<Looper> mLooper;
 | 
			
		||||
		int mFd;
 | 
			
		||||
	public : 
 | 
			
		||||
		MyThread( sp<Looper> &looper , int fd ) : mLooper(looper),mFd(fd){}
 | 
			
		||||
		bool threadLoop() {
 | 
			
		||||
			sleep(3);
 | 
			
		||||
			write( mFd, "W", 1 );
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class CallbackHandler
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	void setCallback( sp<Looper> &looper, int fd, int events )
 | 
			
		||||
	{
 | 
			
		||||
		looper->addFd( fd, 0, events, callbackFunc, this );
 | 
			
		||||
	}
 | 
			
		||||
	static int callbackFunc(int fd, int events, void* data)
 | 
			
		||||
	{
 | 
			
		||||
		return ((CallbackHandler*)data)->handler( fd, events, data );
 | 
			
		||||
	}
 | 
			
		||||
	virtual ~CallbackHandler(){}
 | 
			
		||||
	virtual int handler(int fd, int events, void* data) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class MyCallback : public CallbackHandler
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int handler(int fd, int events, void* data)
 | 
			
		||||
	{
 | 
			
		||||
		printf("MyCallback::handler(%d, %d, %p)\n", fd, events, data);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	int fds[2];
 | 
			
		||||
	pipe(fds);
 | 
			
		||||
	MyCallback callback;
 | 
			
		||||
	sp<Looper> looper = new Looper(true);
 | 
			
		||||
	sp<Thread> thread = new MyThread( looper, fds[1] );
 | 
			
		||||
 | 
			
		||||
	callback.setCallback( looper, fds[0], Looper::EVENT_INPUT );
 | 
			
		||||
	thread->run();
 | 
			
		||||
 | 
			
		||||
	while( 1)
 | 
			
		||||
	{
 | 
			
		||||
		ret = looper->pollOnce(-1);
 | 
			
		||||
 | 
			
		||||
		if( ret == Looper::POLL_WAKE ) 
 | 
			
		||||
			printf("Looper::POLL_WAKE\n");
 | 
			
		||||
		if( ret == Looper::POLL_CALLBACK ) 
 | 
			
		||||
			printf("Looper::POLL_CALLBACK\n");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#if 0
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <utils/Looper.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
class MyThread : public Thread {
 | 
			
		||||
	    sp<Looper> mLooper;
 | 
			
		||||
		int mFd;
 | 
			
		||||
	public : 
 | 
			
		||||
		MyThread( sp<Looper> &looper , int fd ) : mLooper(looper),mFd(fd){}
 | 
			
		||||
		bool threadLoop() {
 | 
			
		||||
			sleep(3);
 | 
			
		||||
			write( mFd, "W", 1 );
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class MyCallback
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	void setCallback( sp<Looper> &looper, int fd, int events )
 | 
			
		||||
	{
 | 
			
		||||
		looper->addFd( fd, 0, events, callbackFunc, this );
 | 
			
		||||
	}
 | 
			
		||||
	static int callbackFunc(int fd, int events, void* data)
 | 
			
		||||
	{
 | 
			
		||||
		return ((MyCallback*)data)->handler( fd, events, data );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int handler(int fd, int events, void* data)
 | 
			
		||||
	{
 | 
			
		||||
		printf("MyCallback::handler(%d, %d, %p)\n", fd, events, data);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	int fds[2];
 | 
			
		||||
	pipe(fds);
 | 
			
		||||
	MyCallback callback;
 | 
			
		||||
	sp<Looper> looper = new Looper(true);
 | 
			
		||||
	sp<Thread> thread = new MyThread( looper, fds[1] );
 | 
			
		||||
 | 
			
		||||
	callback.setCallback( looper, fds[0], Looper::EVENT_INPUT );
 | 
			
		||||
	thread->run();
 | 
			
		||||
 | 
			
		||||
	while( 1)
 | 
			
		||||
	{
 | 
			
		||||
		ret = looper->pollOnce(-1);
 | 
			
		||||
 | 
			
		||||
		if( ret == Looper::POLL_WAKE ) 
 | 
			
		||||
			printf("Looper::POLL_WAKE\n");
 | 
			
		||||
		if( ret == Looper::POLL_CALLBACK ) 
 | 
			
		||||
			printf("Looper::POLL_CALLBACK\n");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#if 0
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <utils/Looper.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
class MyThread : public Thread {
 | 
			
		||||
	    sp<Looper> mLooper;
 | 
			
		||||
		int mFd;
 | 
			
		||||
	public : 
 | 
			
		||||
		MyThread( sp<Looper> &looper , int fd ) : mLooper(looper),mFd(fd){}
 | 
			
		||||
		bool threadLoop() {
 | 
			
		||||
			sleep(3);
 | 
			
		||||
			write( mFd, "W", 1 );
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int foo(int fd, int events, void* data)
 | 
			
		||||
{
 | 
			
		||||
	printf("foo(%d, %d, %p)\n", fd, events, data);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	int fds[2];
 | 
			
		||||
	pipe(fds);
 | 
			
		||||
	sp<Looper> looper = new Looper(true);
 | 
			
		||||
	sp<Thread> thread = new MyThread( looper, fds[1] );
 | 
			
		||||
 | 
			
		||||
	looper->addFd( fds[0], Looper::POLL_CALLBACK, Looper::EVENT_INPUT, foo, 0 );
 | 
			
		||||
	thread->run();
 | 
			
		||||
 | 
			
		||||
	while( 1)
 | 
			
		||||
	{
 | 
			
		||||
		ret = looper->pollOnce(-1);
 | 
			
		||||
 | 
			
		||||
		if( ret == Looper::POLL_WAKE ) 
 | 
			
		||||
			printf("Looper::POLL_WAKE\n");
 | 
			
		||||
		if( ret == Looper::POLL_CALLBACK ) 
 | 
			
		||||
			printf("Looper::POLL_CALLBACK\n");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#if 0
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <utils/Looper.h>
 | 
			
		||||
#include <utils/StrongPointer.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
class MyThread : public Thread {
 | 
			
		||||
	    sp<Looper> mLooper;
 | 
			
		||||
	public : 
 | 
			
		||||
		MyThread( sp<Looper> &looper ) : mLooper(looper){}
 | 
			
		||||
		bool threadLoop() {
 | 
			
		||||
			sleep(3);
 | 
			
		||||
			mLooper->wake();
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
};
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
	sp<Looper> looper = new Looper(true);
 | 
			
		||||
	sp<Thread> thread = new MyThread( looper );
 | 
			
		||||
	thread->run();
 | 
			
		||||
 | 
			
		||||
	while( 1)
 | 
			
		||||
	{
 | 
			
		||||
		ret = looper->pollOnce(-1);
 | 
			
		||||
 | 
			
		||||
		if( ret == Looper::POLL_WAKE ) 
 | 
			
		||||
			printf("Looper::POLL_WAKE\n");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								multimedia/03_day/test-vsync/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								multimedia/03_day/test-vsync/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES:= \
 | 
			
		||||
	vsync.cpp
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := \
 | 
			
		||||
	libcutils \
 | 
			
		||||
	libutils \
 | 
			
		||||
	libbinder \
 | 
			
		||||
    libui \
 | 
			
		||||
    libgui
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE:= test-vsync-events
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE_TAGS := tests
 | 
			
		||||
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
							
								
								
									
										68
									
								
								multimedia/03_day/test-vsync/vsync.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								multimedia/03_day/test-vsync/vsync.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
			
		||||
#include <gui/DisplayEventReceiver.h>
 | 
			
		||||
#include <utils/Looper.h>
 | 
			
		||||
#include <android/looper.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
int receiver(int fd, int events, void* data)
 | 
			
		||||
{
 | 
			
		||||
    DisplayEventReceiver* q = (DisplayEventReceiver*)data;
 | 
			
		||||
 | 
			
		||||
    ssize_t n;
 | 
			
		||||
    DisplayEventReceiver::Event buffer[1];
 | 
			
		||||
 | 
			
		||||
    static nsecs_t oldTimeStamp = 0;
 | 
			
		||||
 | 
			
		||||
    while ((n = q->getEvents(buffer, 1)) > 0) {
 | 
			
		||||
        for (int i=0 ; i<n ; i++) {
 | 
			
		||||
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
 | 
			
		||||
                printf("event vsync: count=%d\t", buffer[i].vsync.count);
 | 
			
		||||
            }
 | 
			
		||||
            if (oldTimeStamp) {
 | 
			
		||||
                float t = float(buffer[i].header.timestamp - oldTimeStamp) / s2ns(1);
 | 
			
		||||
                printf("%f ms (%f Hz)\n", t*1000, 1.0/t);
 | 
			
		||||
            }
 | 
			
		||||
            oldTimeStamp = buffer[i].header.timestamp;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (n<0) {
 | 
			
		||||
        printf("error reading events (%s)\n", strerror(-n));
 | 
			
		||||
    }
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv)
 | 
			
		||||
{
 | 
			
		||||
    DisplayEventReceiver myDisplayEvent;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    sp<Looper> loop = new Looper(false);
 | 
			
		||||
    loop->addFd(myDisplayEvent.getFd(), 0, ALOOPER_EVENT_INPUT, receiver,
 | 
			
		||||
            &myDisplayEvent);
 | 
			
		||||
 | 
			
		||||
    myDisplayEvent.setVsyncRate(1);
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        //printf("about to poll...\n");
 | 
			
		||||
        int32_t ret = loop->pollOnce(-1);
 | 
			
		||||
        switch (ret) {
 | 
			
		||||
            case ALOOPER_POLL_WAKE:
 | 
			
		||||
                //("ALOOPER_POLL_WAKE\n");
 | 
			
		||||
                break;
 | 
			
		||||
            case ALOOPER_POLL_CALLBACK:
 | 
			
		||||
                //("ALOOPER_POLL_CALLBACK\n");
 | 
			
		||||
                break;
 | 
			
		||||
            case ALOOPER_POLL_TIMEOUT:
 | 
			
		||||
                printf("ALOOPER_POLL_TIMEOUT\n");
 | 
			
		||||
                break;
 | 
			
		||||
            case ALOOPER_POLL_ERROR:
 | 
			
		||||
                printf("ALOOPER_POLL_TIMEOUT\n");
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                printf("ugh? poll returned %d\n", ret);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    } while (1);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								multimedia/04_day/test-openmax/ATMParser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								multimedia/04_day/test-openmax/ATMParser.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//#define LOG_NDEBUG 0
 | 
			
		||||
#define LOG_TAG "ATMParser"
 | 
			
		||||
 | 
			
		||||
#include "ATMParser.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <utils/Log.h>
 | 
			
		||||
 | 
			
		||||
#define LOGD ALOGD
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace anatomy {
 | 
			
		||||
 | 
			
		||||
static char pszSource[] = "\
 | 
			
		||||
M9a1X1M13B1M55/1M9B1Z1a1M11B1W1a1M54/1M8Z1r1X2M10@1r1S1;1Z1M53/1M9Z1X1r1M3\
 | 
			
		||||
W2B1W2M3r1X2M6r1X1M12Z1i1X1M4X1;1X1M24/1M10B1X1S2X7S2X1W1M7.1 1Z1M11X1 2X1M3:1 2\
 | 
			
		||||
M6@1M17/1M9B1S2X2a1S1a1S1a1S1a1S3a1W1M7 1r1:1i1M3S1 2M5 1X1M5 1M4:1 2,1M16/1M8X5\
 | 
			
		||||
S1X1S2a1S2X6a1M6 2S1 1S1M1B1 1W1,1 1M4 1S1M5 1M3Z1 1M2 1S1M15/1M6@1X3Z1B5S2a1B5a\
 | 
			
		||||
1X2S1M5 1S1M1 1X1M1:1 1;1i1 1M4 1S1M5 1M3i1 1M2.1,1M15/1M6X1S2X1@1M5a1X1B1M5B1S2\
 | 
			
		||||
X1a1M4 1W1M1 1Z1M1X1 1M2i1M4 1Z1M5 1M3a1 1M2 1X1M1Z1 1a1M11/1M5X2S1a1S1Z6S2a1Z1B\
 | 
			
		||||
1Z4S1a1S1X1B1M2.1 2Z1 2W1M1 3;1M2X1 4M2 5M2.1 3M2B1 2M11/1M4W1X1S1a1S1a1S2X3S2a1\
 | 
			
		||||
S2X3S2a3S1X1M2B1Z1B1M1B2M3B1@1M3@1Z1@2W1M2W1Z1@1W1@1M3W1B1M3a1 1W1M11/1M2@1B1S2a\
 | 
			
		||||
1S1a1S1a1S3a1S1a1S1a1S1a1S1a1S1a1S1a1S1a1X1Z1M35B1Z1M12/1M1B1r1X2a1S1X20S2a1r1X2\
 | 
			
		||||
Z1M46/1Z1S2a1S2Z1M6@1M5@1M1@1M5@1S2X1a1S1r1B1M45/1X1Z1S1Z1X1S1Z1M21S1a1X1a1S1X2M\
 | 
			
		||||
45/1B1S1a2S2a1X19S1X1a2S1a2X1a1M45/1M1B1r1S1X1a2S3X1S1X1S9X1S6a1X1a1X2@1M45/1M2B\
 | 
			
		||||
1X3a4Z1a18S1r1X1Z1M47/1M4W1X1S1a8Z1a12S1X1Z1M23a1X1M24/1M5S1X1S1a6Z1a13S1X1M4B1W\
 | 
			
		||||
1M11W1B1M5 2M5Z1X1M17/1M5@1X1a1S1a8Z1a7Z1a2X1Z1M2X1 3X1M2 2,1 2M2 4M2r1 4:1M2 4M\
 | 
			
		||||
2 6W2 2S1i1 1.1/1M6Z1X1a10Z1a8X2M3a1:1M1 2M2@1 1i1M1 1M2.1W1r1 1M4 1:1M3B1 1M2 1\
 | 
			
		||||
i1M1i1 1M1 1M1 1X1M1X1 1M2 1M1/1M7a1X1a2Z1a13Z1S1X1W1M3B1 2S1X1M3 1M2 1M2i1 1;1i\
 | 
			
		||||
1M4.1r1M1@1M1X1 1M2i1 1M1X1,1M1 1M1,1r1M2 1S2i1M1/1M8Z1X1a5S1a1S1a6Z1S1X1W1M4 2Z\
 | 
			
		||||
2 2M2 1Z1M1 1W1B1 2M1 2r1M2 2a1 1M1@1 1W1M1 1S1M1r1 1M1 1M1 1i1M3 2M2/1M9X1r1S1a\
 | 
			
		||||
1Z1S3a1S1a1S1a3X3@1M4X1 2i1 1.1M1.1 2r1 2M1 2.1 2W1M2r1 2a1M2X1 2i1M2 2,1 1,1 2M\
 | 
			
		||||
3.1 1M2/1M9X1S1X3S1X9S1a1X1Z1M46B1 2Z1M2/1M9X1S1Z1S1X1M3@3M2X1a2S1r1B1M46W1 1.1M\
 | 
			
		||||
3/1M9@1a1Z3M8W1a1Z1a1Z1M53";
 | 
			
		||||
 | 
			
		||||
ATMParser::ATMParser()
 | 
			
		||||
    : mOffset(0),
 | 
			
		||||
    mLength(sizeof(pszSource)) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ATMParser::read(void* buffer, int* length) {
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
	if ( mOffset < mLength )
 | 
			
		||||
	{
 | 
			
		||||
		for ( i = mOffset+1; i < mLength; i++ )
 | 
			
		||||
		{
 | 
			
		||||
			if ( !isdigit(pszSource[i]) )
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		*length = i - mOffset + 1;
 | 
			
		||||
		memcpy(buffer, &pszSource[mOffset], *length);
 | 
			
		||||
		mOffset = i;
 | 
			
		||||
		LOGD("mOffset : %d , mLength : %d, *length : %d", mOffset, mLength, *length);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								multimedia/04_day/test-openmax/ATMParser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								multimedia/04_day/test-openmax/ATMParser.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef ATM_PARSER_H_
 | 
			
		||||
#define ATM_PARSER_H_
 | 
			
		||||
 | 
			
		||||
namespace anatomy {
 | 
			
		||||
 | 
			
		||||
class ATMParser {
 | 
			
		||||
public:
 | 
			
		||||
	ATMParser();
 | 
			
		||||
	virtual ~ATMParser(){}
 | 
			
		||||
	void read(void* buffer,int* length);
 | 
			
		||||
private:
 | 
			
		||||
	int mOffset;
 | 
			
		||||
    int mLength;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace anatomy
 | 
			
		||||
 | 
			
		||||
#endif  // ATM_PARSER_H_
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										263
									
								
								multimedia/04_day/test-openmax/AnatomyOMXClient.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								multimedia/04_day/test-openmax/AnatomyOMXClient.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,263 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//#define LOG_NDEBUG 0
 | 
			
		||||
#define LOG_TAG "AnatomyOMXClient"
 | 
			
		||||
 | 
			
		||||
#include "AnatomyOMXClient.h"
 | 
			
		||||
#include "AnatomyOMXCore.h"
 | 
			
		||||
 | 
			
		||||
#include <media/stagefright/foundation/ADebug.h>
 | 
			
		||||
#include <utils/Log.h>
 | 
			
		||||
 | 
			
		||||
#define LOGW ALOGW
 | 
			
		||||
#define LOGD ALOGD
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace anatomy {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
static void InitOMXParams(T *params) {
 | 
			
		||||
    params->nSize = sizeof(T);
 | 
			
		||||
    params->nVersion.s.nVersionMajor = 1;
 | 
			
		||||
    params->nVersion.s.nVersionMinor = 0;
 | 
			
		||||
    params->nVersion.s.nRevision = 0;
 | 
			
		||||
    params->nVersion.s.nStep = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXClient::prepare() {
 | 
			
		||||
	init();
 | 
			
		||||
 | 
			
		||||
	changeState(OMX_StateIdle);
 | 
			
		||||
	allocateBuffers();
 | 
			
		||||
	sleep(1);
 | 
			
		||||
 | 
			
		||||
	changeState(OMX_StateExecuting);
 | 
			
		||||
	sleep(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXClient::stop() {
 | 
			
		||||
	changeState(OMX_StateIdle);
 | 
			
		||||
	sleep(1);
 | 
			
		||||
	changeState(OMX_StateLoaded);
 | 
			
		||||
	freeBuffers();
 | 
			
		||||
	sleep(1);
 | 
			
		||||
 | 
			
		||||
	deinit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXClient::init() {
 | 
			
		||||
	OMX_HANDLETYPE handle = NULL;
 | 
			
		||||
	char componentName[256];
 | 
			
		||||
	OMX_Init();
 | 
			
		||||
	OMX_ComponentNameEnum(componentName, 256, 0);
 | 
			
		||||
	OMX_GetHandle(&handle, componentName, this, &AnatomyOMXClient::kCallbacks);
 | 
			
		||||
	CHECK(handle != NULL);
 | 
			
		||||
 | 
			
		||||
	mComponentHandle = handle;
 | 
			
		||||
}
 | 
			
		||||
void AnatomyOMXClient::changeState(OMX_STATETYPE state) {
 | 
			
		||||
	OMX_SendCommand(mComponentHandle, OMX_CommandStateSet, state, NULL);
 | 
			
		||||
}
 | 
			
		||||
void AnatomyOMXClient::allocateBuffers() {
 | 
			
		||||
    OMX_PARAM_PORTDEFINITIONTYPE def;
 | 
			
		||||
    InitOMXParams(&def);
 | 
			
		||||
    def.nPortIndex = kPortIndexInput;
 | 
			
		||||
 | 
			
		||||
    OMX_GetParameter(mComponentHandle, OMX_IndexParamPortDefinition, &def);
 | 
			
		||||
 | 
			
		||||
	OMX_BUFFERHEADERTYPE *pInputHeader;
 | 
			
		||||
	for(uint i = 0; i < def.nBufferCountActual; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		OMX_AllocateBuffer(mComponentHandle, &pInputHeader, 0, this, def.nBufferSize);
 | 
			
		||||
		addOMXBufferInfo(kPortIndexInput, pInputHeader);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    InitOMXParams(&def);
 | 
			
		||||
    def.nPortIndex = kPortIndexOutput;
 | 
			
		||||
 | 
			
		||||
    OMX_GetParameter(mComponentHandle, OMX_IndexParamPortDefinition, &def);
 | 
			
		||||
	OMX_BUFFERHEADERTYPE *pOutputHeader;
 | 
			
		||||
	for(uint i = 0; i < def.nBufferCountActual; i++ )
 | 
			
		||||
	{
 | 
			
		||||
			OMX_AllocateBuffer(mComponentHandle, &pOutputHeader, 1, this, def.nBufferSize);
 | 
			
		||||
			addOMXBufferInfo(kPortIndexOutput, pOutputHeader);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXClient::excute() {
 | 
			
		||||
	int nSize = 0;
 | 
			
		||||
	OMX_BUFFERHEADERTYPE *pInputHeader = NULL;
 | 
			
		||||
	OMX_BUFFERHEADERTYPE *pOutputHeader = NULL;
 | 
			
		||||
 | 
			
		||||
	for(size_t i = 0; i < mBufferInfo.size(); i++) {
 | 
			
		||||
		if( mBufferInfo[i].mPortIndex == kPortIndexInput ) {
 | 
			
		||||
			pInputHeader = mBufferInfo[i].mBufferHeader;
 | 
			
		||||
			read((char*)(pInputHeader->pBuffer), &nSize);
 | 
			
		||||
			OMX_EmptyThisBuffer(mComponentHandle, pInputHeader);
 | 
			
		||||
			removeOMXBufferInfo(kPortIndexInput, mBufferInfo[i].mBufferHeader);
 | 
			
		||||
		}
 | 
			
		||||
		if( mBufferInfo[i].mPortIndex == kPortIndexOutput ) {
 | 
			
		||||
			pOutputHeader = mBufferInfo[i].mBufferHeader;
 | 
			
		||||
			OMX_FillThisBuffer(mComponentHandle, pOutputHeader);
 | 
			
		||||
			removeOMXBufferInfo(kPortIndexOutput, mBufferInfo[i].mBufferHeader);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
void AnatomyOMXClient::deinit() {
 | 
			
		||||
	OMX_FreeHandle(mComponentHandle);
 | 
			
		||||
	OMX_Deinit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXClient::addOMXBufferInfo(
 | 
			
		||||
		OMX_U32 portIndex, OMX_BUFFERHEADERTYPE* header) {
 | 
			
		||||
    OMXClientBufferInfo info;
 | 
			
		||||
    info.mPortIndex = portIndex;
 | 
			
		||||
    info.mBufferHeader = header;
 | 
			
		||||
    mBufferInfo.push(info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXClient::removeOMXBufferInfo(
 | 
			
		||||
        OMX_U32 portIndex, OMX_BUFFERHEADERTYPE* header) {
 | 
			
		||||
    bool found = false;
 | 
			
		||||
    for (size_t i = 0; i < mBufferInfo.size(); i++) {
 | 
			
		||||
        if (mBufferInfo[i].mPortIndex == portIndex
 | 
			
		||||
            && mBufferInfo[i].mBufferHeader == header) {
 | 
			
		||||
            found = true;
 | 
			
		||||
            mBufferInfo.removeItemsAt(i);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!found) {
 | 
			
		||||
        LOGW("Attempt to remove an active buffer we know nothing about...");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXClient::freeBuffers() {
 | 
			
		||||
    LOGD("=============================================");
 | 
			
		||||
    for (size_t i = mBufferInfo.size(); i--;) {
 | 
			
		||||
		int port_index= mBufferInfo[i].mPortIndex;
 | 
			
		||||
		OMX_BUFFERHEADERTYPE *header = mBufferInfo[i].mBufferHeader;
 | 
			
		||||
		LOGD("mBufferInfo[%d] mPortIndex : %d, mBufferHeader %p",i, port_index, header);
 | 
			
		||||
    	removeOMXBufferInfo(port_index, header);
 | 
			
		||||
    	OMX_FreeBuffer(mComponentHandle, port_index, header);
 | 
			
		||||
    }
 | 
			
		||||
    LOGD("=============================================");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// static
 | 
			
		||||
OMX_CALLBACKTYPE AnatomyOMXClient::kCallbacks = {
 | 
			
		||||
    &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
OMX_ERRORTYPE AnatomyOMXClient::OnFillBufferDone(
 | 
			
		||||
        OMX_IN OMX_HANDLETYPE hComponent,
 | 
			
		||||
        OMX_IN OMX_PTR pAppData,
 | 
			
		||||
        OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
 | 
			
		||||
 | 
			
		||||
	AnatomyOMXClient* omxclient = reinterpret_cast<AnatomyOMXClient*>(pAppData);
 | 
			
		||||
	CHECK( NULL != omxclient);
 | 
			
		||||
	CHECK( NULL != pBuffer );
 | 
			
		||||
 | 
			
		||||
	omxclient->addOMXBufferInfo(kPortIndexOutput, pBuffer);
 | 
			
		||||
 | 
			
		||||
	if( pBuffer->nFlags & OMX_BUFFERFLAG_EOS || omxclient->getStatus() == 1 )
 | 
			
		||||
	{
 | 
			
		||||
		omxclient->signalEOF();
 | 
			
		||||
		omxclient->setStatus(1);
 | 
			
		||||
		return OMX_ErrorNone;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( pBuffer->nSize > 0 )
 | 
			
		||||
	{
 | 
			
		||||
		omxclient->render(pBuffer->pBuffer, pBuffer->nSize);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	OMX_FillThisBuffer(hComponent, pBuffer);
 | 
			
		||||
	omxclient->removeOMXBufferInfo(kPortIndexOutput, pBuffer);
 | 
			
		||||
	return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_ERRORTYPE AnatomyOMXClient::OnEmptyBufferDone(
 | 
			
		||||
	    OMX_IN OMX_HANDLETYPE hComponent,
 | 
			
		||||
	    OMX_IN OMX_PTR pAppData,
 | 
			
		||||
	    OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
 | 
			
		||||
 | 
			
		||||
	AnatomyOMXClient* omxclient = reinterpret_cast<AnatomyOMXClient*>(pAppData);
 | 
			
		||||
	int nSize = 0;
 | 
			
		||||
	omxclient->addOMXBufferInfo(kPortIndexInput, pBuffer);
 | 
			
		||||
	CHECK(NULL != omxclient);
 | 
			
		||||
	CHECK( NULL != pBuffer );
 | 
			
		||||
 | 
			
		||||
	if( pBuffer->nFlags & OMX_BUFFERFLAG_EOS )
 | 
			
		||||
	{
 | 
			
		||||
		return OMX_ErrorNone;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	omxclient->read(pBuffer->pBuffer, &nSize);
 | 
			
		||||
 | 
			
		||||
	if( nSize <= 0 ) {
 | 
			
		||||
		pBuffer->nSize = 0;
 | 
			
		||||
		pBuffer->nFlags |= OMX_BUFFERFLAG_EOS;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		pBuffer->nSize = nSize;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	OMX_EmptyThisBuffer(hComponent, pBuffer);
 | 
			
		||||
	omxclient->removeOMXBufferInfo(kPortIndexInput, pBuffer);
 | 
			
		||||
	return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_ERRORTYPE AnatomyOMXClient::OnEvent(
 | 
			
		||||
	    OMX_IN OMX_HANDLETYPE hComponent,
 | 
			
		||||
	    OMX_IN OMX_PTR pAppData,
 | 
			
		||||
	    OMX_IN OMX_EVENTTYPE eEvent,
 | 
			
		||||
	    OMX_IN OMX_U32 nData1,
 | 
			
		||||
	    OMX_IN OMX_U32 nData2,
 | 
			
		||||
	    OMX_IN OMX_PTR pEventData) {
 | 
			
		||||
	AnatomyOMXClient* omxclient = reinterpret_cast<AnatomyOMXClient*>(pAppData);
 | 
			
		||||
	switch(eEvent)
 | 
			
		||||
	{
 | 
			
		||||
		case OMX_EventCmdComplete:
 | 
			
		||||
			if (OMX_CommandStateSet == nData1)
 | 
			
		||||
            {
 | 
			
		||||
           		switch (nData2)
 | 
			
		||||
                {
 | 
			
		||||
                    case OMX_StateLoaded:
 | 
			
		||||
						omxclient->signalLoadedState();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case OMX_StateIdle:
 | 
			
		||||
						omxclient->signalIdleState();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case OMX_StateExecuting:
 | 
			
		||||
						omxclient->signalExcutingState();
 | 
			
		||||
                        break;
 | 
			
		||||
           		}
 | 
			
		||||
            }
 | 
			
		||||
			break;
 | 
			
		||||
		case OMX_EventError:
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										113
									
								
								multimedia/04_day/test-openmax/AnatomyOMXClient.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								multimedia/04_day/test-openmax/AnatomyOMXClient.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,113 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef ANATOMY_OMXCLIENT_H_
 | 
			
		||||
#define ANATOMY_OMXCLIENT_H_
 | 
			
		||||
 | 
			
		||||
#include "ATMParser.h"
 | 
			
		||||
#include "StdoutRenderer.h"
 | 
			
		||||
#include "OMX_Types.h"
 | 
			
		||||
#include "OMX_Core.h"
 | 
			
		||||
#include "OMX_Component.h"
 | 
			
		||||
 | 
			
		||||
#include <utils/threads.h>
 | 
			
		||||
#include <utils/Vector.h>
 | 
			
		||||
 | 
			
		||||
namespace anatomy {
 | 
			
		||||
 | 
			
		||||
struct AnatomyOMXClient {
 | 
			
		||||
public:
 | 
			
		||||
	AnatomyOMXClient(){}
 | 
			
		||||
	virtual ~AnatomyOMXClient(){}
 | 
			
		||||
	void prepare();
 | 
			
		||||
	void start() { excute(); waitEOF();}
 | 
			
		||||
	void stop();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void waitEOF() { mEOSCondition.wait(mLock); }
 | 
			
		||||
	void changeState(OMX_STATETYPE state);
 | 
			
		||||
	void allocateBuffers();
 | 
			
		||||
	void freeBuffers();
 | 
			
		||||
	void init();
 | 
			
		||||
	void deinit();
 | 
			
		||||
	void excute();
 | 
			
		||||
	void waitIdleState() { mIdleCondition.wait(mLock); }
 | 
			
		||||
	void waitExcutingState() { mExcutingCondition.wait(mLock);}
 | 
			
		||||
	void waitLoadedState() { mLoadedCondition.wait(mLock);}
 | 
			
		||||
 | 
			
		||||
	void render(void* buffer,int length){mRenderer.render(buffer, length);}
 | 
			
		||||
	void read(void* buffer,int* length){mParser.read(buffer, length);}
 | 
			
		||||
 | 
			
		||||
	void signalEOF() { mEOSCondition.signal(); }
 | 
			
		||||
	void signalIdleState() { mIdleCondition.signal(); }
 | 
			
		||||
	void signalExcutingState() { mExcutingCondition.signal(); }
 | 
			
		||||
	void signalLoadedState() { mLoadedCondition.signal(); }
 | 
			
		||||
 | 
			
		||||
	void addOMXBufferInfo(OMX_U32 portIndex, OMX_BUFFERHEADERTYPE* header);
 | 
			
		||||
	void removeOMXBufferInfo(OMX_U32 portIndex, OMX_BUFFERHEADERTYPE* header);
 | 
			
		||||
 | 
			
		||||
	void setStatus(int status){ mStatus = status; }
 | 
			
		||||
	int getStatus(){ return mStatus; }
 | 
			
		||||
 | 
			
		||||
	static OMX_CALLBACKTYPE kCallbacks;
 | 
			
		||||
 | 
			
		||||
	android::Condition mEOSCondition;
 | 
			
		||||
	android::Condition mExcutingCondition;
 | 
			
		||||
	android::Condition mIdleCondition;
 | 
			
		||||
	android::Condition mLoadedCondition;
 | 
			
		||||
	android::Mutex mLock;
 | 
			
		||||
	ATMParser mParser;
 | 
			
		||||
	StdoutRenderer mRenderer;
 | 
			
		||||
	OMX_HANDLETYPE mComponentHandle;
 | 
			
		||||
	int mStatus;
 | 
			
		||||
 | 
			
		||||
    enum {
 | 
			
		||||
        kPortIndexInput  = 0,
 | 
			
		||||
        kPortIndexOutput = 1
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
	 struct OMXClientBufferInfo {
 | 
			
		||||
        OMX_U32 mPortIndex;
 | 
			
		||||
        OMX_BUFFERHEADERTYPE* mBufferHeader;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    android::Vector<OMXClientBufferInfo> mBufferInfo;
 | 
			
		||||
 | 
			
		||||
	static OMX_ERRORTYPE OnEvent(
 | 
			
		||||
	    OMX_IN OMX_HANDLETYPE hComponent,
 | 
			
		||||
	    OMX_IN OMX_PTR pAppData,
 | 
			
		||||
	    OMX_IN OMX_EVENTTYPE eEvent,
 | 
			
		||||
	    OMX_IN OMX_U32 nData1,
 | 
			
		||||
	    OMX_IN OMX_U32 nData2,
 | 
			
		||||
	    OMX_IN OMX_PTR pEventData);
 | 
			
		||||
 | 
			
		||||
	static OMX_ERRORTYPE OnEmptyBufferDone(
 | 
			
		||||
	    OMX_IN OMX_HANDLETYPE hComponent,
 | 
			
		||||
	    OMX_IN OMX_PTR pAppData,
 | 
			
		||||
	    OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	static OMX_ERRORTYPE OnFillBufferDone(
 | 
			
		||||
	    OMX_IN OMX_HANDLETYPE hComponent,
 | 
			
		||||
	    OMX_IN OMX_PTR pAppData,
 | 
			
		||||
	    OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace anatomy
 | 
			
		||||
 | 
			
		||||
#endif  // ANATOMY_OMXCLIENT_H_
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										161
									
								
								multimedia/04_day/test-openmax/AnatomyOMXComponent.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								multimedia/04_day/test-openmax/AnatomyOMXComponent.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,161 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//#define LOG_NDEBUG 0
 | 
			
		||||
#define LOG_TAG "AnatomyOMXComponent"
 | 
			
		||||
#include <utils/Log.h>
 | 
			
		||||
 | 
			
		||||
#include "AnatomyOMXComponent.h"
 | 
			
		||||
 | 
			
		||||
#include <media/stagefright/foundation/ADebug.h>
 | 
			
		||||
#include <media/stagefright/MediaDefs.h>
 | 
			
		||||
#include <media/stagefright/MediaErrors.h>
 | 
			
		||||
#include <media/IOMX.h>
 | 
			
		||||
 | 
			
		||||
#define LOGD ALOGD
 | 
			
		||||
 | 
			
		||||
namespace android {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
static void InitOMXParams(T *params) {
 | 
			
		||||
    params->nSize = sizeof(T);
 | 
			
		||||
    params->nVersion.s.nVersionMajor = 1;
 | 
			
		||||
    params->nVersion.s.nVersionMinor = 0;
 | 
			
		||||
    params->nVersion.s.nRevision = 0;
 | 
			
		||||
    params->nVersion.s.nStep = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AnatomyOMXComponent::AnatomyOMXComponent(
 | 
			
		||||
        const char *name,
 | 
			
		||||
        const OMX_CALLBACKTYPE *callbacks,
 | 
			
		||||
        OMX_PTR appData,
 | 
			
		||||
        OMX_COMPONENTTYPE **component)
 | 
			
		||||
    : SimpleSoftOMXComponent(name, callbacks, appData, component) {
 | 
			
		||||
    LOGD("anatomy component created");
 | 
			
		||||
    initPorts();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AnatomyOMXComponent::~AnatomyOMXComponent() {
 | 
			
		||||
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
 | 
			
		||||
    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
 | 
			
		||||
    CHECK(outQueue.empty());
 | 
			
		||||
    CHECK(inQueue.empty());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXComponent::initPorts() {
 | 
			
		||||
    OMX_PARAM_PORTDEFINITIONTYPE def;
 | 
			
		||||
    InitOMXParams(&def);
 | 
			
		||||
 | 
			
		||||
    def.nPortIndex = kInputPortIndex;
 | 
			
		||||
    def.eDir = OMX_DirInput;
 | 
			
		||||
    def.nBufferCountMin = kNumInputBuffers;
 | 
			
		||||
    def.nBufferCountActual = def.nBufferCountMin;
 | 
			
		||||
    def.nBufferSize = 2048;
 | 
			
		||||
    def.bEnabled = OMX_TRUE;
 | 
			
		||||
    def.bPopulated = OMX_FALSE;
 | 
			
		||||
    def.eDomain = OMX_PortDomainOther;
 | 
			
		||||
    def.bBuffersContiguous = OMX_FALSE;
 | 
			
		||||
    def.nBufferAlignment = 1;//TODO
 | 
			
		||||
 | 
			
		||||
    def.format.other.eFormat = OMX_OTHER_FormatVendorStartUnused; //TODO
 | 
			
		||||
 | 
			
		||||
    addPort(def);
 | 
			
		||||
 | 
			
		||||
    def.nPortIndex = kOutputPortIndex;
 | 
			
		||||
    def.eDir = OMX_DirOutput;
 | 
			
		||||
    def.nBufferCountMin = kNumOutputBuffers;
 | 
			
		||||
    def.nBufferCountActual = def.nBufferCountMin;
 | 
			
		||||
	def.nBufferSize = 2048;
 | 
			
		||||
    def.bEnabled = OMX_TRUE;
 | 
			
		||||
    def.bPopulated = OMX_FALSE;
 | 
			
		||||
    def.eDomain = OMX_PortDomainOther;
 | 
			
		||||
    def.bBuffersContiguous = OMX_FALSE;
 | 
			
		||||
    def.nBufferAlignment = 1;
 | 
			
		||||
 | 
			
		||||
    def.format.other.eFormat = OMX_OTHER_FormatVendorStartUnused; //TODO
 | 
			
		||||
 | 
			
		||||
    addPort(def);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AnatomyOMXComponent::onQueueFilled(OMX_U32 portIndex) {
 | 
			
		||||
    List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
 | 
			
		||||
    List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
 | 
			
		||||
 | 
			
		||||
	LOGD("onQueueFilled called");
 | 
			
		||||
	while (!inQueue.empty() && !outQueue.empty()) {
 | 
			
		||||
        BufferInfo *inInfo = *inQueue.begin();
 | 
			
		||||
        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
 | 
			
		||||
 | 
			
		||||
        BufferInfo *outInfo = *outQueue.begin();
 | 
			
		||||
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
 | 
			
		||||
            inQueue.erase(inQueue.begin());
 | 
			
		||||
            inInfo->mOwnedByUs = false;
 | 
			
		||||
            notifyEmptyBufferDone(inHeader);
 | 
			
		||||
 | 
			
		||||
            outHeader->nFilledLen = 0;
 | 
			
		||||
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
 | 
			
		||||
 | 
			
		||||
            outQueue.erase(outQueue.begin());
 | 
			
		||||
            outInfo->mOwnedByUs = false;
 | 
			
		||||
            notifyFillBufferDone(outHeader);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		OMX_U32 decoded_size;
 | 
			
		||||
		decodeBuffer(outHeader->pBuffer, inHeader->pBuffer, inHeader->nSize, &decoded_size);
 | 
			
		||||
		usleep(10000);
 | 
			
		||||
		outHeader->nSize = decoded_size;
 | 
			
		||||
 | 
			
		||||
        inQueue.erase(inQueue.begin());
 | 
			
		||||
        inInfo->mOwnedByUs = false;
 | 
			
		||||
		inInfo = NULL;
 | 
			
		||||
        notifyEmptyBufferDone(inHeader);
 | 
			
		||||
		inHeader = NULL;
 | 
			
		||||
 | 
			
		||||
        outQueue.erase(outQueue.begin());
 | 
			
		||||
        outInfo->mOwnedByUs = false;
 | 
			
		||||
		outInfo = NULL;
 | 
			
		||||
        notifyFillBufferDone(outHeader);
 | 
			
		||||
		outHeader = NULL;
 | 
			
		||||
 	  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
void AnatomyOMXComponent::decodeBuffer(OMX_U8* dst, OMX_U8* src, OMX_U32 size, OMX_U32* decoded_size) {
 | 
			
		||||
	char ascii;
 | 
			
		||||
	char* ascii_length;
 | 
			
		||||
	int length = 0;
 | 
			
		||||
	ascii = src[0];
 | 
			
		||||
	length = atoi((char *)&src[1]);
 | 
			
		||||
	LOGD("decode value %c, %d",ascii,length);
 | 
			
		||||
	*decoded_size = length;
 | 
			
		||||
	for(int i = 0; i < length; i++)
 | 
			
		||||
	{
 | 
			
		||||
		dst[i] = ascii;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace android
 | 
			
		||||
android::SoftOMXComponent *createSoftOMXComponent(
 | 
			
		||||
        const char *name, const OMX_CALLBACKTYPE *callbacks,
 | 
			
		||||
        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
 | 
			
		||||
    return new android::AnatomyOMXComponent(name, callbacks, appData, component);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								multimedia/04_day/test-openmax/AnatomyOMXComponent.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								multimedia/04_day/test-openmax/AnatomyOMXComponent.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef ANATOMY_OMX_COMPONENT_H_
 | 
			
		||||
 | 
			
		||||
#define ANATOMY_OMX_COMPONENT_H_
 | 
			
		||||
 | 
			
		||||
#include <include/SimpleSoftOMXComponent.h>
 | 
			
		||||
#include <utils/KeyedVector.h>
 | 
			
		||||
 | 
			
		||||
namespace android {
 | 
			
		||||
 | 
			
		||||
struct AnatomyOMXComponent : public SimpleSoftOMXComponent {
 | 
			
		||||
    AnatomyOMXComponent(const char *name,
 | 
			
		||||
            const OMX_CALLBACKTYPE *callbacks,
 | 
			
		||||
            OMX_PTR appData,
 | 
			
		||||
            OMX_COMPONENTTYPE **component);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual ~AnatomyOMXComponent();
 | 
			
		||||
    virtual void onQueueFilled(OMX_U32 portIndex);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	 enum {
 | 
			
		||||
        kInputPortIndex   = 0,
 | 
			
		||||
        kOutputPortIndex  = 1,
 | 
			
		||||
        kNumInputBuffers  = 2,
 | 
			
		||||
        kNumOutputBuffers = 5,
 | 
			
		||||
    };
 | 
			
		||||
    void initPorts();
 | 
			
		||||
	void decodeBuffer(OMX_U8* dst, OMX_U8* src, OMX_U32 size, OMX_U32* decoded_size);
 | 
			
		||||
 | 
			
		||||
    DISALLOW_EVIL_CONSTRUCTORS(AnatomyOMXComponent);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace android
 | 
			
		||||
 | 
			
		||||
#endif  // ANATOMY_OMX_COMPONENT_H_
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										159
									
								
								multimedia/04_day/test-openmax/AnatomyOMXCore.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								multimedia/04_day/test-openmax/AnatomyOMXCore.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,159 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "AnatomyOMXCore.h"
 | 
			
		||||
 | 
			
		||||
#include <utils/Log.h>
 | 
			
		||||
 | 
			
		||||
#include <include/SimpleSoftOMXComponent.h>
 | 
			
		||||
 | 
			
		||||
//#include <media/stagefright/foundation/ADebug.h>
 | 
			
		||||
//#include <media/stagefright/foundation/AString.h>
 | 
			
		||||
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
#define LOGD ALOGD
 | 
			
		||||
#define LOGV ALOGV
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
    const char *mName;
 | 
			
		||||
    const char *mLibName;
 | 
			
		||||
    const char *mRole;
 | 
			
		||||
 | 
			
		||||
} kComponentInfo[] = {
 | 
			
		||||
	{"OMX.anatomy.atm.decoder", "libanatomy_atmdec.so", "ascii_decoder.atm" },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_Init()
 | 
			
		||||
{
 | 
			
		||||
	return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_Deinit()
 | 
			
		||||
{
 | 
			
		||||
	return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_GetHandle(OMX_OUT OMX_HANDLETYPE*     handle,
 | 
			
		||||
              OMX_IN OMX_STRING    componentName,
 | 
			
		||||
              OMX_IN OMX_PTR             appData,
 | 
			
		||||
              OMX_IN OMX_CALLBACKTYPE* callBacks)
 | 
			
		||||
{
 | 
			
		||||
    if (strcmp(componentName, kComponentInfo[0].mName) == 0) {
 | 
			
		||||
		AString libName;
 | 
			
		||||
        libName.append(kComponentInfo[0].mLibName);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void *libHandle = dlopen(libName.c_str(), RTLD_NOW);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(
 | 
			
		||||
                const char *, const OMX_CALLBACKTYPE *,
 | 
			
		||||
                OMX_PTR, OMX_COMPONENTTYPE **);
 | 
			
		||||
 | 
			
		||||
        CreateSoftOMXComponentFunc createSoftOMXComponent =
 | 
			
		||||
            (CreateSoftOMXComponentFunc)dlsym(
 | 
			
		||||
                    libHandle,
 | 
			
		||||
                    "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"
 | 
			
		||||
                    "PvPP17OMX_COMPONENTTYPE");
 | 
			
		||||
 | 
			
		||||
        sp<SoftOMXComponent> codec =
 | 
			
		||||
            (*createSoftOMXComponent)(componentName, callBacks, appData, (OMX_COMPONENTTYPE **)handle);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        codec->initCheck();
 | 
			
		||||
		codec->incStrong(handle);
 | 
			
		||||
        codec->setLibHandle(libHandle);
 | 
			
		||||
 | 
			
		||||
        return OMX_ErrorNone;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return OMX_ErrorInvalidComponentName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp)
 | 
			
		||||
{
 | 
			
		||||
	 SoftOMXComponent *me =
 | 
			
		||||
        (SoftOMXComponent *)
 | 
			
		||||
            ((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate;
 | 
			
		||||
 | 
			
		||||
    me->prepareForDestruction();
 | 
			
		||||
 | 
			
		||||
    void *libHandle = me->libHandle();
 | 
			
		||||
 | 
			
		||||
    me = NULL;
 | 
			
		||||
 | 
			
		||||
    dlclose(libHandle);
 | 
			
		||||
    libHandle = NULL;
 | 
			
		||||
 | 
			
		||||
    return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName,
 | 
			
		||||
                      OMX_IN  OMX_U32          nameLen,
 | 
			
		||||
                      OMX_IN  OMX_U32            index)
 | 
			
		||||
{
 | 
			
		||||
	if (index >= 1 ) {
 | 
			
		||||
        return OMX_ErrorNoMore;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    strncpy(componentName, kComponentInfo[0].mName, nameLen);
 | 
			
		||||
 | 
			
		||||
    return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE outputComponent,
 | 
			
		||||
                OMX_IN OMX_U32             outputPort,
 | 
			
		||||
                OMX_IN OMX_HANDLETYPE  inputComponent,
 | 
			
		||||
                OMX_IN OMX_U32              inputPort)
 | 
			
		||||
{
 | 
			
		||||
	 return OMX_ErrorNotImplemented;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE
 | 
			
		||||
OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* pipe,
 | 
			
		||||
                   OMX_IN OMX_STRING        uri)
 | 
			
		||||
{
 | 
			
		||||
	 return OMX_ErrorNotImplemented;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE
 | 
			
		||||
OMX_GetComponentsOfRole(OMX_IN OMX_STRING      role,
 | 
			
		||||
                        OMX_INOUT OMX_U32* numComps,
 | 
			
		||||
                        OMX_INOUT OMX_U8** compNames)
 | 
			
		||||
{
 | 
			
		||||
	return OMX_ErrorNotImplemented;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE
 | 
			
		||||
OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName,
 | 
			
		||||
                        OMX_INOUT OMX_U32* numRoles,
 | 
			
		||||
                        OMX_OUT OMX_U8** roles)
 | 
			
		||||
{
 | 
			
		||||
	 return OMX_ErrorNotImplemented;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								multimedia/04_day/test-openmax/AnatomyOMXCore.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								multimedia/04_day/test-openmax/AnatomyOMXCore.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef ANATOMYOMXCORE_H_
 | 
			
		||||
#define ANATOMYOMXCORE_H_
 | 
			
		||||
 | 
			
		||||
#include "OMX_Types.h"
 | 
			
		||||
#include "OMX_Core.h"
 | 
			
		||||
#include "OMX_Component.h"
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_Init();
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_Deinit();
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_GetHandle(OMX_OUT OMX_HANDLETYPE*     handle,
 | 
			
		||||
              OMX_IN OMX_STRING    componentName,
 | 
			
		||||
              OMX_IN OMX_PTR             appData,
 | 
			
		||||
              OMX_IN OMX_CALLBACKTYPE* callBacks);
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp);
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE outputComponent,
 | 
			
		||||
                OMX_IN OMX_U32             outputPort,
 | 
			
		||||
                OMX_IN OMX_HANDLETYPE  inputComponent,
 | 
			
		||||
                OMX_IN OMX_U32              inputPort);
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE
 | 
			
		||||
OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* pipe,
 | 
			
		||||
                   OMX_IN OMX_STRING        uri);
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE OMX_APIENTRY
 | 
			
		||||
OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName,
 | 
			
		||||
                      OMX_IN  OMX_U32          nameLen,
 | 
			
		||||
                      OMX_IN  OMX_U32            index);
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE
 | 
			
		||||
OMX_GetComponentsOfRole(OMX_IN OMX_STRING      role,
 | 
			
		||||
                        OMX_INOUT OMX_U32* numComps,
 | 
			
		||||
                        OMX_INOUT OMX_U8** compNames);
 | 
			
		||||
 | 
			
		||||
OMX_API OMX_ERRORTYPE
 | 
			
		||||
OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName,
 | 
			
		||||
                        OMX_INOUT OMX_U32* numRoles,
 | 
			
		||||
                        OMX_OUT OMX_U8** roles);
 | 
			
		||||
 | 
			
		||||
#endif /* ANATOMYOMXCORE_H_ */
 | 
			
		||||
							
								
								
									
										170
									
								
								multimedia/04_day/test-openmax/AnatomyOMXPlugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								multimedia/04_day/test-openmax/AnatomyOMXPlugin.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,170 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//#define LOG_NDEBUG 0
 | 
			
		||||
#define LOG_TAG "AnatomyOMXPlugin"
 | 
			
		||||
#include <utils/Log.h>
 | 
			
		||||
 | 
			
		||||
#include "AnatomyOMXPlugin.h"
 | 
			
		||||
#include <include/SoftOMXComponent.h>
 | 
			
		||||
 | 
			
		||||
#include <media/stagefright/foundation/ADebug.h>
 | 
			
		||||
#include <media/stagefright/foundation/AString.h>
 | 
			
		||||
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
#define LOGV ALOGV
 | 
			
		||||
#define LOGE ALOGE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace android {
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
    const char *mName;
 | 
			
		||||
    const char *mLibNameSuffix;
 | 
			
		||||
    const char *mRole;
 | 
			
		||||
 | 
			
		||||
} kComponents[] = {
 | 
			
		||||
    { "OMX.anatomy.atm.decoder", "atmdec", "ascii_decoder.atm" },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const size_t kNumComponents =
 | 
			
		||||
    sizeof(kComponents) / sizeof(kComponents[0]);
 | 
			
		||||
 | 
			
		||||
AnatomyOMXPlugin::AnatomyOMXPlugin() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_ERRORTYPE AnatomyOMXPlugin::makeComponentInstance(
 | 
			
		||||
        const char *name,
 | 
			
		||||
        const OMX_CALLBACKTYPE *callbacks,
 | 
			
		||||
        OMX_PTR appData,
 | 
			
		||||
        OMX_COMPONENTTYPE **component) {
 | 
			
		||||
    LOGV("makeComponentInstance '%s'", name);
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < kNumComponents; ++i) {
 | 
			
		||||
        if (strcmp(name, kComponents[i].mName)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AString libName = "libanatomy_";
 | 
			
		||||
        libName.append(kComponents[i].mLibNameSuffix);
 | 
			
		||||
        libName.append(".so");
 | 
			
		||||
 | 
			
		||||
        void *libHandle = dlopen(libName.c_str(), RTLD_NOW);
 | 
			
		||||
 | 
			
		||||
        if (libHandle == NULL) {
 | 
			
		||||
            LOGE("unable to dlopen %s", libName.c_str());
 | 
			
		||||
 | 
			
		||||
            return OMX_ErrorComponentNotFound;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(
 | 
			
		||||
                const char *, const OMX_CALLBACKTYPE *,
 | 
			
		||||
                OMX_PTR, OMX_COMPONENTTYPE **);
 | 
			
		||||
 | 
			
		||||
        CreateSoftOMXComponentFunc createSoftOMXComponent =
 | 
			
		||||
            (CreateSoftOMXComponentFunc)dlsym(
 | 
			
		||||
                    libHandle,
 | 
			
		||||
                    "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"
 | 
			
		||||
                    "PvPP17OMX_COMPONENTTYPE");
 | 
			
		||||
 | 
			
		||||
        if (createSoftOMXComponent == NULL) {
 | 
			
		||||
            dlclose(libHandle);
 | 
			
		||||
            libHandle = NULL;
 | 
			
		||||
 | 
			
		||||
            return OMX_ErrorComponentNotFound;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sp<SoftOMXComponent> codec =
 | 
			
		||||
            (*createSoftOMXComponent)(name, callbacks, appData, component);
 | 
			
		||||
 | 
			
		||||
        if (codec == NULL) {
 | 
			
		||||
            dlclose(libHandle);
 | 
			
		||||
            libHandle = NULL;
 | 
			
		||||
 | 
			
		||||
            return OMX_ErrorInsufficientResources;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        OMX_ERRORTYPE err = codec->initCheck();
 | 
			
		||||
        if (err != OMX_ErrorNone) {
 | 
			
		||||
            dlclose(libHandle);
 | 
			
		||||
            libHandle = NULL;
 | 
			
		||||
 | 
			
		||||
            return err;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        codec->incStrong(this);
 | 
			
		||||
        codec->setLibHandle(libHandle);
 | 
			
		||||
 | 
			
		||||
        return OMX_ErrorNone;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return OMX_ErrorInvalidComponentName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_ERRORTYPE AnatomyOMXPlugin::destroyComponentInstance(
 | 
			
		||||
        OMX_COMPONENTTYPE *component) {
 | 
			
		||||
    SoftOMXComponent *me =
 | 
			
		||||
        (SoftOMXComponent *)
 | 
			
		||||
            ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
 | 
			
		||||
 | 
			
		||||
    me->prepareForDestruction();
 | 
			
		||||
 | 
			
		||||
    void *libHandle = me->libHandle();
 | 
			
		||||
 | 
			
		||||
    CHECK_EQ(me->getStrongCount(), 1);
 | 
			
		||||
    me->decStrong(this);
 | 
			
		||||
    me = NULL;
 | 
			
		||||
 | 
			
		||||
    dlclose(libHandle);
 | 
			
		||||
    libHandle = NULL;
 | 
			
		||||
 | 
			
		||||
    return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_ERRORTYPE AnatomyOMXPlugin::enumerateComponents(
 | 
			
		||||
        OMX_STRING name,
 | 
			
		||||
        size_t size,
 | 
			
		||||
        OMX_U32 index) {
 | 
			
		||||
    if (index >= kNumComponents) {
 | 
			
		||||
        return OMX_ErrorNoMore;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    strcpy(name, kComponents[index].mName);
 | 
			
		||||
 | 
			
		||||
    return OMX_ErrorNone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OMX_ERRORTYPE AnatomyOMXPlugin::getRolesOfComponent(
 | 
			
		||||
        const char *name,
 | 
			
		||||
        Vector<String8> *roles) {
 | 
			
		||||
    for (size_t i = 0; i < kNumComponents; ++i) {
 | 
			
		||||
        if (strcmp(name, kComponents[i].mName)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        roles->clear();
 | 
			
		||||
        roles->push(String8(kComponents[i].mRole));
 | 
			
		||||
 | 
			
		||||
        return OMX_ErrorNone;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return OMX_ErrorInvalidComponentName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace android
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										55
									
								
								multimedia/04_day/test-openmax/AnatomyOMXPlugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								multimedia/04_day/test-openmax/AnatomyOMXPlugin.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef ANATOMY_OMX_PLUGIN_H_
 | 
			
		||||
 | 
			
		||||
#define ANATOMY_OMX_PLUGIN_H_
 | 
			
		||||
 | 
			
		||||
#include <media/stagefright/foundation/ABase.h>
 | 
			
		||||
#include <media/hardware/OMXPluginBase.h>
 | 
			
		||||
 | 
			
		||||
namespace android {
 | 
			
		||||
 | 
			
		||||
struct AnatomyOMXPlugin : public OMXPluginBase {
 | 
			
		||||
    AnatomyOMXPlugin();
 | 
			
		||||
 | 
			
		||||
    virtual OMX_ERRORTYPE makeComponentInstance(
 | 
			
		||||
            const char *name,
 | 
			
		||||
            const OMX_CALLBACKTYPE *callbacks,
 | 
			
		||||
            OMX_PTR appData,
 | 
			
		||||
            OMX_COMPONENTTYPE **component);
 | 
			
		||||
 | 
			
		||||
    virtual OMX_ERRORTYPE destroyComponentInstance(
 | 
			
		||||
            OMX_COMPONENTTYPE *component);
 | 
			
		||||
 | 
			
		||||
    virtual OMX_ERRORTYPE enumerateComponents(
 | 
			
		||||
            OMX_STRING name,
 | 
			
		||||
            size_t size,
 | 
			
		||||
            OMX_U32 index);
 | 
			
		||||
 | 
			
		||||
    virtual OMX_ERRORTYPE getRolesOfComponent(
 | 
			
		||||
            const char *name,
 | 
			
		||||
            Vector<String8> *roles);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    DISALLOW_EVIL_CONSTRUCTORS(AnatomyOMXPlugin);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace android
 | 
			
		||||
 | 
			
		||||
#endif  // ANATOMY_OMX_PLUGIN_H_
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										59
									
								
								multimedia/04_day/test-openmax/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								multimedia/04_day/test-openmax/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,59 @@
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE    := test-openmax
 | 
			
		||||
LOCAL_MODULE_TAGS := tests
 | 
			
		||||
 | 
			
		||||
LOCAL_C_INCLUDES := \
 | 
			
		||||
			$(LOCAL_PATH)/include \
 | 
			
		||||
			bionic/ \
 | 
			
		||||
 			external/stlport/stlport \
 | 
			
		||||
 			frameworks/base/include \
 | 
			
		||||
 			frameworks/av/media/libstagefright \
 | 
			
		||||
			frameworks/native/include/media/openmax \
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES := \
 | 
			
		||||
				AnatomyOMXCore.cpp \
 | 
			
		||||
				AnatomyOMXPlugin.cpp \
 | 
			
		||||
				main_anatomy_omxclient.cpp \
 | 
			
		||||
				AnatomyOMXClient.cpp \
 | 
			
		||||
				ATMParser.cpp \
 | 
			
		||||
				StdoutRenderer.cpp \
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := \
 | 
			
		||||
		libcutils\
 | 
			
		||||
		libutils\
 | 
			
		||||
		libdl\
 | 
			
		||||
 		libstlport \
 | 
			
		||||
 		libstagefright_omx \
 | 
			
		||||
 		libstagefright_foundation \
 | 
			
		||||
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
LOCAL_MODULE    := libanatomy_atmdec
 | 
			
		||||
LOCAL_MODULE_TAGS := tests
 | 
			
		||||
 | 
			
		||||
LOCAL_C_INCLUDES := \
 | 
			
		||||
			$(LOCAL_PATH)/include \
 | 
			
		||||
			bionic/ \
 | 
			
		||||
 			external/stlport/stlport \
 | 
			
		||||
 			frameworks/base/include \
 | 
			
		||||
 			frameworks/av/media/libstagefright \
 | 
			
		||||
			frameworks/native/include/media/openmax \
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := \
 | 
			
		||||
		libcutils\
 | 
			
		||||
		libutils\
 | 
			
		||||
		libdl\
 | 
			
		||||
 		libstlport \
 | 
			
		||||
 		libstagefright_omx \
 | 
			
		||||
 		libstagefright_foundation \
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES := \
 | 
			
		||||
				AnatomyOMXComponent.cpp \
 | 
			
		||||
 | 
			
		||||
include $(BUILD_SHARED_LIBRARY)
 | 
			
		||||
							
								
								
									
										41
									
								
								multimedia/04_day/test-openmax/StdoutRenderer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								multimedia/04_day/test-openmax/StdoutRenderer.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//#define LOG_NDEBUG 0
 | 
			
		||||
#define LOG_TAG "StdoutRenderer"
 | 
			
		||||
 | 
			
		||||
#include "StdoutRenderer.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace anatomy {
 | 
			
		||||
 | 
			
		||||
void StdoutRenderer::render(void* buffer,int length) {
 | 
			
		||||
	memcpy(mBuffer, buffer, length);
 | 
			
		||||
	mBuffer[length] = '\0';
 | 
			
		||||
	if( mBuffer[0] == '/' )
 | 
			
		||||
	{
 | 
			
		||||
		std::cout << std::endl;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		std::cout << mBuffer;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										36
									
								
								multimedia/04_day/test-openmax/StdoutRenderer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								multimedia/04_day/test-openmax/StdoutRenderer.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef STDOUT_RENDERER_H_
 | 
			
		||||
#define STDOUT_RENDERER_H_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace anatomy {
 | 
			
		||||
 | 
			
		||||
class StdoutRenderer {
 | 
			
		||||
public:
 | 
			
		||||
	StdoutRenderer(){}
 | 
			
		||||
	virtual ~StdoutRenderer(){}
 | 
			
		||||
	void render(void* buffer,int length);
 | 
			
		||||
private:
 | 
			
		||||
	char mBuffer[256];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace anatomy
 | 
			
		||||
 | 
			
		||||
#endif  // STDOUT_RENDERER_H_
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								multimedia/04_day/test-openmax/main_anatomy_omxclient.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								multimedia/04_day/test-openmax/main_anatomy_omxclient.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
/*
 | 
			
		||||
**
 | 
			
		||||
** Copyright 2013, kod21236@gmail.com
 | 
			
		||||
**
 | 
			
		||||
** Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
** you may not use this file except in compliance with the License.
 | 
			
		||||
** You may obtain a copy of the License at
 | 
			
		||||
**
 | 
			
		||||
**     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
**
 | 
			
		||||
** Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
** distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
** See the License for the specific language governing permissions and
 | 
			
		||||
** limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "AnatomyOMXClient.h"
 | 
			
		||||
 | 
			
		||||
#include <utils/Log.h>
 | 
			
		||||
#include <media/stagefright/foundation/ADebug.h>
 | 
			
		||||
 | 
			
		||||
using namespace anatomy;
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
	AnatomyOMXClient* pOMXClient = new AnatomyOMXClient;
 | 
			
		||||
 | 
			
		||||
	CHECK( NULL != pOMXClient );
 | 
			
		||||
 | 
			
		||||
	pOMXClient->prepare();
 | 
			
		||||
 | 
			
		||||
	pOMXClient->start();
 | 
			
		||||
 | 
			
		||||
	pOMXClient->stop();
 | 
			
		||||
 | 
			
		||||
	delete pOMXClient;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										138
									
								
								multimedia/04_day/test-openmax/tags
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								multimedia/04_day/test-openmax/tags
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,138 @@
 | 
			
		||||
!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/
 | 
			
		||||
!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/
 | 
			
		||||
!_TAG_PROGRAM_AUTHOR	Darren Hiebert	/dhiebert@users.sourceforge.net/
 | 
			
		||||
!_TAG_PROGRAM_NAME	Exuberant Ctags	//
 | 
			
		||||
!_TAG_PROGRAM_URL	http://ctags.sourceforge.net	/official site/
 | 
			
		||||
!_TAG_PROGRAM_VERSION	5.9~svn20110310	//
 | 
			
		||||
ANATOMYOMXCORE_H_	AnatomyOMXCore.h	19;"	d
 | 
			
		||||
ANATOMY_OMXCLIENT_H_	AnatomyOMXClient.h	19;"	d
 | 
			
		||||
ANATOMY_OMX_COMPONENT_H_	AnatomyOMXComponent.h	20;"	d
 | 
			
		||||
ANATOMY_OMX_PLUGIN_H_	AnatomyOMXPlugin.h	20;"	d
 | 
			
		||||
ATMParser	ATMParser.cpp	/^ATMParser::ATMParser()$/;"	f	class:anatomy::ATMParser
 | 
			
		||||
ATMParser	ATMParser.h	/^class ATMParser {$/;"	c	namespace:anatomy
 | 
			
		||||
ATM_PARSER_H_	ATMParser.h	18;"	d
 | 
			
		||||
AnatomyOMXClient	AnatomyOMXClient.h	/^	AnatomyOMXClient(){}$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
AnatomyOMXClient	AnatomyOMXClient.h	/^struct AnatomyOMXClient {$/;"	s	namespace:anatomy
 | 
			
		||||
AnatomyOMXComponent	AnatomyOMXComponent.cpp	/^AnatomyOMXComponent::AnatomyOMXComponent($/;"	f	class:android::AnatomyOMXComponent
 | 
			
		||||
AnatomyOMXComponent	AnatomyOMXComponent.h	/^struct AnatomyOMXComponent : public SimpleSoftOMXComponent {$/;"	s	namespace:android
 | 
			
		||||
AnatomyOMXPlugin	AnatomyOMXPlugin.cpp	/^AnatomyOMXPlugin::AnatomyOMXPlugin() {$/;"	f	class:android::AnatomyOMXPlugin
 | 
			
		||||
AnatomyOMXPlugin	AnatomyOMXPlugin.h	/^struct AnatomyOMXPlugin : public OMXPluginBase {$/;"	s	namespace:android
 | 
			
		||||
InitOMXParams	AnatomyOMXClient.cpp	/^static void InitOMXParams(T *params) {$/;"	f	namespace:anatomy
 | 
			
		||||
InitOMXParams	AnatomyOMXComponent.cpp	/^static void InitOMXParams(T *params) {$/;"	f	namespace:android
 | 
			
		||||
LOCAL_C_INCLUDES	Android.mk	/^LOCAL_C_INCLUDES := \\$/;"	m
 | 
			
		||||
LOCAL_MODULE	Android.mk	/^LOCAL_MODULE    := anatomy_omx_client$/;"	m
 | 
			
		||||
LOCAL_MODULE	Android.mk	/^LOCAL_MODULE    := libanatomy_atmdec$/;"	m
 | 
			
		||||
LOCAL_MODULE_TAGS	Android.mk	/^LOCAL_MODULE_TAGS := tests$/;"	m
 | 
			
		||||
LOCAL_PATH	Android.mk	/^LOCAL_PATH := $(call my-dir)$/;"	m
 | 
			
		||||
LOCAL_SHARED_LIBRARIES	Android.mk	/^LOCAL_SHARED_LIBRARIES := \\$/;"	m
 | 
			
		||||
LOCAL_SRC_FILES	Android.mk	/^LOCAL_SRC_FILES := \\$/;"	m
 | 
			
		||||
LOGD	ATMParser.cpp	25;"	d	file:
 | 
			
		||||
LOGD	AnatomyOMXClient.cpp	28;"	d	file:
 | 
			
		||||
LOGD	AnatomyOMXComponent.cpp	29;"	d	file:
 | 
			
		||||
LOGD	AnatomyOMXCore.cpp	29;"	d	file:
 | 
			
		||||
LOGE	AnatomyOMXPlugin.cpp	31;"	d	file:
 | 
			
		||||
LOGV	AnatomyOMXCore.cpp	30;"	d	file:
 | 
			
		||||
LOGV	AnatomyOMXPlugin.cpp	30;"	d	file:
 | 
			
		||||
LOGW	AnatomyOMXClient.cpp	27;"	d	file:
 | 
			
		||||
LOG_TAG	ATMParser.cpp	19;"	d	file:
 | 
			
		||||
LOG_TAG	AnatomyOMXClient.cpp	19;"	d	file:
 | 
			
		||||
LOG_TAG	AnatomyOMXComponent.cpp	19;"	d	file:
 | 
			
		||||
LOG_TAG	AnatomyOMXPlugin.cpp	19;"	d	file:
 | 
			
		||||
LOG_TAG	StdoutRenderer.cpp	19;"	d	file:
 | 
			
		||||
OMXClientBufferInfo	AnatomyOMXClient.h	/^	 struct OMXClientBufferInfo {$/;"	s	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
OMX_ComponentNameEnum	AnatomyOMXCore.cpp	/^OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName,$/;"	f
 | 
			
		||||
OMX_Deinit	AnatomyOMXCore.cpp	/^OMX_Deinit()$/;"	f
 | 
			
		||||
OMX_FreeHandle	AnatomyOMXCore.cpp	/^OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp)$/;"	f
 | 
			
		||||
OMX_GetComponentsOfRole	AnatomyOMXCore.cpp	/^OMX_GetComponentsOfRole(OMX_IN OMX_STRING      role,$/;"	f
 | 
			
		||||
OMX_GetContentPipe	AnatomyOMXCore.cpp	/^OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* pipe,$/;"	f
 | 
			
		||||
OMX_GetHandle	AnatomyOMXCore.cpp	/^OMX_GetHandle(OMX_OUT OMX_HANDLETYPE*     handle,$/;"	f
 | 
			
		||||
OMX_GetRolesOfComponent	AnatomyOMXCore.cpp	/^OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName,$/;"	f
 | 
			
		||||
OMX_Init	AnatomyOMXCore.cpp	/^OMX_Init()$/;"	f
 | 
			
		||||
OMX_SetupTunnel	AnatomyOMXCore.cpp	/^OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE outputComponent,$/;"	f
 | 
			
		||||
OnEmptyBufferDone	AnatomyOMXClient.cpp	/^OMX_ERRORTYPE AnatomyOMXClient::OnEmptyBufferDone($/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
OnEvent	AnatomyOMXClient.cpp	/^OMX_ERRORTYPE AnatomyOMXClient::OnEvent($/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
OnFillBufferDone	AnatomyOMXClient.cpp	/^OMX_ERRORTYPE AnatomyOMXClient::OnFillBufferDone($/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
STDOUT_RENDERER_H_	StdoutRenderer.h	19;"	d
 | 
			
		||||
StdoutRenderer	StdoutRenderer.h	/^	StdoutRenderer(){}$/;"	f	class:anatomy::StdoutRenderer
 | 
			
		||||
StdoutRenderer	StdoutRenderer.h	/^class StdoutRenderer {$/;"	c	namespace:anatomy
 | 
			
		||||
addOMXBufferInfo	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::addOMXBufferInfo($/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
allocateBuffers	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::allocateBuffers() {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
anatomy	ATMParser.cpp	/^namespace anatomy {$/;"	n	file:
 | 
			
		||||
anatomy	ATMParser.h	/^namespace anatomy {$/;"	n
 | 
			
		||||
anatomy	AnatomyOMXClient.cpp	/^namespace anatomy {$/;"	n	file:
 | 
			
		||||
anatomy	AnatomyOMXClient.h	/^namespace anatomy {$/;"	n
 | 
			
		||||
anatomy	StdoutRenderer.cpp	/^namespace anatomy {$/;"	n	file:
 | 
			
		||||
anatomy	StdoutRenderer.h	/^namespace anatomy {$/;"	n
 | 
			
		||||
android	AnatomyOMXComponent.cpp	/^namespace android {$/;"	n	file:
 | 
			
		||||
android	AnatomyOMXComponent.h	/^namespace android {$/;"	n
 | 
			
		||||
android	AnatomyOMXPlugin.cpp	/^namespace android {$/;"	n	file:
 | 
			
		||||
android	AnatomyOMXPlugin.h	/^namespace android {$/;"	n
 | 
			
		||||
changeState	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::changeState(OMX_STATETYPE state) {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
createSoftOMXComponent	AnatomyOMXComponent.cpp	/^android::SoftOMXComponent *createSoftOMXComponent($/;"	f
 | 
			
		||||
decodeBuffer	AnatomyOMXComponent.cpp	/^void AnatomyOMXComponent::decodeBuffer(OMX_U8* dst, OMX_U8* src, OMX_U32 size, OMX_U32* decoded_size) {$/;"	f	class:android::AnatomyOMXComponent
 | 
			
		||||
deinit	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::deinit() {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
destroyComponentInstance	AnatomyOMXPlugin.cpp	/^OMX_ERRORTYPE AnatomyOMXPlugin::destroyComponentInstance($/;"	f	class:android::AnatomyOMXPlugin
 | 
			
		||||
enumerateComponents	AnatomyOMXPlugin.cpp	/^OMX_ERRORTYPE AnatomyOMXPlugin::enumerateComponents($/;"	f	class:android::AnatomyOMXPlugin
 | 
			
		||||
excute	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::excute() {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
freeBuffers	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::freeBuffers() {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
getRolesOfComponent	AnatomyOMXPlugin.cpp	/^OMX_ERRORTYPE AnatomyOMXPlugin::getRolesOfComponent($/;"	f	class:android::AnatomyOMXPlugin
 | 
			
		||||
getStatus	AnatomyOMXClient.h	/^	int getStatus(){ return mStatus; }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
init	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::init() {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
initPorts	AnatomyOMXComponent.cpp	/^void AnatomyOMXComponent::initPorts() {$/;"	f	class:android::AnatomyOMXComponent
 | 
			
		||||
kCallbacks	AnatomyOMXClient.cpp	/^OMX_CALLBACKTYPE AnatomyOMXClient::kCallbacks = {$/;"	m	class:anatomy::AnatomyOMXClient	file:
 | 
			
		||||
kCallbacks	AnatomyOMXClient.h	/^	static OMX_CALLBACKTYPE kCallbacks;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
kComponentInfo	AnatomyOMXCore.cpp	/^} kComponentInfo[] = {$/;"	v	typeref:struct:__anon4	file:
 | 
			
		||||
kComponents	AnatomyOMXPlugin.cpp	/^} kComponents[] = {$/;"	m	namespace:android	typeref:struct:android::__anon3	file:
 | 
			
		||||
kInputPortIndex	AnatomyOMXComponent.h	/^        kInputPortIndex   = 0,$/;"	e	enum:android::AnatomyOMXComponent::__anon2
 | 
			
		||||
kNumComponents	AnatomyOMXPlugin.cpp	/^static const size_t kNumComponents =$/;"	m	namespace:android	file:
 | 
			
		||||
kNumInputBuffers	AnatomyOMXComponent.h	/^        kNumInputBuffers  = 2,$/;"	e	enum:android::AnatomyOMXComponent::__anon2
 | 
			
		||||
kNumOutputBuffers	AnatomyOMXComponent.h	/^        kNumOutputBuffers = 5,$/;"	e	enum:android::AnatomyOMXComponent::__anon2
 | 
			
		||||
kOutputPortIndex	AnatomyOMXComponent.h	/^        kOutputPortIndex  = 1,$/;"	e	enum:android::AnatomyOMXComponent::__anon2
 | 
			
		||||
kPortIndexInput	AnatomyOMXClient.h	/^        kPortIndexInput  = 0,$/;"	e	enum:anatomy::AnatomyOMXClient::__anon1
 | 
			
		||||
kPortIndexOutput	AnatomyOMXClient.h	/^        kPortIndexOutput = 1$/;"	e	enum:anatomy::AnatomyOMXClient::__anon1
 | 
			
		||||
mBuffer	StdoutRenderer.h	/^	char mBuffer[256];$/;"	m	class:anatomy::StdoutRenderer
 | 
			
		||||
mBufferHeader	AnatomyOMXClient.h	/^        OMX_BUFFERHEADERTYPE* mBufferHeader;$/;"	m	struct:anatomy::AnatomyOMXClient::OMXClientBufferInfo
 | 
			
		||||
mBufferInfo	AnatomyOMXClient.h	/^    android::Vector<OMXClientBufferInfo> mBufferInfo;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mComponentHandle	AnatomyOMXClient.h	/^	OMX_HANDLETYPE mComponentHandle;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mEOSCondition	AnatomyOMXClient.h	/^	android::Condition mEOSCondition;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mExcutingCondition	AnatomyOMXClient.h	/^	android::Condition mExcutingCondition;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mIdleCondition	AnatomyOMXClient.h	/^	android::Condition mIdleCondition;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mLength	ATMParser.h	/^    int mLength;$/;"	m	class:anatomy::ATMParser
 | 
			
		||||
mLibName	AnatomyOMXCore.cpp	/^    const char *mLibName;$/;"	m	struct:__anon4	file:
 | 
			
		||||
mLibNameSuffix	AnatomyOMXPlugin.cpp	/^    const char *mLibNameSuffix;$/;"	m	struct:android::__anon3	file:
 | 
			
		||||
mLoadedCondition	AnatomyOMXClient.h	/^	android::Condition mLoadedCondition;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mLock	AnatomyOMXClient.h	/^	android::Mutex mLock;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mName	AnatomyOMXCore.cpp	/^    const char *mName;$/;"	m	struct:__anon4	file:
 | 
			
		||||
mName	AnatomyOMXPlugin.cpp	/^    const char *mName;$/;"	m	struct:android::__anon3	file:
 | 
			
		||||
mOffset	ATMParser.h	/^	int mOffset;$/;"	m	class:anatomy::ATMParser
 | 
			
		||||
mParser	AnatomyOMXClient.h	/^	ATMParser mParser;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mPortIndex	AnatomyOMXClient.h	/^        OMX_U32 mPortIndex;$/;"	m	struct:anatomy::AnatomyOMXClient::OMXClientBufferInfo
 | 
			
		||||
mRenderer	AnatomyOMXClient.h	/^	StdoutRenderer mRenderer;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
mRole	AnatomyOMXCore.cpp	/^    const char *mRole;$/;"	m	struct:__anon4	file:
 | 
			
		||||
mRole	AnatomyOMXPlugin.cpp	/^    const char *mRole;$/;"	m	struct:android::__anon3	file:
 | 
			
		||||
mStatus	AnatomyOMXClient.h	/^	int mStatus;$/;"	m	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
main	main_anatomy_omxclient.cpp	/^int main()$/;"	f
 | 
			
		||||
makeComponentInstance	AnatomyOMXPlugin.cpp	/^OMX_ERRORTYPE AnatomyOMXPlugin::makeComponentInstance($/;"	f	class:android::AnatomyOMXPlugin
 | 
			
		||||
onQueueFilled	AnatomyOMXComponent.cpp	/^void AnatomyOMXComponent::onQueueFilled(OMX_U32 portIndex) {$/;"	f	class:android::AnatomyOMXComponent
 | 
			
		||||
prepare	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::prepare() {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
pszSource	ATMParser.cpp	/^static char pszSource[] = "\\$/;"	m	namespace:anatomy	file:
 | 
			
		||||
read	ATMParser.cpp	/^void ATMParser::read(void* buffer, int* length) {$/;"	f	class:anatomy::ATMParser
 | 
			
		||||
read	AnatomyOMXClient.h	/^	void read(void* buffer,int* length){mParser.read(buffer, length);}$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
removeOMXBufferInfo	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::removeOMXBufferInfo($/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
render	AnatomyOMXClient.h	/^	void render(void* buffer,int length){mRenderer.render(buffer, length);}$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
render	StdoutRenderer.cpp	/^void StdoutRenderer::render(void* buffer,int length) {$/;"	f	class:anatomy::StdoutRenderer
 | 
			
		||||
setStatus	AnatomyOMXClient.h	/^	void setStatus(int status){ mStatus = status; }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
signalEOF	AnatomyOMXClient.h	/^	void signalEOF() { mEOSCondition.signal(); }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
signalExcutingState	AnatomyOMXClient.h	/^	void signalExcutingState() { mExcutingCondition.signal(); }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
signalIdleState	AnatomyOMXClient.h	/^	void signalIdleState() { mIdleCondition.signal(); }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
signalLoadedState	AnatomyOMXClient.h	/^	void signalLoadedState() { mLoadedCondition.signal(); }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
start	AnatomyOMXClient.h	/^	void start() { excute(); waitEOF();}$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
stop	AnatomyOMXClient.cpp	/^void AnatomyOMXClient::stop() {$/;"	f	class:anatomy::AnatomyOMXClient
 | 
			
		||||
waitEOF	AnatomyOMXClient.h	/^	void waitEOF() { mEOSCondition.wait(mLock); }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
waitExcutingState	AnatomyOMXClient.h	/^	void waitExcutingState() { mExcutingCondition.wait(mLock);}$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
waitIdleState	AnatomyOMXClient.h	/^	void waitIdleState() { mIdleCondition.wait(mLock); }$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
waitLoadedState	AnatomyOMXClient.h	/^	void waitLoadedState() { mLoadedCondition.wait(mLock);}$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
~ATMParser	ATMParser.h	/^	virtual ~ATMParser(){}$/;"	f	class:anatomy::ATMParser
 | 
			
		||||
~AnatomyOMXClient	AnatomyOMXClient.h	/^	virtual ~AnatomyOMXClient(){}$/;"	f	struct:anatomy::AnatomyOMXClient
 | 
			
		||||
~AnatomyOMXComponent	AnatomyOMXComponent.cpp	/^AnatomyOMXComponent::~AnatomyOMXComponent() {$/;"	f	class:android::AnatomyOMXComponent
 | 
			
		||||
~StdoutRenderer	StdoutRenderer.h	/^	virtual ~StdoutRenderer(){}$/;"	f	class:anatomy::StdoutRenderer
 | 
			
		||||
							
								
								
									
										55
									
								
								multimedia/05_day/test-camera/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								multimedia/05_day/test-camera/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
# Copyright 2013 The Android Open Source Project
 | 
			
		||||
#
 | 
			
		||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
# you may not use this file except in compliance with the License.
 | 
			
		||||
# You may obtain a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
# Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
# See the License for the specific language governing permissions and
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
 | 
			
		||||
LOCAL_PATH:= $(call my-dir)
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES:= \
 | 
			
		||||
	main.cpp \
 | 
			
		||||
	ProCameraTests.cpp \
 | 
			
		||||
	VendorTagDescriptorTests.cpp
 | 
			
		||||
 | 
			
		||||
LOCAL_SHARED_LIBRARIES := \
 | 
			
		||||
	libutils \
 | 
			
		||||
	libcutils \
 | 
			
		||||
	libstlport \
 | 
			
		||||
	libcamera_metadata \
 | 
			
		||||
	libcamera_client \
 | 
			
		||||
	libgui \
 | 
			
		||||
	libsync \
 | 
			
		||||
	libui \
 | 
			
		||||
	libdl \
 | 
			
		||||
	libbinder
 | 
			
		||||
 | 
			
		||||
LOCAL_STATIC_LIBRARIES := \
 | 
			
		||||
	libgtest
 | 
			
		||||
 | 
			
		||||
LOCAL_C_INCLUDES += \
 | 
			
		||||
	bionic \
 | 
			
		||||
	bionic/libstdc++/include \
 | 
			
		||||
	external/gtest/include \
 | 
			
		||||
	external/stlport/stlport \
 | 
			
		||||
	system/media/camera/include \
 | 
			
		||||
	system/media/private/camera/include \
 | 
			
		||||
	system/media/camera/tests \
 | 
			
		||||
	frameworks/av/services/camera/libcameraservice \
 | 
			
		||||
	frameworks/av/include/camera \
 | 
			
		||||
	frameworks/native/include \
 | 
			
		||||
 | 
			
		||||
LOCAL_CFLAGS += -Wall -Wextra
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE:= camera_client_test
 | 
			
		||||
LOCAL_MODULE_TAGS := tests
 | 
			
		||||
 | 
			
		||||
include $(BUILD_NATIVE_TEST)
 | 
			
		||||
							
								
								
									
										1314
									
								
								multimedia/05_day/test-camera/ProCameraTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1314
									
								
								multimedia/05_day/test-camera/ProCameraTests.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										205
									
								
								multimedia/05_day/test-camera/VendorTagDescriptorTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								multimedia/05_day/test-camera/VendorTagDescriptorTests.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,205 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define LOG_NDEBUG 0
 | 
			
		||||
#define LOG_TAG "VendorTagDescriptorTests"
 | 
			
		||||
 | 
			
		||||
#include <binder/Parcel.h>
 | 
			
		||||
#include <camera/VendorTagDescriptor.h>
 | 
			
		||||
#include <camera_metadata_tests_fake_vendor.h>
 | 
			
		||||
#include <camera_metadata_hidden.h>
 | 
			
		||||
#include <system/camera_vendor_tags.h>
 | 
			
		||||
#include <utils/Errors.h>
 | 
			
		||||
#include <utils/Log.h>
 | 
			
		||||
#include <utils/RefBase.h>
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    BAD_TAG_ARRAY = 0xDEADBEEFu,
 | 
			
		||||
    BAD_TAG = 0x8DEADBADu,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define ARRAY_SIZE(a)      (sizeof(a) / sizeof((a)[0]))
 | 
			
		||||
 | 
			
		||||
static bool ContainsTag(uint32_t* tagArray, size_t size, uint32_t tag) {
 | 
			
		||||
    for (size_t i = 0; i < size; ++i) {
 | 
			
		||||
        if (tag == tagArray[i]) return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define EXPECT_CONTAINS_TAG(t, a) \
 | 
			
		||||
    EXPECT_TRUE(ContainsTag(a, ARRAY_SIZE(a), t))
 | 
			
		||||
 | 
			
		||||
#define ASSERT_NOT_NULL(x) \
 | 
			
		||||
    ASSERT_TRUE((x) != NULL)
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
 | 
			
		||||
static int default_get_tag_count(const vendor_tag_ops_t* vOps) {
 | 
			
		||||
    return VENDOR_TAG_COUNT_ERR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void default_get_all_tags(const vendor_tag_ops_t* vOps, uint32_t* tagArray) {
 | 
			
		||||
    //Noop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char* default_get_section_name(const vendor_tag_ops_t* vOps, uint32_t tag) {
 | 
			
		||||
    return VENDOR_SECTION_NAME_ERR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char* default_get_tag_name(const vendor_tag_ops_t* vOps, uint32_t tag) {
 | 
			
		||||
    return VENDOR_TAG_NAME_ERR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int default_get_tag_type(const vendor_tag_ops_t* vOps, uint32_t tag) {
 | 
			
		||||
    return VENDOR_TAG_TYPE_ERR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} /*extern "C"*/
 | 
			
		||||
 | 
			
		||||
// Set default vendor operations for a vendor_tag_ops struct
 | 
			
		||||
static void FillWithDefaults(vendor_tag_ops_t* vOps) {
 | 
			
		||||
    ASSERT_NOT_NULL(vOps);
 | 
			
		||||
    vOps->get_tag_count = default_get_tag_count;
 | 
			
		||||
    vOps->get_all_tags = default_get_all_tags;
 | 
			
		||||
    vOps->get_section_name = default_get_section_name;
 | 
			
		||||
    vOps->get_tag_name = default_get_tag_name;
 | 
			
		||||
    vOps->get_tag_type = default_get_tag_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Test if values from VendorTagDescriptor methods match corresponding values
 | 
			
		||||
 * from vendor_tag_ops functions.
 | 
			
		||||
 */
 | 
			
		||||
#if 0
 | 
			
		||||
TEST(VendorTagDescriptorTest, ConsistentWithVendorTags) {
 | 
			
		||||
    sp<VendorTagDescriptor> vDesc;
 | 
			
		||||
    const vendor_tag_ops_t *vOps = &fakevendor_ops;
 | 
			
		||||
    EXPECT_EQ(OK, VendorTagDescriptor::createDescriptorFromOps(vOps, /*out*/vDesc));
 | 
			
		||||
 | 
			
		||||
    ASSERT_NOT_NULL(vDesc);
 | 
			
		||||
 | 
			
		||||
    // Ensure reasonable tag count
 | 
			
		||||
    int tagCount = vDesc->getTagCount();
 | 
			
		||||
    EXPECT_EQ(tagCount, vOps->get_tag_count(vOps));
 | 
			
		||||
 | 
			
		||||
    uint32_t descTagArray[tagCount];
 | 
			
		||||
    uint32_t opsTagArray[tagCount];
 | 
			
		||||
 | 
			
		||||
    // Get all tag ids
 | 
			
		||||
    vDesc->getTagArray(descTagArray);
 | 
			
		||||
    vOps->get_all_tags(vOps, opsTagArray);
 | 
			
		||||
 | 
			
		||||
    ASSERT_NOT_NULL(descTagArray);
 | 
			
		||||
    ASSERT_NOT_NULL(opsTagArray);
 | 
			
		||||
 | 
			
		||||
    uint32_t tag;
 | 
			
		||||
    for (int i = 0; i < tagCount; ++i) {
 | 
			
		||||
        // For each tag id, check whether type, section name, tag name match
 | 
			
		||||
        tag = descTagArray[i];
 | 
			
		||||
        EXPECT_CONTAINS_TAG(tag, opsTagArray);
 | 
			
		||||
        EXPECT_EQ(vDesc->getTagType(tag), vOps->get_tag_type(vOps, tag));
 | 
			
		||||
        EXPECT_STREQ(vDesc->getSectionName(tag), vOps->get_section_name(vOps, tag));
 | 
			
		||||
        EXPECT_STREQ(vDesc->getTagName(tag), vOps->get_tag_name(vOps, tag));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Test if values from VendorTagDescriptor methods stay consistent after being
 | 
			
		||||
 * parcelled/unparcelled.
 | 
			
		||||
 */
 | 
			
		||||
TEST(VendorTagDescriptorTest, ConsistentAcrossParcel) {
 | 
			
		||||
    sp<VendorTagDescriptor> vDescOriginal, vDescParceled;
 | 
			
		||||
    const vendor_tag_ops_t *vOps = &fakevendor_ops;
 | 
			
		||||
    EXPECT_EQ(OK, VendorTagDescriptor::createDescriptorFromOps(vOps, /*out*/vDescOriginal));
 | 
			
		||||
 | 
			
		||||
    ASSERT_TRUE(vDescOriginal != NULL);
 | 
			
		||||
 | 
			
		||||
    Parcel p;
 | 
			
		||||
 | 
			
		||||
    // Check whether parcel read/write succeed
 | 
			
		||||
    EXPECT_EQ(OK, vDescOriginal->writeToParcel(&p));
 | 
			
		||||
    p.setDataPosition(0);
 | 
			
		||||
    ASSERT_EQ(OK, VendorTagDescriptor::createFromParcel(&p, vDescParceled));
 | 
			
		||||
 | 
			
		||||
    // Ensure consistent tag count
 | 
			
		||||
    int tagCount = vDescOriginal->getTagCount();
 | 
			
		||||
    ASSERT_EQ(tagCount, vDescParceled->getTagCount());
 | 
			
		||||
 | 
			
		||||
    uint32_t descTagArray[tagCount];
 | 
			
		||||
    uint32_t desc2TagArray[tagCount];
 | 
			
		||||
 | 
			
		||||
    // Get all tag ids
 | 
			
		||||
    vDescOriginal->getTagArray(descTagArray);
 | 
			
		||||
    vDescParceled->getTagArray(desc2TagArray);
 | 
			
		||||
 | 
			
		||||
    ASSERT_NOT_NULL(descTagArray);
 | 
			
		||||
    ASSERT_NOT_NULL(desc2TagArray);
 | 
			
		||||
 | 
			
		||||
    uint32_t tag;
 | 
			
		||||
    for (int i = 0; i < tagCount; ++i) {
 | 
			
		||||
        // For each tag id, check consistency between the two vendor tag
 | 
			
		||||
        // descriptors for each type, section name, tag name
 | 
			
		||||
        tag = descTagArray[i];
 | 
			
		||||
        EXPECT_CONTAINS_TAG(tag, desc2TagArray);
 | 
			
		||||
        EXPECT_EQ(vDescOriginal->getTagType(tag), vDescParceled->getTagType(tag));
 | 
			
		||||
        EXPECT_STREQ(vDescOriginal->getSectionName(tag), vDescParceled->getSectionName(tag));
 | 
			
		||||
        EXPECT_STREQ(vDescOriginal->getTagName(tag), vDescParceled->getTagName(tag));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Test defaults and error conditions.
 | 
			
		||||
 */
 | 
			
		||||
TEST(VendorTagDescriptorTest, ErrorConditions) {
 | 
			
		||||
    sp<VendorTagDescriptor> vDesc;
 | 
			
		||||
    vendor_tag_ops_t vOps;
 | 
			
		||||
    FillWithDefaults(&vOps);
 | 
			
		||||
 | 
			
		||||
    // Ensure create fails when using null vOps
 | 
			
		||||
    EXPECT_EQ(BAD_VALUE, VendorTagDescriptor::createDescriptorFromOps(/*vOps*/NULL, vDesc));
 | 
			
		||||
 | 
			
		||||
    // Ensure create works when there are no vtags defined in a well-formed vOps
 | 
			
		||||
    ASSERT_EQ(OK, VendorTagDescriptor::createDescriptorFromOps(&vOps, vDesc));
 | 
			
		||||
 | 
			
		||||
    // Ensure defaults are returned when no vtags are defined, or tag is unknown
 | 
			
		||||
    EXPECT_EQ(VENDOR_TAG_COUNT_ERR, vDesc->getTagCount());
 | 
			
		||||
    uint32_t* tagArray = reinterpret_cast<uint32_t*>(BAD_TAG_ARRAY);
 | 
			
		||||
    uint32_t* testArray = tagArray;
 | 
			
		||||
    vDesc->getTagArray(tagArray);
 | 
			
		||||
    EXPECT_EQ(testArray, tagArray);
 | 
			
		||||
    EXPECT_EQ(VENDOR_SECTION_NAME_ERR, vDesc->getSectionName(BAD_TAG));
 | 
			
		||||
    EXPECT_EQ(VENDOR_TAG_NAME_ERR, vDesc->getTagName(BAD_TAG));
 | 
			
		||||
    EXPECT_EQ(VENDOR_TAG_TYPE_ERR, vDesc->getTagType(BAD_TAG));
 | 
			
		||||
 | 
			
		||||
    // Make sure global can be set/cleared
 | 
			
		||||
    const vendor_tag_ops_t *fakeOps = &fakevendor_ops;
 | 
			
		||||
    sp<VendorTagDescriptor> prevGlobal = VendorTagDescriptor::getGlobalVendorTagDescriptor();
 | 
			
		||||
    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
 | 
			
		||||
 | 
			
		||||
    EXPECT_TRUE(VendorTagDescriptor::getGlobalVendorTagDescriptor() == NULL);
 | 
			
		||||
    EXPECT_EQ(OK, VendorTagDescriptor::setAsGlobalVendorTagDescriptor(vDesc));
 | 
			
		||||
    EXPECT_TRUE(VendorTagDescriptor::getGlobalVendorTagDescriptor() != NULL);
 | 
			
		||||
    EXPECT_EQ(VENDOR_SECTION_NAME_ERR, vDesc->getSectionName(BAD_TAG));
 | 
			
		||||
    EXPECT_EQ(OK, VendorTagDescriptor::setAsGlobalVendorTagDescriptor(prevGlobal));
 | 
			
		||||
    EXPECT_EQ(prevGlobal, VendorTagDescriptor::getGlobalVendorTagDescriptor());
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										27
									
								
								multimedia/05_day/test-camera/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								multimedia/05_day/test-camera/main.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
 | 
			
		||||
    ::testing::InitGoogleTest(&argc, argv);
 | 
			
		||||
 | 
			
		||||
    int ret = RUN_ALL_TESTS();
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								multimedia/05_day/test-player/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								multimedia/05_day/test-player/Android.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
LOCAL_PATH := $(call my-dir)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE    := test-player 
 | 
			
		||||
LOCAL_SRC_FILES := player.cpp
 | 
			
		||||
LOCAL_SHARED_LIBRARIES :=  libutils  libui libgui libmedia libbinder
 | 
			
		||||
 | 
			
		||||
include $(BUILD_EXECUTABLE)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								multimedia/05_day/test-player/a.mp4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								multimedia/05_day/test-player/a.mp4
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										86
									
								
								multimedia/05_day/test-player/player.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								multimedia/05_day/test-player/player.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include <media/mediaplayer.h>
 | 
			
		||||
#include <media/IMediaPlayer.h>
 | 
			
		||||
#include <binder/ProcessState.h>
 | 
			
		||||
#include <binder/IPCThreadState.h>
 | 
			
		||||
#include <gui/SurfaceComposerClient.h>
 | 
			
		||||
#include <gui/ISurfaceComposer.h>
 | 
			
		||||
#include <gui/IGraphicBufferProducer.h>
 | 
			
		||||
#include <gui/Surface.h>
 | 
			
		||||
#include <utils/String8.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
using namespace android;
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	sp < ProcessState > proc = ProcessState::self();
 | 
			
		||||
	proc->startThreadPool();
 | 
			
		||||
	printf("entering main...\n");
 | 
			
		||||
	MediaPlayer mediaplayer;
 | 
			
		||||
	sp <Surface> gsf;
 | 
			
		||||
	status_t nState;
 | 
			
		||||
	int fd, fsize;
 | 
			
		||||
 | 
			
		||||
	fd = open( argv[1], O_RDONLY );
 | 
			
		||||
	if( fd < 0 )
 | 
			
		||||
	{
 | 
			
		||||
		perror("open()");
 | 
			
		||||
		exit(-1);
 | 
			
		||||
	}
 | 
			
		||||
	fsize = lseek( fd, 0, SEEK_END );
 | 
			
		||||
	printf("fsize=%d\n", fsize );
 | 
			
		||||
	mediaplayer.setDataSource(fd,0,fsize);
 | 
			
		||||
	close(fd);
 | 
			
		||||
 | 
			
		||||
	printf("create SurfaceComposerClient\n");
 | 
			
		||||
 | 
			
		||||
	sp<SurfaceComposerClient> composerClient;
 | 
			
		||||
	sp<SurfaceControl> control;
 | 
			
		||||
 | 
			
		||||
	composerClient = new SurfaceComposerClient;
 | 
			
		||||
	composerClient->initCheck();
 | 
			
		||||
 | 
			
		||||
	printf("create video surface\n");
 | 
			
		||||
 | 
			
		||||
	control = composerClient->createSurface(
 | 
			
		||||
			String8("A Surface"),
 | 
			
		||||
			1280,
 | 
			
		||||
			800,
 | 
			
		||||
			PIXEL_FORMAT_RGBA_8888,
 | 
			
		||||
			0);
 | 
			
		||||
 | 
			
		||||
	SurfaceComposerClient::openGlobalTransaction();
 | 
			
		||||
	control->setLayer(INT_MAX);
 | 
			
		||||
	control->show();
 | 
			
		||||
	SurfaceComposerClient::closeGlobalTransaction();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	gsf = control->getSurface();
 | 
			
		||||
	sp<IGraphicBufferProducer> videoSurfaceTexture = gsf->getIGraphicBufferProducer();
 | 
			
		||||
	printf("set video surface to player\n");
 | 
			
		||||
 | 
			
		||||
	mediaplayer.setVideoSurfaceTexture(videoSurfaceTexture);
 | 
			
		||||
 | 
			
		||||
	status_t retCode = mediaplayer.prepare();
 | 
			
		||||
 | 
			
		||||
	if (retCode < 0)
 | 
			
		||||
	{
 | 
			
		||||
		printf("prepare failed: %d\n", retCode);
 | 
			
		||||
		IPCThreadState::self()->stopProcess(0);
 | 
			
		||||
		return -1;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	mediaplayer.start();
 | 
			
		||||
	for (int i = 0; i < 4*60; i++)
 | 
			
		||||
	{
 | 
			
		||||
		sleep(1);
 | 
			
		||||
	}
 | 
			
		||||
	mediaplayer.reset();
 | 
			
		||||
 | 
			
		||||
	// close binder fd, still need waiting for all binder threads exit?
 | 
			
		||||
	IPCThreadState::self()->stopProcess(0);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user