From 98ecefcc2309d1b5078a9cf3d27f5f78465b5310 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期日, 30 十一月 2025 10:36:47 +0800
Subject: [PATCH] 1.h264 完整 可以跑 ;提交相关文件
---
gradlew | 185 +++++++++++++
如何检查test.h264文件.md | 184 +++++++++++++
test.h264 | 0
check_h264.py | 209 ++++++++++++++
README_H264_CHECK.md | 120 ++++++++
gradlew.bat | 89 ++++++
keystore.properties | 4
7 files changed, 791 insertions(+), 0 deletions(-)
diff --git a/README_H264_CHECK.md b/README_H264_CHECK.md
new file mode 100644
index 0000000..3481192
--- /dev/null
+++ b/README_H264_CHECK.md
@@ -0,0 +1,120 @@
+# H264鏂囦欢妫�鏌ュ伐鍏蜂娇鐢ㄨ鏄�
+
+## 蹇�熸鏌�
+
+### 鏂规硶1: 鐩存帴浠庤澶囪矾寰勬鏌ワ紙濡傛灉鏂囦欢鍦ㄦ湰鍦帮級
+
+```bash
+python check_h264.py test.h264
+```
+
+### 鏂规硶2: 浠嶢ndroid璁惧涓嬭浇鏂囦欢鍚庢鏌�
+
+1. **杩炴帴Android璁惧骞跺惎鐢║SB璋冭瘯**
+
+2. **鏌ユ壘鏂囦欢璺緞**
+
+ Android璁惧涓婄殑鏂囦欢璺緞閫氬父鏄細
+ ```
+ /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264
+ ```
+
+ 鎴栬�呬娇鐢╝db鏌ユ壘锛�
+ ```bash
+ adb shell "find /sdcard -name test.h264 2>/dev/null"
+ ```
+
+3. **涓嬭浇鏂囦欢鍒版湰鍦�**
+ ```bash
+ adb pull /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264 ./test.h264
+ ```
+
+4. **杩愯妫�鏌ュ伐鍏�**
+ ```bash
+ python check_h264.py test.h264
+ ```
+
+## 妫�鏌ュ唴瀹�
+
+宸ュ叿浼氭鏌ヤ互涓嬪唴瀹癸細
+
+1. 鉁� **鏂囦欢鏄惁瀛樺湪**
+2. 鉁� **鏂囦欢澶у皬**锛堝簲璇ュぇ浜�100瀛楄妭锛�
+3. 鉁� **NALU鍗曞厓鏁伴噺**锛堣嚦灏戝簲璇ユ湁SPS/PPS + 1涓叧閿抚锛�
+4. 鉁� **鏄惁鍖呭惈SPS**锛堝簭鍒楀弬鏁伴泦锛屽繀闇�锛�
+5. 鉁� **鏄惁鍖呭惈PPS**锛堝浘鍍忓弬鏁伴泦锛屽繀闇�锛�
+6. 鉁� **鏄惁鍖呭惈IDR鍏抽敭甯�**锛堝繀闇�锛�
+7. 鉁� **鏄惁鏈夊涓抚**
+
+## 棰勬湡缁撴灉
+
+涓�涓彲浠ユ挱鏀剧殑H264鏂囦欢搴旇鍖呭惈锛�
+
+- 鉁� 鑷冲皯1涓猄PS (绫诲瀷7)
+- 鉁� 鑷冲皯1涓狿PS (绫诲瀷8)
+- 鉁� 鑷冲皯1涓狪DR鍏抽敭甯� (绫诲瀷5)
+- 鉁� 澶氫釜NALU鍗曞厓锛堝缓璁�>10涓級
+
+## 甯歌闂
+
+### Q: 鏂囦欢鍙湁1甯ф�庝箞鍔烇紵
+
+**A:** 杩欐槸涔嬪墠鐨勯棶棰樸�傜幇鍦ㄧ殑浠g爜宸茬粡淇锛�
+- 鉁� 姝g‘澶勭悊SPS/PPS閰嶇疆
+- 鉁� 鍦ㄥ叧閿抚鏃跺悎骞禨PS/PPS
+- 鉁� 鏀硅繘缂栫爜寰幆锛岀‘淇濆鐞嗘墍鏈夎緭鍑�
+- 鉁� 娣诲姞娓呯┖缂栫爜鍣ㄥ姛鑳�
+
+**寤鸿锛�**
+1. 閲嶆柊缂栬瘧骞惰繍琛屽簲鐢�
+2. 褰曞埗鑷冲皯3-5绉掕棰�
+3. 鍋滄缂栫爜鍚庢鏌ユ枃浠�
+
+### Q: 鏂囦欢鏃犳硶鎾斁鎬庝箞鍔烇紵
+
+**鍙兘鍘熷洜锛�**
+1. 鉂� 缂哄皯SPS/PPS - 妫�鏌ユ槸鍚﹁緭鍑轰簡閰嶇疆鏁版嵁
+2. 鉂� 鏂囦欢鏍煎紡閿欒 - 妫�鏌ユ槸鍚︽槸Annex-B鏍煎紡
+3. 鉂� 鍙湁1甯� - 妫�鏌ョ紪鐮佸惊鐜槸鍚︽甯稿伐浣�
+
+**瑙e喅鏂规锛�**
+1. 鏌ョ湅Logcat鏃ュ織锛屾悳绱� "H264Encoder"
+2. 妫�鏌ユ槸鍚︽湁 "SPS/PPS included" 鏃ュ織
+3. 妫�鏌ユ槸鍚︽湁 "Frame encoded" 鏃ュ織
+4. 浣跨敤姝ゅ伐鍏锋鏌ユ枃浠剁粨鏋�
+
+### Q: 濡備綍鎾斁H264鏂囦欢锛�
+
+鍙互浣跨敤浠ヤ笅鎾斁鍣細
+- **VLC Media Player**锛堟帹鑽愶級
+- **ffplay** (FFmpeg鑷甫)
+- **MPC-HC**
+- **PotPlayer**
+
+鐩存帴鍙屽嚮 `.h264` 鏂囦欢鎴栨嫋鏀惧埌鎾斁鍣ㄧ獥鍙e嵆鍙��
+
+## 璋冭瘯寤鸿
+
+濡傛灉鏂囦欢鏃犳硶鎾斁锛岃妫�鏌ワ細
+
+1. **鏌ョ湅Logcat鏃ュ織**
+ ```bash
+ adb logcat -s H264Encoder:D MainActivity:D
+ ```
+
+2. **妫�鏌ュ叧閿棩蹇�**
+ - "SPS/PPS included in key frame data" - 璇存槑SPS/PPS宸插悎骞�
+ - "Frame encoded: ..." - 璇存槑鏈夊抚杈撳嚭
+ - "Encoder output EOS" - 璇存槑姝e父缁撴潫
+
+3. **楠岃瘉鏂囦欢缁撴瀯**
+ ```bash
+ python check_h264.py test.h264
+ ```
+
+4. **浣跨敤hexdump鏌ョ湅鏂囦欢澶�**
+ ```bash
+ hexdump -C test.h264 | head -20
+ ```
+ 搴旇鐪嬪埌锛歚00 00 00 01` 鎴� `00 00 01`锛圓nnex-B璧峰鐮侊級
+
diff --git a/check_h264.py b/check_h264.py
new file mode 100644
index 0000000..307e7a2
--- /dev/null
+++ b/check_h264.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+H264鏂囦欢妫�鏌ュ伐鍏�
+妫�鏌ョ敓鎴愮殑test.h264鏂囦欢鏄惁绗﹀悎鎾斁瑕佹眰
+"""
+
+import os
+import sys
+
+def check_h264_file(file_path):
+ """妫�鏌264鏂囦欢鏄惁绗﹀悎鎾斁瑕佹眰"""
+ print(f"妫�鏌ユ枃浠�: {file_path}\n")
+
+ # 1. 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦�
+ if not os.path.exists(file_path):
+ print("鉂� 鏂囦欢涓嶅瓨鍦紒")
+ print(f" 棰勬湡璺緞: {file_path}")
+ print("\n鎻愮ず锛�")
+ print(" - 濡傛灉鏄疉ndroid璁惧锛岄渶瑕佸厛閫氳繃adb pull涓嬭浇鏂囦欢")
+ print(f" - 鎴栬�呭皢鏂囦欢澶嶅埗鍒板綋鍓嶇洰褰�")
+ return False
+
+ # 2. 妫�鏌ユ枃浠跺ぇ灏�
+ file_size = os.path.getsize(file_path)
+ print(f"鉁� 鏂囦欢澶у皬: {file_size} 瀛楄妭 ({file_size / 1024:.2f} KB)")
+
+ if file_size == 0:
+ print("鉂� 鏂囦欢涓虹┖锛�")
+ return False
+
+ if file_size < 100:
+ print("鈿狅笍 璀﹀憡: 鏂囦欢澶皬锛屽彲鑳藉彧鏈塖PS/PPS鎴�1甯ф暟鎹�")
+
+ # 3. 璇诲彇鏂囦欢鍐呭骞跺垎鏋�
+ try:
+ with open(file_path, 'rb') as f:
+ data = f.read()
+ except Exception as e:
+ print(f"鉂� 璇诲彇鏂囦欢澶辫触: {e}")
+ return False
+
+ # 妫�鏌ALU鍗曞厓
+ nal_start_code_3 = bytes([0x00, 0x00, 0x01])
+ nal_start_code_4 = bytes([0x00, 0x00, 0x00, 0x01])
+
+ nalu_list = []
+ i = 0
+
+ # 鏌ユ壘鎵�鏈塏ALU鍗曞厓
+ while i < len(data):
+ # 鏌ユ壘璧峰鐮�
+ found = False
+
+ # 鏌ユ壘4瀛楄妭璧峰鐮�
+ if i + 4 <= len(data) and data[i:i+4] == nal_start_code_4:
+ start_pos = i + 4
+ found = True
+ # 鏌ユ壘3瀛楄妭璧峰鐮�
+ elif i + 3 <= len(data) and data[i:i+3] == nal_start_code_3:
+ # 纭繚鍓嶉潰涓嶆槸0x00 (閬垮厤璇垽)
+ if i == 0 or data[i-1] != 0x00:
+ start_pos = i + 3
+ found = True
+
+ if found:
+ # 鏌ユ壘涓嬩竴涓捣濮嬬爜
+ next_start = -1
+
+ # 鍏堟壘4瀛楄妭璧峰鐮�
+ for j in range(start_pos, len(data) - 3):
+ if j + 4 <= len(data) and data[j:j+4] == nal_start_code_4:
+ next_start = j
+ break
+
+ # 濡傛灉娌℃壘鍒�4瀛楄妭鐨勶紝鎵�3瀛楄妭鐨�
+ if next_start == -1:
+ for j in range(start_pos, len(data) - 2):
+ if j + 3 <= len(data) and data[j:j+3] == nal_start_code_3:
+ # 纭繚鍓嶉潰涓嶆槸0x00
+ if j == 0 or data[j-1] != 0x00:
+ next_start = j
+ break
+
+ # 鎻愬彇NALU鏁版嵁
+ if next_start == -1:
+ nalu_data = data[start_pos:]
+ else:
+ nalu_data = data[start_pos:next_start]
+
+ if len(nalu_data) > 0:
+ # 鑾峰彇NALU绫诲瀷 (绗竴涓瓧鑺傜殑浣�5浣�)
+ nal_type = nalu_data[0] & 0x1F
+ nalu_list.append({
+ 'type': nal_type,
+ 'size': len(nalu_data),
+ 'name': get_nalu_type_name(nal_type)
+ })
+
+ i = next_start if next_start != -1 else len(data)
+ else:
+ i += 1
+
+ # 4. 鍒嗘瀽NALU鍗曞厓
+ print(f"\n鉁� 鎵惧埌 {len(nalu_list)} 涓狽ALU鍗曞厓\n")
+
+ if len(nalu_list) == 0:
+ print("鉂� 鏈壘鍒颁换浣昇ALU鍗曞厓锛佹枃浠舵牸寮忓彲鑳戒笉姝g‘")
+ return False
+
+ # 缁熻涓嶅悓绫诲瀷鐨凬ALU
+ nal_type_count = {}
+ for nalu in nalu_list:
+ nal_type = nalu['type']
+ if nal_type not in nal_type_count:
+ nal_type_count[nal_type] = 0
+ nal_type_count[nal_type] += 1
+
+ print("NALU绫诲瀷缁熻:")
+ for nal_type in sorted(nal_type_count.keys()):
+ count = nal_type_count[nal_type]
+ name = get_nalu_type_name(nal_type)
+ print(f" {name} (绫诲瀷{nal_type}): {count} 涓�")
+
+ # 5. 妫�鏌ュ叧閿姹�
+ print("\n妫�鏌ラ」:")
+
+ has_sps = 7 in nal_type_count
+ has_pps = 8 in nal_type_count
+ has_idr = 5 in nal_type_count
+ has_non_idr = 1 in nal_type_count
+
+ # SPS/PPS妫�鏌�
+ if has_sps:
+ print(f" 鉁� 鍖呭惈SPS (搴忓垪鍙傛暟闆�) - {nal_type_count[7]} 涓�")
+ else:
+ print(" 鉂� 缂哄皯SPS (搴忓垪鍙傛暟闆�) - 蹇呴渶锛�")
+
+ if has_pps:
+ print(f" 鉁� 鍖呭惈PPS (鍥惧儚鍙傛暟闆�) - {nal_type_count[8]} 涓�")
+ else:
+ print(" 鉂� 缂哄皯PPS (鍥惧儚鍙傛暟闆�) - 蹇呴渶锛�")
+
+ # 鍏抽敭甯ф鏌�
+ if has_idr:
+ print(f" 鉁� 鍖呭惈IDR鍏抽敭甯� - {nal_type_count[5]} 涓�")
+ else:
+ print(" 鉂� 缂哄皯IDR鍏抽敭甯�")
+
+ # 闈炲叧閿抚妫�鏌�
+ if has_non_idr:
+ print(f" 鉁� 鍖呭惈闈濱DR甯� - {nal_type_count[1]} 涓�")
+ else:
+ print(" 鈿狅笍 娌℃湁闈濱DR甯э紙鍙湁鍏抽敭甯э級")
+
+ # 6. 鎬讳綋璇勪及
+ print("\n" + "="*50)
+ can_play = has_sps and has_pps and has_idr
+
+ if can_play:
+ if len(nalu_list) >= 3:
+ print("鉁� 鏂囦欢搴旇鍙互鎾斁锛�")
+ print(f" 鍖呭惈瀹屾暣鐨凷PS/PPS鍜� {len(nalu_list)} 涓狽ALU鍗曞厓")
+ else:
+ print("鈿狅笍 鏂囦欢缁撴瀯瀹屾暣锛屼絾甯ф暟杈冨皯")
+ print(" 寤鸿褰曞埗鏇撮暱鏃堕棿浠ヨ幏寰楁洿澶氬抚")
+ else:
+ print("鉂� 鏂囦欢鍙兘鏃犳硶鎾斁")
+ if not has_sps or not has_pps:
+ print(" 鍘熷洜: 缂哄皯SPS/PPS鍙傛暟闆�")
+ if not has_idr:
+ print(" 鍘熷洜: 缂哄皯IDR鍏抽敭甯�")
+
+ print("="*50)
+
+ return can_play
+
+def get_nalu_type_name(nal_type):
+ """鑾峰彇NALU绫诲瀷鍚嶇О"""
+ nal_names = {
+ 1: "闈濱DR缂栫爜鐗�",
+ 2: "缂栫爜鐗囨暟鎹垎鍖篈",
+ 3: "缂栫爜鐗囨暟鎹垎鍖築",
+ 4: "缂栫爜鐗囨暟鎹垎鍖篊",
+ 5: "IDR鍥惧儚缂栫爜鐗�",
+ 6: "SEI (琛ュ厖澧炲己淇℃伅)",
+ 7: "SPS (搴忓垪鍙傛暟闆�)",
+ 8: "PPS (鍥惧儚鍙傛暟闆�)",
+ 9: "璁块棶鍗曞厓鍒嗛殧绗�",
+ 10: "搴忓垪缁撴潫",
+ 11: "娴佺粨鏉�",
+ 12: "濉厖鏁版嵁"
+ }
+ return nal_names.get(nal_type, f"鏈煡绫诲瀷{nal_type}")
+
+if __name__ == "__main__":
+ # 榛樿鏂囦欢璺緞
+ default_path = "test.h264"
+
+ # 濡傛灉鎻愪緵浜嗗懡浠よ鍙傛暟锛屼娇鐢ㄥ弬鏁颁綔涓烘枃浠惰矾寰�
+ file_path = sys.argv[1] if len(sys.argv) > 1 else default_path
+
+ print("H264鏂囦欢妫�鏌ュ伐鍏�")
+ print("="*50)
+
+ success = check_h264_file(file_path)
+
+ sys.exit(0 if success else 1)
+
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# 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
+#
+# https://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.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/keystore.properties b/keystore.properties
new file mode 100644
index 0000000..4504553
--- /dev/null
+++ b/keystore.properties
@@ -0,0 +1,4 @@
+storePassword = 123456
+keyPassword = 123456
+keyAlias = key0
+storeFile = ../key/key.jks
\ No newline at end of file
diff --git a/test.h264 b/test.h264
new file mode 100644
index 0000000..6d2cdb8
--- /dev/null
+++ b/test.h264
Binary files differ
diff --git "a/\345\246\202\344\275\225\346\243\200\346\237\245test.h264\346\226\207\344\273\266.md" "b/\345\246\202\344\275\225\346\243\200\346\237\245test.h264\346\226\207\344\273\266.md"
new file mode 100644
index 0000000..8058f55
--- /dev/null
+++ "b/\345\246\202\344\275\225\346\243\200\346\237\245test.h264\346\226\207\344\273\266.md"
@@ -0,0 +1,184 @@
+# 濡備綍妫�鏌est.h264鏂囦欢鑳藉惁鎾斁
+
+## 蹇�熷垽鏂柟娉�
+
+### 鏂规硶1: 鐩存帴鐢ㄦ挱鏀惧櫒娴嬭瘯锛堟渶绠�鍗曪級
+
+1. **浠嶢ndroid璁惧涓嬭浇鏂囦欢**
+ ```bash
+ adb pull /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264 ./test.h264
+ ```
+
+2. **鐢╒LC鎾斁鍣ㄦ墦寮�**
+ - 涓嬭浇VLC: https://www.videolan.org/vlc/
+ - 鐩存帴鍙屽嚮 `test.h264` 鏂囦欢
+ - 鎴栬�呮嫋鏀惧埌VLC绐楀彛
+
+3. **濡傛灉鑳芥挱鏀�** 鉁�
+ - 璇存槑鏂囦欢鏍煎紡姝g‘
+ - 鍙互鐪嬪埌瑙嗛鍐呭
+
+4. **濡傛灉涓嶈兘鎾斁** 鉂�
+ - 鍙兘缂哄皯SPS/PPS
+ - 鍙兘鍙湁1甯�
+ - 鍙兘鏍煎紡閿欒
+
+### 鏂规硶2: 浣跨敤Python宸ュ叿妫�鏌ワ紙璇︾粏鍒嗘瀽锛�
+
+1. **纭繚瀹夎浜哖ython** (Python 3.6+)
+
+2. **涓嬭浇鏂囦欢鍒版湰鍦�**
+ ```bash
+ adb pull /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264 ./test.h264
+ ```
+
+3. **杩愯妫�鏌ュ伐鍏�**
+ ```bash
+ python check_h264.py test.h264
+ ```
+
+4. **鏌ョ湅妫�鏌ョ粨鏋�**
+
+ 鉁� **鍙互鎾斁鐨勬爣蹇楋細**
+ - 鉁� 鍖呭惈SPS (搴忓垪鍙傛暟闆�)
+ - 鉁� 鍖呭惈PPS (鍥惧儚鍙傛暟闆�)
+ - 鉁� 鍖呭惈IDR鍏抽敭甯�
+ - 鉁� 鏈夊涓狽ALU鍗曞厓锛堝缓璁�>10涓級
+
+ 鉂� **涓嶈兘鎾斁鐨勬爣蹇楋細**
+ - 缂哄皯SPS鎴朠PS
+ - 鍙湁1-2涓狽ALU鍗曞厓
+ - 鏂囦欢澶皬锛�<100瀛楄妭锛�
+
+### 鏂规硶3: 浣跨敤ffprobe妫�鏌ワ紙濡傛灉瀹夎浜咶Fmpeg锛�
+
+```bash
+ffprobe test.h264
+```
+
+濡傛灉鑳芥纭樉绀鸿棰戜俊鎭紙鍒嗚鲸鐜囥�佸抚鐜囩瓑锛夛紝璇存槑鏂囦欢鍙互鎾斁銆�
+
+### 鏂规硶4: 鏌ョ湅鏂囦欢澶у皬锛堢矖鐣ュ垽鏂級
+
+```bash
+# 鍦ˋndroid璁惧涓�
+adb shell "ls -lh /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264"
+```
+
+**鍙傝�冩爣鍑嗭細**
+- 鉁� **鍙互鎾斁**锛氶�氬父 > 10KB锛�640x480@25fps锛�3绉掔害30-50KB锛�
+- 鈿狅笍 **鍙兘鍙湁1甯�**锛�< 5KB
+- 鉂� **鏂囦欢寮傚父**锛�= 0KB
+
+## 妫�鏌ユ枃浠跺唴瀹癸紙楂樼骇锛�
+
+### 浣跨敤hexdump鏌ョ湅鏂囦欢澶�
+
+```bash
+hexdump -C test.h264 | head -20
+```
+
+**姝e父鏂囦欢搴旇鐪嬪埌锛�**
+```
+00000000 00 00 00 01 67 64 00 1f ac 72 84 44 26 84 00 00 |....gd...r.D&...|
+00000010 00 01 00 00 00 01 68 ee 3c b0 44 00 00 00 01 06 |......h.<.D.....|
+```
+
+- `00 00 00 01` = Annex-B璧峰鐮侊紙4瀛楄妭锛�
+- `67` = SPS鐨凬ALU绫诲瀷锛�0x67 & 0x1F = 7锛�
+- `68` = PPS鐨凬ALU绫诲瀷锛�0x68 & 0x1F = 8锛�
+
+### 浣跨敤adb鍦ㄨ澶囦笂鐩存帴妫�鏌�
+
+```bash
+# 妫�鏌ユ枃浠跺ぇ灏�
+adb shell "stat -c '%s' /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264"
+
+# 鏌ョ湅鏂囦欢鍓�50瀛楄妭
+adb shell "hexdump -C /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264 | head -5"
+```
+
+## 甯歌闂璇婃柇
+
+### 鉂� 闂1: 鏂囦欢鍙湁1甯с��0绉�
+
+**鍘熷洜锛�**
+- 缂栫爜鍣ㄨ緭鍑哄鐞嗕笉瀹屾暣
+- SPS/PPS娌℃湁姝g‘鍐欏叆
+- 缂栫爜寰幆鎻愬墠閫�鍑�
+
+**瑙e喅鏂规锛�**
+鉁� 宸茬粡淇锛佹柊浠g爜鍖呭惈锛�
+- 姝g‘澶勭悊SPS/PPS閰嶇疆鏁版嵁
+- 鍦ㄥ叧閿抚鏃跺悎骞禨PS/PPS
+- 鏀硅繘缂栫爜寰幆锛屽鐞嗘墍鏈夎緭鍑�
+- 娣诲姞娓呯┖缂栫爜鍣ㄥ姛鑳�
+
+**寤鸿锛�**
+1. 閲嶆柊缂栬瘧杩愯搴旂敤
+2. 褰曞埗鑷冲皯3-5绉�
+3. 姝e父鍋滄缂栫爜锛堜笉瑕佸己鍒堕��鍑猴級
+
+### 鉂� 闂2: VLC鏃犳硶鎾斁
+
+**妫�鏌ユ楠わ細**
+
+1. **鏌ョ湅鏂囦欢澶у皬**
+ ```bash
+ adb shell "ls -lh /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264"
+ ```
+ 濡傛灉澶皬锛�<1KB锛夛紝璇存槑鍙兘鍙湁閰嶇疆鏁版嵁
+
+2. **鏌ョ湅Logcat鏃ュ織**
+ ```bash
+ adb logcat -s H264Encoder:D | grep -E "Frame encoded|SPS/PPS|NALU"
+ ```
+ 搴旇鐪嬪埌锛�
+ - "SPS/PPS included in key frame data"
+ - "Frame encoded: ..." 锛堝娆★級
+
+3. **妫�鏌ユ枃浠舵牸寮�**
+ ```bash
+ adb shell "hexdump -C /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264 | head -3"
+ ```
+ 搴旇鐪嬪埌 `00 00 00 01` 鎴� `00 00 01`
+
+### 鉂� 闂3: 鏂囦欢瀛樺湪浣嗘挱鏀惧櫒鎶ラ敊
+
+**鍙兘鍘熷洜锛�**
+1. 鏂囦欢鏍煎紡涓嶆槸绾疉nnex-B
+2. 缂哄皯SPS/PPS
+3. 鏁版嵁鎹熷潖
+
+**瑙e喅鏂规硶锛�**
+1. 浣跨敤 `check_h264.py` 璇︾粏妫�鏌�
+2. 鏌ョ湅Logcat纭缂栫爜杩囩▼姝e父
+3. 灏濊瘯鐢╢fmpeg杞崲锛�
+ ```bash
+ ffmpeg -i test.h264 -c copy test_fixed.h264
+ ```
+
+## 楠岃瘉淇鏁堟灉
+
+淇鍚庣殑浠g爜搴旇鑳藉锛�
+
+鉁� **鐢熸垚鍙挱鏀剧殑H264鏂囦欢**
+- 鍖呭惈瀹屾暣鐨凷PS/PPS
+- 鍖呭惈澶氫釜甯э紙IDR + 闈濱DR锛�
+- 姝g‘鐨凙nnex-B鏍煎紡
+
+鉁� **鏂囦欢鐗瑰緛锛�**
+- 鏂囦欢澶у皬 > 10KB锛�3绉掑綍鍒讹級
+- NALU鍗曞厓鏁伴噺 > 10涓�
+- 鍖呭惈SPS (绫诲瀷7)
+- 鍖呭惈PPS (绫诲瀷8)
+- 鍖呭惈IDR鍏抽敭甯� (绫诲瀷5)
+- 鍖呭惈闈濱DR甯� (绫诲瀷1)
+
+## 涓嬩竴姝�
+
+1. **閲嶆柊杩愯搴旂敤**锛屽綍鍒�3-5绉掕棰�
+2. **涓嬭浇鏂囦欢**鍒版湰鍦�
+3. **鐢╒LC鎾斁**楠岃瘉
+4. **濡傛灉杩樻湁闂**锛岃繍琛屾鏌ュ伐鍏疯幏鍙栬缁嗚瘖鏂�
+
--
Gitblit v1.8.0