| README_H264_CHECK.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| check_h264.py | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| gradlew | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| gradlew.bat | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| keystore.properties | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| test.h264 | 补丁 | 查看 | 原始文档 | blame | 历史 | |
| 如何检查test.h264文件.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
README_H264_CHECK.md
New file @@ -0,0 +1,120 @@ # H264æä»¶æ£æ¥å·¥å ·ä½¿ç¨è¯´æ ## å¿«éæ£æ¥ ### æ¹æ³1: ç´æ¥ä»è®¾å¤è·¯å¾æ£æ¥ï¼å¦ææä»¶å¨æ¬å°ï¼ ```bash python check_h264.py test.h264 ``` ### æ¹æ³2: ä»Android设å¤ä¸è½½æä»¶åæ£æ¥ 1. **è¿æ¥Android设å¤å¹¶å¯ç¨USBè°è¯** 2. **æ¥æ¾æä»¶è·¯å¾** Android设å¤ä¸çæä»¶è·¯å¾é常æ¯ï¼ ``` /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264 ``` æè 使ç¨adbæ¥æ¾ï¼ ```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个SPS (ç±»å7) - â è³å°1个PPS (ç±»å8) - â è³å°1个IDRå ³é®å¸§ (ç±»å5) - â å¤ä¸ªNALUåå ï¼å»ºè®®>10ä¸ªï¼ ## 常è§é®é¢ ### Q: æä»¶åªæ1帧æä¹åï¼ **A:** è¿æ¯ä¹åçé®é¢ãç°å¨ç代ç å·²ç»ä¿®å¤ï¼ - â æ£ç¡®å¤çSPS/PPSé ç½® - â å¨å ³é®å¸§æ¶åå¹¶SPS/PPS - â æ¹è¿ç¼ç 循ç¯ï¼ç¡®ä¿å¤çææè¾åº - â æ·»å æ¸ ç©ºç¼ç å¨åè½ **建议ï¼** 1. éæ°ç¼è¯å¹¶è¿è¡åºç¨ 2. å½å¶è³å°3-5ç§è§é¢ 3. 忢ç¼ç åæ£æ¥æä»¶ ### Q: æä»¶æ æ³ææ¾æä¹åï¼ **å¯è½åå ï¼** 1. â 缺å°SPS/PPS - æ£æ¥æ¯å¦è¾åºäºé ç½®æ°æ® 2. â æä»¶æ ¼å¼é误 - æ£æ¥æ¯å¦æ¯Annex-Bæ ¼å¼ 3. â åªæ1帧 - æ£æ¥ç¼ç å¾ªç¯æ¯å¦æ£å¸¸å·¥ä½ **è§£å³æ¹æ¡ï¼** 1. æ¥çLogcatæ¥å¿ï¼æç´¢ "H264Encoder" 2. æ£æ¥æ¯å¦æ "SPS/PPS included" æ¥å¿ 3. æ£æ¥æ¯å¦æ "Frame encoded" æ¥å¿ 4. ä½¿ç¨æ¤å·¥å ·æ£æ¥æä»¶ç»æ ### Q: å¦ä½ææ¾H264æä»¶ï¼ å¯ä»¥ä½¿ç¨ä»¥ä¸ææ¾å¨ï¼ - **VLC Media Player**ï¼æ¨èï¼ - **ffplay** (FFmpegèªå¸¦) - **MPC-HC** - **PotPlayer** ç´æ¥åå» `.h264` æä»¶æææ¾å°ææ¾å¨çªå£å³å¯ã ## è°è¯å»ºè®® 妿æä»¶æ æ³ææ¾ï¼è¯·æ£æ¥ï¼ 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" - è¯´ææ£å¸¸ç»æ 3. **éªè¯æä»¶ç»æ** ```bash python check_h264.py test.h264 ``` 4. **使ç¨hexdumpæ¥çæä»¶å¤´** ```bash hexdump -C test.h264 | head -20 ``` åºè¯¥çå°ï¼`00 00 00 01` æ `00 00 01`ï¼Annex-Bèµ·å§ç ï¼ check_h264.py
New file @@ -0,0 +1,209 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ H264æä»¶æ£æ¥å·¥å · æ£æ¥çæçtest.h264æä»¶æ¯å¦ç¬¦åææ¾è¦æ± """ import os import sys def check_h264_file(file_path): """æ£æ¥H264æä»¶æ¯å¦ç¬¦åææ¾è¦æ±""" print(f"æ£æ¥æä»¶: {file_path}\n") # 1. æ£æ¥æä»¶æ¯å¦åå¨ if not os.path.exists(file_path): print("â æä»¶ä¸åå¨ï¼") print(f" é¢æè·¯å¾: {file_path}") print("\næç¤ºï¼") print(" - 妿æ¯Android设å¤ï¼éè¦å éè¿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("â ï¸ è¦å: æä»¶å¤ªå°ï¼å¯è½åªæSPS/PPSæ1å¸§æ°æ®") # 3. 读åæä»¶å å®¹å¹¶åæ try: with open(file_path, 'rb') as f: data = f.read() except Exception as e: print(f"â 读åæä»¶å¤±è´¥: {e}") return False # æ£æ¥NALUåå nal_start_code_3 = bytes([0x00, 0x00, 0x01]) nal_start_code_4 = bytes([0x00, 0x00, 0x00, 0x01]) nalu_list = [] i = 0 # æ¥æ¾ææNALUåå 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)} 个NALUåå \n") if len(nalu_list) == 0: print("â æªæ¾å°ä»»ä½NALUåå ï¼æä»¶æ ¼å¼å¯è½ä¸æ£ç¡®") return False # ç»è®¡ä¸åç±»åçNALU 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" â å å«éIDR帧 - {nal_type_count[1]} 个") else: print(" â ï¸ æ²¡æéIDR帧ï¼åªæå ³é®å¸§ï¼") # 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" å å«å®æ´çSPS/PPSå {len(nalu_list)} 个NALUåå ") 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: "éIDRç¼ç ç", 2: "ç¼ç çæ°æ®ååºA", 3: "ç¼ç çæ°æ®ååºB", 4: "ç¼ç çæ°æ®ååºC", 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) gradlew
New file @@ -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" "$@" gradlew.bat
New file @@ -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 keystore.properties
New file @@ -0,0 +1,4 @@ storePassword = 123456 keyPassword = 123456 keyAlias = key0 storeFile = ../key/key.jks test.h264Binary files differ
ÈçºÎ¼ì²étest.h264Îļþ.md
New file @@ -0,0 +1,184 @@ # å¦ä½æ£æ¥test.h264æä»¶è½å¦ææ¾ ## å¿«éå¤ææ¹æ³ ### æ¹æ³1: ç´æ¥ç¨ææ¾å¨æµè¯ï¼æç®åï¼ 1. **ä»Android设å¤ä¸è½½æä»¶** ```bash adb pull /storage/emulated/0/Android/data/com.anyun.h264/files/test.h264 ./test.h264 ``` 2. **ç¨VLCææ¾å¨æå¼** - ä¸è½½VLC: https://www.videolan.org/vlc/ - ç´æ¥åå» `test.h264` æä»¶ - æè ææ¾å°VLCçªå£ 3. **å¦æè½ææ¾** â - 说ææä»¶æ ¼å¼æ£ç¡® - å¯ä»¥çå°è§é¢å 容 4. **妿ä¸è½ææ¾** â - å¯è½ç¼ºå°SPS/PPS - å¯è½åªæ1帧 - å¯è½æ ¼å¼é误 ### æ¹æ³2: 使ç¨Pythonå·¥å ·æ£æ¥ï¼è¯¦ç»åæï¼ 1. **ç¡®ä¿å®è£ äºPython** (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å ³é®å¸§ - â æå¤ä¸ªNALUåå ï¼å»ºè®®>10ä¸ªï¼ â **ä¸è½ææ¾çæ å¿ï¼** - 缺å°SPSæPPS - åªæ1-2个NALUåå - æä»¶å¤ªå°ï¼<100åèï¼ ### æ¹æ³3: 使ç¨ffprobeæ£æ¥ï¼å¦æå®è£ äºFFmpegï¼ ```bash ffprobe test.h264 ``` å¦æè½æ£ç¡®æ¾ç¤ºè§é¢ä¿¡æ¯ï¼å辨çã帧ççï¼ï¼è¯´ææä»¶å¯ä»¥ææ¾ã ### æ¹æ³4: æ¥çæä»¶å¤§å°ï¼ç²ç¥å¤æï¼ ```bash # å¨Android设å¤ä¸ 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 ``` **æ£å¸¸æä»¶åºè¯¥çå°ï¼** ``` 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çNALUç±»åï¼0x67 & 0x1F = 7ï¼ - `68` = PPSçNALUç±»åï¼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æ²¡ææ£ç¡®åå ¥ - ç¼ç å¾ªç¯æåéåº **è§£å³æ¹æ¡ï¼** â å·²ç»ä¿®å¤ï¼æ°ä»£ç å å«ï¼ - æ£ç¡®å¤çSPS/PPSé ç½®æ°æ® - å¨å ³é®å¸§æ¶åå¹¶SPS/PPS - æ¹è¿ç¼ç 循ç¯ï¼å¤çææè¾åº - æ·»å æ¸ 空ç¼ç å¨åè½ **建议ï¼** 1. éæ°ç¼è¯è¿è¡åºç¨ 2. å½å¶è³å°3-5ç§ 3. æ£å¸¸åæ¢ç¼ç ï¼ä¸è¦å¼ºå¶éåºï¼ ### â é®é¢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. æä»¶æ ¼å¼ä¸æ¯çº¯Annex-B 2. 缺å°SPS/PPS 3. æ°æ®æå **è§£å³æ¹æ³ï¼** 1. ä½¿ç¨ `check_h264.py` è¯¦ç»æ£æ¥ 2. æ¥çLogcat确认ç¼ç è¿ç¨æ£å¸¸ 3. å°è¯ç¨ffmpeg转æ¢ï¼ ```bash ffmpeg -i test.h264 -c copy test_fixed.h264 ``` ## éªè¯ä¿®å¤ææ ä¿®å¤åç代ç åºè¯¥è½å¤ï¼ â **çæå¯ææ¾çH264æä»¶** - å å«å®æ´çSPS/PPS - å å«å¤ä¸ªå¸§ï¼IDR + éIDRï¼ - æ£ç¡®çAnnex-Bæ ¼å¼ â **æä»¶ç¹å¾ï¼** - æä»¶å¤§å° > 10KBï¼3ç§å½å¶ï¼ - NALUåå æ°é > 10个 - å å«SPS (ç±»å7) - å å«PPS (ç±»å8) - å å«IDRå ³é®å¸§ (ç±»å5) - å å«éIDR帧 (ç±»å1) ## ä¸ä¸æ¥ 1. **éæ°è¿è¡åºç¨**ï¼å½å¶3-5ç§è§é¢ 2. **ä¸è½½æä»¶**å°æ¬å° 3. **ç¨VLCææ¾**éªè¯ 4. **å¦æè¿æé®é¢**ï¼è¿è¡æ£æ¥å·¥å ·è·å详ç»è¯æ