Quantcast
Channel: Статьи Intel Developer Zone
Viewing all articles
Browse latest Browse all 357

Воспроизведение мультимедиа на API Google Android с эффектами Renderscript

$
0
0

Отказ от ответственности

Содержание

1. Введение

2. Необходимые условия

3. Настройка
      3.1 Декодер
    
 3.2 RenderScript

4. Запуск декодера

5. Применение эффекта RenderScript

6. Обработка цветов

7. Заключение


Введение

В этой статье мы покажем, как использовать классы Android Media и Android RenderScript для применения эффектов к декодированному видео. Для упрощения в статье описывается только воспроизведение видео; воспроизведение звука не рассматривается. Существует два рабочих потока: поток декодера и поток RenderScript.

Поток декодера делает следующее:
1.    Декодирует поток данных и помещает декодированные изображения в декодированный буфер. 
2.    Копирует только что декодированный кадр в расположение Renderscript.

Поток Renderscript делает следующее:
1.    Производит постобработку декодированных кадров видео, чтобы применить преобразование цветового пространства и эффект оттенков серого.
2.    Направляет выходные данные в другое расположение, связанное с SurfaceTexture.

 

 

Необходимые условия

Для воспроизведения API Android требуется опыт разработки приложений для Android. Дополнительные сведения о Media Decoder и RenderScript см. в следующих статьях.

1. Android BasicMediaDecoder - The Android Sample BasicMediaDecoder sample -      
    
http://developer.android.com/samples/BasicMediaDecoder/index.html

2. Android BasicRenderScript - The Android Sample BasicRenderScript sample -  
    
http://developer.android.com/samples/BasicRenderScript/index.html

3. Intel INDE Code Sample - Getting Started with RenderScript  
    
https://software.intel.com/en-us/articles/renderscript-basic-sample-for-android-os

 

Настройка

Декодер

Вот фрагмент кода для настройки декодера. Дополнительные сведения см. в разделе класс Android MediaExtractor.

// Get the media file
String MediaPath = Environment.getExternalStorageDirectory().getPath() + "/Movies/test4.mp4";
// Create a Uri which parses the given encoded URI string
Uri uri = Uri.parse(MediaPath);

try
{
	// Set the Data Source for the MediaExtractor
	mMediaExtractor.setDataSource(this, uri, null);
	// Get The number of tracks
	int numTracks = mMediaExtractor.getTrackCount();

	for( int i=0; i < numTracks; i++ )
	{
		mMediaExtractor.unselectTrack(i);
	}

	for( int i=0; i < numTracks; i++ )
	{
		// Get the type of the track
		MediaFormat format = mMediaExtractor.getTrackFormat(i);
		String mimeType = format.getString(MediaFormat.KEY_MIME);

		if(mimeType.contains("video"))
		{
			// For a Video Track, get Media Format
			// Frame width and height
			mVideoWidth = format.getInteger(MediaFormat.KEY_WIDTH);
	        	mVideoHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
	        	// Buffer Width and Height
	        mBufferWidth = mVideoWidth;
	        // make sure that the buffer height is a multiple of 16
	        mBufferHeight = mVideoHeight + (mVideoHeight%16);

	        // Initialize RenderScript See Section 3
	        initRenderScript();

	        // Creade a Decoder
			mDecoder = MediaCodec.createDecoderByType(mimeType);
			// Configure the decoder
			mDecoder.configure(format,	// Media Format from the stream
					null, 				// set surface to send decoded frames to buffers
					null,				// no Crypto
					0);					// flags
			if(mDecoder != null)
			{

				// Select this track
				mMediaExtractor.selectTrack(i);
				// start the decoder
				mDecoder.start();

				// query input and output buffers
		        mInputBuffers = mDecoder.getInputBuffers();
		        mOutputBuffers = mDecoder.getOutputBuffers();

		        // allocate byte buffer to temporarily hold decoded frame, input to renderscript
		        // 3/2 because the decoder outputs NV12 which has 12bits per pixel
		        mLocalOutputBuffers = new byte[mBufferWidth*mBufferHeight*3/2];


				break;
			}
		}
		else
		{
			// Handle this condition
		}
	}
}
catch (IOException e)
{
	e.printStackTrace();
}


RenderScript

Вот фрагмент кода для настройки RenderScript. Дополнительные сведения см. в разделе Android Renderscript.

  // Create RenderScript Context
    mRS = RenderScript.create(this);

    // Load RenderScript
    mScript = new ScriptC_process(mRS);

    // Create Allocations for reading into and out of Script
    // Input Allocation
    // Create a new Pixel Element of type YUV
    Element elemYUV = Element.createPixel(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_YUV);

    // Create a new (Type).Builder object of type elemYUV
    Type.Builder TypeYUV = new Type.Builder(mRS, elemYUV);

    // Set YUV format to NV21. The Decoder Outputs NV21 Surfaces
    TypeYUV.setYuvFormat(ImageFormat.NV21);

    // Create an Allocation
    mAllocationYUV = Allocation.createTyped(mRS,TypeYUV.setX(mVideoWidth).setY(mVideoHeight).create(),
    // Allocation Type Allocation.MipmapControl.MIPMAP_NONE, // No MIPMAP
Allocation.USAGE_SCRIPT);// Allocation will be used by a script

    // Output Allocation
    // Create a new Pixel Element of type RGBA
    Element elemOUT = Element.createPixel(mRS, Element.DataType.UNSIGNED_8, Element.DataKind.PIXEL_RGBA);

     // Create a new (Type).Builder object of type elemOUT
     Type.Builder TypeOUT = new Type.Builder(mRS, elemOUT);

     // create an Allocation
     mAllocationOUT = Allocation.createTyped(mRS,
     TypeOUT.setX(mVideoWidth).setY(mVideoHeight).create(),   // Allocation Type
Allocation.MipmapControl.MIPMAP_NONE,    // No MIPMAP
Allocation.USAGE_SCRIPT|                 // will be used by a script
Allocation.USAGE_IO_OUTPUT);             // will be used as a SurfaceTexture producer

    // Associate the Surface with output allocation
    // Get the Surface Texture
    SurfaceTexture surfaceTexture = mPlaybackView.getSurfaceTexture();

    if(surfaceTexture != null)
    {
    // Create a new surface
    Surface surface = new Surface(surfaceTexture);
    if(surface != null)
    {
   // set allocation surface
   mAllocationOUT.setSurface(surface);
    }
    }
    // Set the Input Allocation
    mScript.set_gIn(mAllocationYUV);

 

Запуск декодера

Вот фрагмент кода для копирования декодированных буферов в расположение RenderScript, входящее в состав потока декодирования. Дополнительные сведения о запуске этого потока см. в разделе класс MediaCodec.

Перед вызовом codec.releaseOutputBuffer(outputBufferIndex, ...) выполните следующие действия:

1. Получите декодированный буфер
2. Скопируйте его в расположение
3. Создайте новый поток для применения эффекта RenderScript

// decoded buffer size
int bufsize = mOutputBuffers[index].capacity();

// get the decode buffer
mOutputBuffers[index].get(mLocalOutputBuffers, 0, bufsize);

// copy to input Allocation
mAllocationYUV.copyFrom(mLocalOutputBuffers);

// rewind the ByteBuffer so that the pointer can be back to 0
mOutputBuffers[index].rewind();

// start a new thread for applying RenderScript effect
new ProcessData().execute();

// release outputbuffer back to the decoder
mDecoder.releaseOutputBuffer(index, render); 

 

Применение эффекта RenderScript

Вот фрагмент кода для потока RenderScript. Дополнительные сведения о потоке UI см. в разделе AsyncTask.

private class ProcessData extends AsyncTask<byte[], Void, Boolean>
{
@Override
	protected Boolean doInBackground(byte[]... args)
        {
        	// Apply the Renderscript YUV_to_RGB + greyscale effect
        	mScript.forEach_yuvToRgb_greyscale(mAllocationYUV, mAllocationOUT);
        	// Send the output allocation to surfacetexture
        	mAllocationOUT.ioSend();

            return true;
        }
    }

           

Обработка цветов

Вот простой сценарий для преобразования цветового пространства из YUV в RGB.
rs_allocation gIn;

void yuvToRgb_greyscale(const uchar *v_in, uchar4 *v_out, uint32_t x, uint32_t y) {
    uchar yp = rsGetElementAtYuv_uchar_Y(gIn , x, y) & 0xFF;

    uchar4 res4;
    res4.r = yp;
    res4.g = yp;
    res4.b = yp;
    res4.a = 0xFF;

    *v_out = res4;
}

 

Заключение

Платформа Android Multimedia Framework предоставляет высокоуровневый API для использования аппаратной поддержки мультимедиа. Обработка видео является весьма ресурсоемкой нагрузкой, и Renderscript предоставляет платформу для распараллеливания этой нагрузки.  В приведенной выше статье описывается метод, позволяющий платформе Android Multimedia Framework взаимодействовать с Renderscript для применения эффектов постобработки к декодированному видео.

Для публикаций и участия в обсуждении этой статьи можно использовать форум


Viewing all articles
Browse latest Browse all 357

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>