Android 的视频编码 H263 MP4V H264

编码器使用的是x264的开源库,

 

很容易看懂的

简单的封装了一个JNI库

 

编码库在BBS里 CSDN的资源太难用了

http://www.eoeandroid.com/forum.php?mod=viewthread&tid=52739&extra=

 

x264的编译放方法

 

export ARM_ROOT=$ANDROID_NDK_ROOT
export ARM_INC=$ARM_ROOT/build/platforms/android-5/arch-arm/usr/include/
export ARM_LIB=$ARM_ROOT/build/platforms/android-5/arch-arm/usr/lib/
export ARM_TOOL=$ARM_ROOT/build/prebuilt/windows/arm-eabi-4.4.0
export ARM_LIBO=$ARM_TOOL/lib/gcc/arm-eabi/4.4.0
export PATH=$ARM_TOOL/bin:$PATH
export ARM_PRE=arm-eabi

./configure --prefix=/home/egmkang/libx264 --enable-shared /
-disable-asm --host=arm-linux --cross-prefix=arm-eabi-/
--extra-cflags=" -I$ARM_INC -fPIC -DANDROID -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__  -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -DANDROID  -Wa,--noexecstack -MMD -MP "/
--extra-ldflags="-nostdlib -Bdynamic -Wl,--no-undefined -Wl,-z,noexecstack  -Wl,-z,nocopyreloc -Wl,-soname,/system/lib/libz.so -Wl,-rpath-link=$ARM_LIB,-dynamic-linker=/system/bin/linker -L$ARM_LIB -nostdlib $ARM_LIB/crtbegin_dynamic.o $ARM_LIB/crtend_android.o -lc -lm -ldl -lgcc"

这里生成的是x264的静态库

 

整个工程唯一有点麻烦的是 生成 JNI 动态库的时候 报错 。。

 

后来发现是少链接了一个库,

于是根据x264的编译方法 在Android.mk添加一些配置就可以了。当然这就是难点,在网上查了很多都没有结果。

 

有些目录的参数自己调整哈

我把前面生成的libx264.a 和 x264.h 文件放到jni的libx264目录下了 有问题自己调整

 

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES +=$(LOCAL_PATH)/libx264/include
LOCAL_MODULE    := H264Android
LOCAL_SRC_FILES := H264Android.c 
LOCAL_LDFLAGS += $(LOCAL_PATH)/libx264/lib/libx264.a
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -lgcc


include $(BUILD_SHARED_LIBRARY)

 

 

 

估计很多人都会发现很熟悉 嘻嘻 这个就是根据

http://www.cnblogs.com/mcodec/articles/1780598.html

改的 连文件名字都没有换!!比较懒

 

 

 

另: 编码的效率很低下啊

 

 

AndroidVideo.java

[java]  view plain copy
  1. import java.io.File;  
  2. import java.io.RandomAccessFile;  
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.content.res.Configuration;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10. import android.view.SurfaceHolder;  
  11. import android.view.SurfaceView;  
  12. import android.view.Window;  
  13. import android.view.WindowManager;  
  14. import android.view.SurfaceHolder.Callback;  
  15. import android.graphics.PixelFormat;  
  16. import android.hardware.Camera;  
  17. public class AndroidVideo extends Activity implements Callback,  
  18.         Camera.PictureCallback {  
  19.     private SurfaceView mSurfaceView = null;  
  20.     private SurfaceHolder mSurfaceHolder = null;  
  21.     private Camera mCamera = null;  
  22.     private boolean mPreviewRunning = false;  
  23.     public void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         getWindow().setFormat(PixelFormat.TRANSLUCENT);  
  26.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  27.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  28.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  29.         setContentView(R.layout.camera);  
  30.         mSurfaceView = (SurfaceView) this.findViewById(R.id.surface_camera);  
  31.         mSurfaceHolder = mSurfaceView.getHolder();  
  32.         mSurfaceHolder.addCallback(this);  
  33.         mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  34.     }  
  35.       
  36.     @Override  
  37.     public void onPictureTaken(byte[] data, Camera camera) {  
  38.     }  
  39.     @Override  
  40.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  41.             int height) {  
  42.         if (mPreviewRunning) {  
  43.             mCamera.stopPreview();  
  44.         }  
  45.         Camera.Parameters p = mCamera.getParameters();  
  46.         p.setPreviewSize(352288);  
  47.         mCamera.setPreviewCallback(new H264Encoder(352288));  
  48.         mCamera.setParameters(p);  
  49.         try {  
  50.             mCamera.setPreviewDisplay(holder);  
  51.         } catch (Exception ex) {  
  52.         }  
  53.         mCamera.startPreview();  
  54.         mPreviewRunning = true;  
  55.     }  
  56.     @Override  
  57.     public void surfaceCreated(SurfaceHolder holder) {  
  58.         mCamera = Camera.open();  
  59.     }  
  60.     @Override  
  61.     public void surfaceDestroyed(SurfaceHolder holder) {  
  62.         if (mCamera != null) {  
  63.             mCamera.setPreviewCallback(null);  
  64.             mCamera.stopPreview();  
  65.             mPreviewRunning = false;  
  66.             mCamera.release();  
  67.             mCamera = null;  
  68.         }  
  69.     }  
  70.     public void onConfigurationChanged(Configuration newConfig) {  
  71.         try {  
  72.             super.onConfigurationChanged(newConfig);  
  73.             if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {  
  74.             } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {  
  75.             }  
  76.         } catch (Exception ex) {  
  77.         }  
  78.     }  
  79. }  
  80. class H264Encoder implements Camera.PreviewCallback {  
  81.     long encoder=0;  
  82.     RandomAccessFile raf=null;  
  83.     byte[] h264Buff =null;  
  84.     static {  
  85.         System.loadLibrary("H264Android");  
  86.     }  
  87.     private H264Encoder(){};  
  88.       
  89.     public H264Encoder(int width, int height) {  
  90.         encoder = CompressBegin(width, height);  
  91.         h264Buff = new byte[width * height *8];  
  92.         try {  
  93.             File file = new File("/sdcard/camera.h264");  
  94.             raf = new RandomAccessFile(file, "rw");  
  95.         } catch (Exception ex) {  
  96.             Log.v("System.out", ex.toString());  
  97.         }  
  98.           
  99.     };  
  100.     protected void finalize()  
  101.     {  
  102.         CompressEnd(encoder);  
  103.         if (null != raf)  
  104.         {  
  105.             try {  
  106.                 raf.close();  
  107.             } catch (Exception ex) {  
  108.                 Log.v("System.out", ex.toString());  
  109.             }  
  110.         }  
  111.         try {  
  112.             super.finalize();  
  113.         } catch (Throwable e) {  
  114.             // TODO Auto-generated catch block  
  115.             e.printStackTrace();  
  116.         }  
  117.     }  
  118.     private native long CompressBegin(int width,int height);  
  119.     private native int CompressBuffer(long encoder, int type,byte[] in, int insize,byte[] out);  
  120.     private native int CompressEnd(long encoder);  
  121.     @Override  
  122.     public void onPreviewFrame(byte[] data, Camera camera) {      
  123.           
  124.         int result=CompressBuffer(encoder, -1, data, data.length,h264Buff);  
  125.         try {  
  126.             if (result>0)  
  127.                 raf.write(h264Buff, 0, result);  
  128.         } catch (Exception ex) {  
  129.             Log.v("System.out", ex.toString());  
  130.         }  
  131.     }  
  132.       
  133. }  

 

 

H264Android.c

[cpp]  view plain copy
  1. #include <string.h>  
  2. #include <jni.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <arpa/inet.h>  
  6. #include <x264.h>  
  7. #define DATA_MAX 3000000  
  8. #define H264_MTU 1024  
  9. typedef struct  
  10. {  
  11.     x264_param_t * param;  
  12.     x264_t *handle;  
  13.     x264_picture_t * picture;  
  14.     x264_nal_t  *nal;  
  15. } Encoder;  
  16. jlong Java_h264_com_H264Encoder_CompressBegin(JNIEnv* env, jobject thiz,  
  17.         jint width, jint height) {  
  18.     Encoder * en = (Encoder *) malloc(sizeof(Encoder));  
  19.     en->param = (x264_param_t *) malloc(sizeof(x264_param_t));  
  20.     en->picture = (x264_param_t *) malloc(sizeof(x264_picture_t));  
  21.     x264_param_default(en->param); //set default param  
  22.     //en->param->rc.i_rc_method = X264_RC_CQP;  
  23.     en->param->i_log_level = X264_LOG_NONE;  
  24.     en->param->i_width = width; //set frame width  
  25.     en->param->i_height = height; //set frame height  
  26.     en->param->rc.i_lookahead =0;  
  27.     en->param->i_bframe=0;  
  28.     en->param->i_fps_num =5;  
  29.     en->param->i_fps_den = 1;  
  30.     if ((en->handle = x264_encoder_open(en->param)) == 0) {  
  31.         return 0;  
  32.     }  
  33.     /* Create a new pic */  
  34.     x264_picture_alloc(en->picture, X264_CSP_I420, en->param->i_width,  
  35.             en->param->i_height);  
  36.     return (jlong) en;  
  37. }  
  38. jint Java_h264_com_H264Encoder_CompressEnd(JNIEnv* env, jobject thiz,jlong handle)  
  39. {  
  40.     Encoder * en = (Encoder *) handle;  
  41.     if(en->picture)  
  42.     {  
  43.         x264_picture_clean(en->picture);  
  44.         free(en->picture);  
  45.         en->picture  = 0;  
  46.     }  
  47.     if(en->param)  
  48.     {  
  49.         free(en->param);  
  50.         en->param=0;  
  51.     }  
  52.     if(en->handle)  
  53.     {  
  54.         x264_encoder_close(en->handle);  
  55.     }  
  56.     free(en);  
  57.     return 0;  
  58. }  
  59. jint Java_h264_com_H264Encoder_CompressBuffer(JNIEnv* env, jobject thiz,jlong handle,jint type,jbyteArray in, jint insize,jbyteArray out)  
  60. {  
  61.     Encoder * en = (Encoder *) handle;  
  62.     x264_picture_t pic_out;  
  63.     int i_data=0;  
  64.     int nNal=-1;  
  65.     int result=0;  
  66.     int i=0,j=0;  
  67.     int nPix=0;  
  68.     jbyte * Buf = (jbyte*)(*env)->GetByteArrayElements(env, in, 0);  
  69.     jbyte * h264Buf = (jbyte*)(*env)->GetByteArrayElements(env, out, 0);  
  70.     unsigned char * pTmpOut = h264Buf;  
  71.     int nPicSize=en->param->i_width*en->param->i_height;  
  72.     /* 
  73.     Y数据全部从在一块,UV数据使用interleave方式存储 
  74.     YYYY 
  75.     YYYY 
  76.     UVUV 
  77.      */  
  78.     jbyte * y=en->picture->img.plane[0];  
  79.     jbyte * v=en->picture->img.plane[1];  
  80.     jbyte * u=en->picture->img.plane[2];  
  81.     memcpy(en->picture->img.plane[0],Buf,nPicSize);  
  82.     for (i=0;i<nPicSize/4;i++)  
  83.     {  
  84.         *(u+i)=*(Buf+nPicSize+i*2);  
  85.         *(v+i)=*(Buf+nPicSize+i*2+1);  
  86.     }  
  87.     switch (type)  
  88.     {  
  89.     case 0:  
  90.         en->picture->i_type = X264_TYPE_P;  
  91.         break;  
  92.     case 1:  
  93.         en->picture->i_type = X264_TYPE_IDR;  
  94.         break;  
  95.     case 2:  
  96.         en->picture->i_type = X264_TYPE_I;  
  97.         break;  
  98.     default:  
  99.         en->picture->i_type = X264_TYPE_AUTO;  
  100.         break;  
  101.     }  
  102.     if( x264_encoder_encode( en->handle, &(en->nal), &nNal, en->picture ,&pic_out) < 0 )  
  103.     {  
  104.         return -1;  
  105.     }  
  106.     for (i = 0; i < nNal; i++){  
  107.           memcpy(pTmpOut, en->nal[i].p_payload, en->nal[i].i_payload);  
  108.           pTmpOut += en->nal[i].i_payload;  
  109.           result+=en->nal[i].i_payload;  
  110.     }  
  111.     return result;  
  112. }  



上一篇我说了如何使用JNI进行h264编码,但是由于效率的问题 感觉并不太实用。

经过几天的折腾,并参照http://www.javaeye.com/problems/27244 大体实现的Android 的实时编码问题,但是只是思路,还没有进入代码实现的阶段。

 

比较重要的2个类 MediaRecorder ParcelFileDescriptor

 

MediaRecorder 是Android提供的进行采集编码的类,而 ParcelFileDescriptor是个用Socket实现 setOutputFile的一个类

 

在测试liuzongan 的程序的过程中,发现其他这位仁兄已经实现了我们需要的大部分的功能,唯一要处理的就是在服务器端的程序。

 

在这里我先猜测一下MediaRecorder写文件的过程

 

1 , MediaRecorder写入一个固定的头,估计是占位用的 都是00H( 占位的长度好像和使用的编码器有关系)

再插入 00 00 00 08 6D 64 61 74 (mdat box)


2,开始编码,并把编码后的没一个帧都添加到文件中,看到00 00 80了没, 了解h263的同志一定很熟悉,根本就是263视频的标志吗!

(如果有音频数据的话,很定会和视频数据交错在一起,但是我们的目标只是实时编码视频流,不需要处理音频,所以在初始化 MediaRecorder的时候我不不要 MediaRecorder.setAudioSource,这样就没有音频数据了。)

 

3 结束捕获。 MediaRecorder应该会返回到文件的头部填充文件头。但由于不是真正文件的关系,不能返回到头部,于是就把文件头附加到文件的后面了,感觉也就是 liuzongan 这仁兄提出的问题的答案了。

 

这个是,文件开头mdat box的长度,用于替换 00 00 00 08.

 

 

这个是3gp文件的头, 用于替换开头的占位。

 

 

4最后, MediaRecorder补充3gp文件的moov box ,这一部分已经属于3gp的媒体索引部分了,具体的内容对于我们来说已经不太关心了。大家可以参照http://www.cnitblog.com/zouzheng/archive/2007/04/04/25155.html 研究。

 

 

 

 

 

 

 

 

下开始说我们要是实现的内容了

 

其实有了上面的描述,大家应该能想到我们要实现的其实就是视频的分帧就可以了。。

 

server 端处理h263的方法

 

1一步 找到 mdat这个串, 后面的数据就是我们要的视频数据了,

 

2在流中查找 00 00 80 这个标志,每一个都是一帧数据的开始

 

 

对于 h264和mpeg4的,要预采集一次数据,这是因为mp4v的相关解码参数,在esds box中的, 而esds box 是在采集结束后才写入的,所以对于我们的程序来说需要先编码一次 获取 mp4v的相关解码参数,然后在用相同的参数进行采集, 呵呵 这样我们就能获得原始的mp4v流了

 

 

h264一样  不过是存在了 avcC box 里

 

 

 

 

 

 

最近很多同学问我SPS和PPS在那里设置,其实这篇文章只是我 上篇文章的一个简单实现 

 

具体情况情看看上一篇

 

http://blog.csdn.net/zblue78/archive/2010/12/15/6078040.aspx

 

 这里只用HTC的G7做了H264的程序,谅解!

 

csdn的资源慢了 粘代码算了

 

资源 http://download.csdn.net/source/2918751

 

 

 

欢迎大家经常访问我的blog http://blog.csdn.net/zblue78/

共同探讨,啥也不说的 直接上码

AndroidManifest.xml

 

[xhtml]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="com.zjzhang"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">  
  7.         <activity android:name=".VideoCameraActivity"  
  8.                  android:screenOrientation="landscape"  
  9.                   android:label="@string/app_name">  
  10.             <intent-filter>  
  11.                 <action android:name="android.intent.action.MAIN" />  
  12.                 <category android:name="android.intent.category.LAUNCHER" />  
  13.             </intent-filter>  
  14.         </activity>  
  15.     </application>  
  16.    <uses-sdk android:minSdkVersion="3" />  
  17.     <uses-permission android:name="android.permission.INTERNET"/>  
  18.     <uses-permission android:name="android.permission.CAMERA"/>  
  19.     <uses-permission android:name="android.permission.RECORD_VIDEO"/>  
  20.     <uses-permission android:name="android.permission.RECORD_AUDIO"/>  
  21.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
  22. </manifest>   

main.xml

 

[xhtml]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.     <SurfaceView   
  8.             android:id="@+id/surface_camera"  
  9.             android:layout_width="176px"  
  10.             android:layout_height="144px"  
  11.             android:layout_alignParentRight="true"  
  12.             android:layout_alignParentTop="true"  
  13.     />   
  14. </LinearLayout>  

 

[java]  view plain copy
  1. package com.zjzhang;  
  2. import java.io.DataInputStream;  
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.RandomAccessFile;  
  7. import android.app.Activity;  
  8. import android.content.Context;  
  9. import android.os.Bundle;  
  10. import android.graphics.PixelFormat;  
  11. import android.media.MediaRecorder;  
  12. import android.net.LocalServerSocket;  
  13. import android.net.LocalSocket;  
  14. import android.net.LocalSocketAddress;  
  15. import android.util.Log;  
  16. import android.view.SurfaceHolder;  
  17. import android.view.SurfaceView;  
  18. import android.view.View;  
  19. import android.view.Window;  
  20. import android.view.WindowManager;  
  21. public class VideoCameraActivity extends Activity implements  
  22.         SurfaceHolder.Callback, MediaRecorder.OnErrorListener,  
  23.         MediaRecorder.OnInfoListener {  
  24.     private static final int mVideoEncoder =MediaRecorder.VideoEncoder.H264;  
  25.     private static final String TAG = "VideoCamera";  
  26.     LocalSocket receiver, sender;  
  27.     LocalServerSocket lss;  
  28.     private MediaRecorder mMediaRecorder = null;  
  29.     boolean mMediaRecorderRecording = false;  
  30.     private SurfaceView mSurfaceView = null;  
  31.     private SurfaceHolder mSurfaceHolder = null;  
  32.     Thread t;  
  33.     Context mContext = this;  
  34.     RandomAccessFile raf = null;  
  35.     @Override  
  36.     public void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.         getWindow().setFormat(PixelFormat.TRANSLUCENT);  
  39.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  40.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  41.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  42.         setContentView(R.layout.main);  
  43.         mSurfaceView = (SurfaceView) this.findViewById(R.id.surface_camera);  
  44.         SurfaceHolder holder = mSurfaceView.getHolder();  
  45.         holder.addCallback(this);  
  46.         holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  47.         mSurfaceView.setVisibility(View.VISIBLE);  
  48.         receiver = new LocalSocket();  
  49.         try {  
  50.             lss = new LocalServerSocket("VideoCamera");  
  51.             receiver.connect(new LocalSocketAddress("VideoCamera"));  
  52.             receiver.setReceiveBufferSize(500000);  
  53.             receiver.setSendBufferSize(500000);  
  54.             sender = lss.accept();  
  55.             sender.setReceiveBufferSize(500000);  
  56.             sender.setSendBufferSize(500000);  
  57.         } catch (IOException e) {  
  58.             finish();  
  59.             return;  
  60.         }  
  61.     }  
  62.     @Override  
  63.     public void onStart() {  
  64.         super.onStart();  
  65.     }  
  66.     @Override  
  67.     public void onResume() {  
  68.         super.onResume();  
  69.     }  
  70.     @Override  
  71.     public void onPause() {  
  72.         super.onPause();  
  73.         if (mMediaRecorderRecording) {  
  74.             stopVideoRecording();  
  75.             try {  
  76.                 lss.close();  
  77.                 receiver.close();  
  78.                 sender.close();  
  79.             } catch (IOException e) {  
  80.                 e.printStackTrace();  
  81.             }  
  82.         }  
  83.         finish();  
  84.     }  
  85.     private void stopVideoRecording() {  
  86.         Log.d(TAG, "stopVideoRecording");  
  87.         if (mMediaRecorderRecording || mMediaRecorder != null) {  
  88.             if (t != null)  
  89.                 t.interrupt();  
  90.             try {  
  91.                 raf.close();  
  92.             } catch (IOException e) {  
  93.                 // TODO Auto-generated catch block  
  94.                 e.printStackTrace();  
  95.             }  
  96.             releaseMediaRecorder();  
  97.         }  
  98.     }  
  99.     private void startVideoRecording() {  
  100.         Log.d(TAG, "startVideoRecording");  
  101.         (t = new Thread() {  
  102.             public void run() {  
  103.                 int frame_size = 1024;  
  104.                 byte[] buffer = new byte[1024 * 64];  
  105.                 int num, number = 0;  
  106.                 InputStream fis = null;  
  107.                 try {  
  108.                     fis = receiver.getInputStream();  
  109.                 } catch (IOException e1) {  
  110.                     return;  
  111.                 }  
  112.                 try {  
  113.                     Thread.currentThread().sleep(500);  
  114.                 } catch (InterruptedException e1) {  
  115.                     e1.printStackTrace();  
  116.                 }  
  117.                 number = 0;  
  118.                 releaseMediaRecorder();  
  119.                 //如果是H264或是MPEG_4_SP的就要在这里找到相应的设置参数的流  
  120.                 //avcC box H264的设置参数  
  121.                 //esds box MPEG_4_SP 的设置参数  
  122.                 //其实 如果分辨率 等数值不变的话,这些参数是不会变化的,  
  123.                 //那么我就只需要在第一次运行的时候确定就可以了  
  124.                 while (true) {  
  125.                     try {  
  126.                         num = fis.read(buffer, number, frame_size);  
  127.                         number += num;  
  128.                         if (num < frame_size) {  
  129.                             break;  
  130.                         }  
  131.                     } catch (IOException e) {  
  132.                         break;  
  133.                     }  
  134.                 }  
  135.                   
  136.                 initializeVideo();  
  137.                 number = 0;  
  138.                 // 重新启动捕获,以获取视频流  
  139.                 DataInputStream dis=new DataInputStream(fis);  
  140.                   
  141.                 //读取最前面的32个自己的空头  
  142.                 try {  
  143.                     dis.read(buffer,0,32);  
  144.                 } catch (IOException e1) {  
  145.                     // TODO Auto-generated catch block  
  146.                     e1.printStackTrace();  
  147.                 }  
  148.                   
  149.                   
  150.                 try {  
  151.                     File file = new File("/sdcard/stream.h264");  
  152.                     if (file.exists())  
  153.                         file.delete();  
  154.                     raf = new RandomAccessFile(file, "rw");  
  155.                 } catch (Exception ex) {  
  156.                     Log.v("System.out", ex.toString());  
  157.                 }                 
  158.                   
  159.                   
  160.                   
  161.                   
  162.                 //这些参数要对应我现在的视频设置,如果想变化的话需要去重新确定,  
  163.                 //当然不知道是不是不同的机器是不是一样,我这里只有一个HTC G7做测试。  
  164.                 byte[] h264sps={0x67,0x42,0x00,0x0C,(byte0x96,0x54,0x0B,0x04,(byte0xA2};  
  165.                 byte[] h264pps={0x68,(byte0xCE,0x38,(byte0x80};  
  166.                 byte[] h264head={0,0,0,1};  
  167.                 try {  
  168.                     raf.write(h264head);  
  169.                     raf.write(h264sps);  
  170.                     raf.write(h264head);  
  171.                     raf.write(h264pps);  
  172.                 } catch (IOException e1) {  
  173.                     // TODO Auto-generated catch block  
  174.                     e1.printStackTrace();  
  175.                 }  
  176.                 while (true)  
  177.                 {  
  178.                     try {  
  179.                         //读取每场的长度  
  180.                         int h264length=dis.readInt();  
  181.                         number =0;  
  182.                         raf.write(h264head);  
  183.                         while(number<h264length)  
  184.                         {  
  185.                             int lost=h264length-number;  
  186.                             num = fis.read(buffer,0,frame_size<lost?frame_size:lost);  
  187.                             Log.d(TAG,String.format("H264 %d,%d,%d", h264length,number,num));  
  188.                             number+=num;  
  189.                             raf.write(buffer, 0, num);  
  190.                         }  
  191.                     } catch (IOException e) {  
  192.                         break;  
  193.                     }  
  194.                 }  
  195.             }  
  196.         }).start();  
  197.     }  
  198.     private boolean initializeVideo() {  
  199.         if (mSurfaceHolder==null)  
  200.             return false;  
  201.         mMediaRecorderRecording = true;  
  202.         if (mMediaRecorder == null)  
  203.             mMediaRecorder = new MediaRecorder();  
  204.         else  
  205.             mMediaRecorder.reset();  
  206.         mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);  
  207.         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);  
  208.         mMediaRecorder.setVideoFrameRate(20);  
  209.         mMediaRecorder.setVideoSize(352288);  
  210.         mMediaRecorder.setVideoEncoder(mVideoEncoder);  
  211.         mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());  
  212.         mMediaRecorder.setMaxDuration(0);  
  213.         mMediaRecorder.setMaxFileSize(0);  
  214.         mMediaRecorder.setOutputFile(sender.getFileDescriptor());  
  215.         try {  
  216.             mMediaRecorder.setOnInfoListener(this);  
  217.             mMediaRecorder.setOnErrorListener(this);  
  218.             mMediaRecorder.prepare();  
  219.             mMediaRecorder.start();  
  220.         } catch (IOException exception) {  
  221.             releaseMediaRecorder();  
  222.             finish();  
  223.             return false;  
  224.         }  
  225.         return true;  
  226.     }  
  227.     private void releaseMediaRecorder() {  
  228.         Log.v(TAG, "Releasing media recorder.");  
  229.         if (mMediaRecorder != null) {  
  230.             if (mMediaRecorderRecording) {  
  231.                 try {  
  232.                     mMediaRecorder.setOnErrorListener(null);  
  233.                     mMediaRecorder.setOnInfoListener(null);  
  234.                     mMediaRecorder.stop();  
  235.                 } catch (RuntimeException e) {  
  236.                     Log.e(TAG, "stop fail: " + e.getMessage());  
  237.                 }  
  238.                 mMediaRecorderRecording = false;  
  239.             }  
  240.             mMediaRecorder.reset();  
  241.             mMediaRecorder.release();  
  242.             mMediaRecorder = null;  
  243.         }  
  244.     }  
  245.     @Override  
  246.     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {  
  247.         Log.d(TAG, "surfaceChanged");  
  248.         mSurfaceHolder = holder;  
  249.         if (!mMediaRecorderRecording) {  
  250.             initializeVideo();  
  251.             startVideoRecording();  
  252.         }  
  253.     }  
  254.     @Override  
  255.     public void surfaceCreated(SurfaceHolder holder) {  
  256.         Log.d(TAG, "surfaceCreated");  
  257.         mSurfaceHolder = holder;  
  258.     }  
  259.     @Override  
  260.     public void surfaceDestroyed(SurfaceHolder holder) {  
  261.         Log.d(TAG, "surfaceDestroyed");  
  262.         mSurfaceHolder = null;  
  263.     }  
  264.     @Override  
  265.     public void onInfo(MediaRecorder mr, int what, int extra) {  
  266.         switch (what) {  
  267.         case MediaRecorder.MEDIA_RECORDER_INFO_UNKNOWN:  
  268.             Log.d(TAG, "MEDIA_RECORDER_INFO_UNKNOWN");  
  269.             break;  
  270.         case MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED:  
  271.             Log.d(TAG, "MEDIA_RECORDER_INFO_MAX_DURATION_REACHED");  
  272.             break;  
  273.         case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED:  
  274.             Log.d(TAG, "MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED");  
  275.             break;  
  276.         }  
  277.     }  
  278.     @Override  
  279.     public void onError(MediaRecorder mr, int what, int extra) {  
  280.         if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {  
  281.             Log.d(TAG, "MEDIA_RECORDER_ERROR_UNKNOWN");  
  282.             finish();  
  283.         }  
  284.     }  
  285. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值