Skip to content

Commit

Permalink
Add mp4 box
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaoba committed Oct 23, 2016
1 parent d7268cd commit 69ff2f6
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 11 deletions.
22 changes: 16 additions & 6 deletions app/src/main/java/com/mushuichuan/mediacodecdemo/MainActivity.java
Expand Up @@ -15,13 +15,15 @@
import android.widget.Button;
import android.widget.TextView;

import com.mushuichuan.mediacodecdemo.Mp4.Mp4Extractor;

public class MainActivity extends AppCompatActivity {
SurfaceView mSurfaceView;
private static String SAMPLE = Environment.getExternalStorageDirectory() + "/DCIM/Camera/20161013_140201.mp4";
private static String mFilePath = Environment.getExternalStorageDirectory() + "/DCIM/Camera/20161013_140201.mp4";
SurfaceRender mSurfaceRender;
FileVideoDecoder mFileDecoder;
TextView mFilePathText;
private Button mFileButton, mRenderButton, mChooseButton;
private Button mFileButton, mRenderButton, mChooseButton,mSelfDefineButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -35,7 +37,7 @@ protected void onCreate(Bundle savedInstanceState) {
mSurfaceRender = new SurfaceRender(mSurfaceView.getHolder().getSurface());

mFilePathText = (TextView) findViewById(R.id.file_path);
mFilePathText.setText(SAMPLE);
mFilePathText.setText(mFilePath);
mFileButton = (Button) findViewById(R.id.button);
mFileButton.setOnClickListener(new View.OnClickListener() {
@Override
Expand All @@ -55,12 +57,20 @@ public void onClick(View v) {
if (mFileDecoder.isPlaying()) {
mFileDecoder.stop();
} else {
mFileDecoder.start(SAMPLE);
mFileDecoder.start(mFilePath);
}

}
});

mSelfDefineButton = (Button) findViewById(R.id.self_define_button);
mSelfDefineButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Mp4Extractor mp4Extractor=new Mp4Extractor();
mp4Extractor.setDataSource(mFilePath);
}
});
mChooseButton = (Button) findViewById(R.id.decode_file_button);
mChooseButton.setOnClickListener(new View.OnClickListener() {
@Override
Expand All @@ -79,8 +89,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = data.getData();
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor.moveToFirst()) {
SAMPLE = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
mFilePathText.setText(SAMPLE);
mFilePath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
mFilePathText.setText(mFilePath);
}

}
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/mushuichuan/mediacodecdemo/Mp4/FtypBox.java
@@ -0,0 +1,13 @@
package com.mushuichuan.mediacodecdemo.Mp4;

/**
* Created by yanshun.li on 10/23/16.
*/

public class FtypBox extends Mp4Box {

public FtypBox() {
hasSubBox = false;
headSize = 12;
}
}
65 changes: 65 additions & 0 deletions app/src/main/java/com/mushuichuan/mediacodecdemo/Mp4/Mp4Box.java
@@ -0,0 +1,65 @@
package com.mushuichuan.mediacodecdemo.Mp4;

import com.mushuichuan.mediacodecdemo.Logger;

import java.util.ArrayList;

/**
* head:
* 4 bytes size
* 4 bytes type
* 1 bytes version for ftyp
* 3 bytes flags for ftyp
* 8 bytes largesize (if siz==0)
* 16 bytes UUIDs (if type==uuid)
* Created by yanshun.li on 10/20/16.
*/

public class Mp4Box {
public int headSize = 8;
public int size;
public String type;
public long largeSize;
public ArrayList<Mp4Box> subBox = new ArrayList<>();
public boolean hasSubBox = false;

public Mp4Box() {
}

public Mp4Box parse(byte[] byteBuffer, int start, int end) {
size = end - start;
if (size == 1) {
largeSize = Util.get64LongFromBuffer(byteBuffer, 8);
headSize += 8;
} else if (size == 0) {
//box extends to the end of file
}
String type = Util.getStringFromBuffer(byteBuffer, start + 4, 4);
if (type.equals("uuid")) {
headSize += 16;
}
Logger.d(type + " size:" + size);


// there is no sub boxs
if (!hasSubBox) {
return this;
}

start += headSize;
// String test = Util.getStringFromBuffer(byteBuffer, start, 1024);
long totalLength = 0;
do {
int len = Util.get32IntFromBuffer(byteBuffer, start);
type = Util.getStringFromBuffer(byteBuffer, start + 4, 4);
if (len > 8) {
subBox.add(new Mp4Box().parse(byteBuffer, start, start + len));
totalLength += len;
start += len;
} else {
break;
}
} while (totalLength < end);
return this;
}
}
@@ -0,0 +1,20 @@
package com.mushuichuan.mediacodecdemo.Mp4;

/**
* Created by yanshun.li on 10/23/16.
*/

public class Mp4Extractor {

public Mp4Extractor() {

}

public void setDataSource(String path){
byte[] ftyps = Util.getBoxBuffer(path, "ftyp");
Mp4Box ftypBox = new FtypBox().parse(ftyps, 0, ftyps.length);

byte[] moovs = Util.getBoxBuffer(path, "moov");
Mp4Box moovBox = new Mp4Box().parse(moovs, 0, moovs.length);
}
}
95 changes: 95 additions & 0 deletions app/src/main/java/com/mushuichuan/mediacodecdemo/Mp4/Util.java
@@ -0,0 +1,95 @@
package com.mushuichuan.mediacodecdemo.Mp4;

import com.mushuichuan.mediacodecdemo.Logger;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
* Created by yanshun.li on 10/20/16.
*/

public class Util {
public static final int FOUR_BYTES = 4;
public static final int EIGHT_BYTES = 8;
public static final int BITS_PER_BYTE = 8;

public static byte[] getBoxBuffer(String path, String type) {
InputStream in;
byte[] boxBuffer = new byte[0];
try {
in = new FileInputStream(path);
} catch (FileNotFoundException e) {
return null;
}
try {
while (true) {
//read length and type
byte[] lenTypeBuffer = new byte[FOUR_BYTES * 2];
in.read(lenTypeBuffer);

int length = get32IntFromBuffer(lenTypeBuffer, 0);
String boxType = getStringFromBuffer(lenTypeBuffer, FOUR_BYTES, FOUR_BYTES);

if (type.equals(boxType)) {
boxBuffer = new byte[length];
System.arraycopy(lenTypeBuffer, 0, boxBuffer, 0, lenTypeBuffer.length);
int reade = lenTypeBuffer.length;

do {
int len = in.read(boxBuffer, reade, length - reade);
reade += len;
} while (reade < length);
break;
} else {
in.skip(length - FOUR_BYTES * 2);
continue;
}

}
} catch (IOException e) {
Logger.e(e);
}

return boxBuffer;
}

public static int get32IntFromBuffer(byte[] buffer, int start) {
int result = 0;
if (buffer.length - start >= FOUR_BYTES) {
for (int i = 0; i < FOUR_BYTES; i++) {
result |= (buffer[start + i] & 0xff) << BITS_PER_BYTE * (FOUR_BYTES - i - 1);
}
}
return result;
}

public static long get64LongFromBuffer(byte[] buffer, int start) {
long result = 0;
if (buffer.length - start >= FOUR_BYTES) {
for (int i = 0; i < EIGHT_BYTES; i++) {
result |= (buffer[start + i] & 0xff) << BITS_PER_BYTE * (EIGHT_BYTES - i - 1);
}
}
return result;
}

/**
* @param buffer
* @param start
* @param size
* @return
*/
public static String getStringFromBuffer(byte[] buffer, int start, int size) {
char[] result = new char[size];
if (buffer.length - start >= size) {
for (int i = 0; i < size; i++) {
result[i] = (char) (buffer[start + i] & 0xff);
}
}
return String.valueOf(result);
}

}
17 changes: 12 additions & 5 deletions app/src/main/res/layout/content_main.xml
Expand Up @@ -6,23 +6,25 @@
android:id="@+id/content_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.mushuichuan.mediacodecdemo.MainActivity"
tools:showIn="@layout/activity_main"
android:orientation="vertical">
tools:showIn="@layout/activity_main">

<SurfaceView
android:id="@+id/surface_view"
android:layout_width="wrap_content"
android:layout_height="300dp"/>

<TextView
android:id="@+id/file_path"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/file_path"/>
android:layout_height="wrap_content"/>

<Button
android:id="@+id/button"
android:layout_width="match_parent"
Expand All @@ -35,12 +37,17 @@
android:layout_height="wrap_content"
android:text="Decode File"/>

<Button
android:id="@+id/self_define_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Self define decode File"/>

<Button
android:id="@+id/choose_file_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Choose File"/>



</LinearLayout>

0 comments on commit 69ff2f6

Please sign in to comment.