大家好,我在android上写了一个视频录像程序,视音频数据(h264+aac)保存在两个队列里,我想要用MP4v2,开两个线程把数据打包成MP4视频文件,结果发现生成的视频不能使用VideoView播放,去SD卡找到生成的视频文件,使用小米视频能播放,却没有声音,数据也有错误——视频时长显示为11:35:36,实际录像时长只有几秒,能播放的也是那几秒。
网上能查的资料很少,github上也没有可供参考的项目。我自己瞎改了一下参数,没有效果。测试后发现不写入音频数据的话,可以正常播放(没有声音),一写入音频数据,或者说调用了MP4AddAudioTrack找到audio的trackId就会出现该问题,猜测是数据写入错误,具体原因还不清楚,也想不出什么解决方法。请问有哪些可能的原因和解决问题的方向吗?(工作的一个问题,只能用MP4v2,不能用ffmpeg)
已经被这个问题困扰了很久了,所以把全部C币都拿出来悬赏,也不知道大家在意不在意这个C币,希望有了解MP4v2的大神帮忙解惑,万分感谢!
如果这个问题比较复杂,或者说可能的原因有很多,一下子说不完,那么可以给个学习方向上的建议吗?比如应该去哪里学习、补充哪些知识之类,对这个问题,我真的有一种无从下手的感觉。只要给我一个研究方向/建议,我也很感激了!
这是代码:
//写视频数据
BOOL WriteVideoData(RECORD_PARAM *struRecordParam, char* pVideoData, int nSize, int iFrameRate, int iType, long lTimestemp){
BOOL bResult = FALSE;
if(struRecordParam==NULL || struRecordParam->mp4FileHandle<=0 || struRecordParam->isOpen==FALSE) return FALSE;
// if (struRecordParam->videoId == MP4_INVALID_TRACK_ID) {
//
// return FALSE;
// }
if (nSize==0) {//写空帧
if (!MP4WriteSample(struRecordParam->mp4FileHandle,
struRecordParam->videoId,
(const uint8_t*)pVideoData,
nSize,
lTimestemp,
0,
true)) {
return FALSE;
}
return TRUE;
}
//
if ((pVideoData[4]&0x1f) == 7) {
NSLOGE("writeVideoFrame: if 7");
if (struRecordParam->hasSPS) {
return FALSE;
}
NSLOGE("to MP4AddH264VideoTrack ");
struRecordParam->videoId = MP4AddH264VideoTrack(struRecordParam->mp4FileHandle,
struRecordParam->nVideoTimeScale,
(struRecordParam->nVideoTimeScale/struRecordParam->nVideoFrameRate),
struRecordParam->nVideoWidth,
struRecordParam->nVideoHeight,
pVideoData[5],
pVideoData[6],
pVideoData[7],
3);
if (struRecordParam->videoId == MP4_INVALID_TRACK_ID) {
return FALSE;
}
MP4SetVideoProfileLevel(struRecordParam->mp4FileHandle, 0x7F);
MP4AddH264SequenceParameterSet(struRecordParam->mp4FileHandle,
struRecordParam->videoId,
(const uint8_t*)(pVideoData+4),
nSize-4);
struRecordParam->hasSPS = TRUE;
NSLOGE("MP4AddH264VideoTrack ok");
} else if ((pVideoData[4]&0x1f) == 8) {
NSLOGE("writeVideoFrame: if 8");
if (struRecordParam->hasPPS) {
return FALSE;
}
MP4AddH264PictureParameterSet(struRecordParam->mp4FileHandle,
struRecordParam->videoId,
(const uint8_t*)(pVideoData+4),
nSize-4);
struRecordParam->hasPPS = TRUE;
} else {
NSLOGE("writeVideoFrame: if else");
pVideoData[0] = (nSize-4) >> 24;
pVideoData[1] = (nSize-4) >> 16;
pVideoData[2] = (nSize-4) >> 8;
pVideoData[3] = (nSize-4) & 0xff;
if (!MP4WriteSample(struRecordParam->mp4FileHandle,
struRecordParam->videoId,
(const uint8_t*)(pVideoData),
nSize,
MP4_INVALID_DURATION,
0,
true)) {
return FALSE;
}
}
return TRUE;
}
//写空帧
BOOL WriteEmptyVideoData(RECORD_PARAM *struRecordParam){
if(struRecordParam==NULL || struRecordParam->isOpen==FALSE) return FALSE;
if (!MP4WriteSample(struRecordParam->mp4FileHandle,
struRecordParam->videoId,
NULL,
0,
MP4_INVALID_DURATION,
0,
true)) {
return FALSE;
}
return TRUE;
}
//写音频数据
BOOL WriteAudioData(RECORD_PARAM *struRecordParam, char* pAudioData, int nSize, long lTimestemp){
if(struRecordParam==NULL || struRecordParam->mp4FileHandle<=0 || struRecordParam->isOpen==FALSE) return FALSE;
BOOL bResult = FALSE;
uint8_t *bufaudio = (uint8_t*)pAudioData;
if (struRecordParam->audioId == MP4_INVALID_TRACK_ID)
{
//添加aac音频
NSLOGE("MP4AddAudioTrack");//add for test
struRecordParam->audioId = MP4AddAudioTrack(struRecordParam->mp4FileHandle, 48000, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
if (struRecordParam->audioId == MP4_INVALID_TRACK_ID)
{
return bResult;
}
NSLOGE("MP4SetAudioProfileLevel");//add for test
MP4SetAudioProfileLevel(struRecordParam->mp4FileHandle, 0x02);
NSLOGE("MP4SetTrackESConfiguration");//add for test
MP4SetTrackESConfiguration(struRecordParam->mp4FileHandle, struRecordParam->audioId, &bufaudio[0], nSize);
}
if (struRecordParam->audioId != MP4_INVALID_TRACK_ID) {
NSLOGE("MP4WriteSample audio");//add for test
MP4WriteSample(struRecordParam->mp4FileHandle,
struRecordParam->audioId,
&bufaudio[7],
nSize-7,
lTimestemp,
0,
true);
}
bResult = TRUE;
return bResult;
}
你这个应该涉及到视频格式转码的问题,不是简单的保存为mp4就可以的
你能把logcat发出来给我看看吗?
在app内点击生成的视频文件时,出现的logcat日志如下:
11-01 14:06:08.715: E/WifiTrafficPoller(781): TRAFFIC_STATS_POLL true Token 149 num clients 24
11-01 14:06:08.715: E/WifiTrafficPoller(781): packet count Tx=44896 Rx=49194
11-01 14:06:09.437: E/DrmMtkUtil/DrmUtil(276): checkDcf: not dcf type, dcf version value [0]
11-01 14:06:09.437: E/Cta5File(276): Cta5File::isCta5NormalFile false, bad magic:
11-01 14:06:09.437: E/Cta5File(276): Cta5File::isCta5MultimediaFile false, bad magic:
11-01 14:06:09.437: E/DrmMtkUtil/DrmUtil(276): checkDcf: not dcf type, dcf version value [0]
11-01 14:06:09.437: E/Cta5File(276): Cta5File::isCta5NormalFile false, bad magic:
11-01 14:06:09.437: E/Cta5File(276): Cta5File::isCta5MultimediaFile false, bad magic:
11-01 14:06:09.438: E/DrmMtkUtil/DrmUtil(276): checkDcf: not dcf type, dcf version value [0]
11-01 14:06:09.440: E/DrmMtkUtil/DrmUtil(275): parseDcf: not dcf type, dcf version value [0]
11-01 14:06:09.440: E/DrmMtkPlugIn(275): onOpenDecryptSession() : failed to parse dcf file.
11-01 14:06:09.452: E/APEExtractor(276): getAPEInfo not ape 5003
11-01 14:06:09.456: E/DrmMtkUtil/DrmUtil(275): parseDcf: not dcf type, dcf version value [0]
11-01 14:06:09.456: E/DrmMtkPlugIn(275): onOpenDecryptSession() : failed to parse dcf file.
11-01 14:06:09.467: E/APEExtractor(276): getAPEInfo not ape 5003
11-01 14:06:09.479: E/MtkOmxVdec(276): [0xab983d90] [MtkOmxVdec]VAL_CHIP_NAME_MT6795
11-01 14:06:09.481: E/MtkOmxVdec(276): [0xab983d90] SetParameter: VDEC_DRV_PIXEL_FORMAT_YUV_420_PLANER_MTK
11-01 14:06:09.481: E/MtkOmxVdec(276): [0xab983d90] OMX_GoogleAndroidIndexEnableAndroidNativeBuffers enable(1)
11-01 14:06:09.485: E/OMXNodeInstance(276): setParameter(33554433) ERROR: 0x80001005
11-01 14:06:09.485: E/OMXNodeInstance(276): setParameter(33554433) ERROR: 0x80001005
11-01 14:06:09.485: E/MtkOmxVdec(276): [0xab983d90] keep going before decoder init
11-01 14:06:09.485: E/MtkOmxVdec(276): [0xab983d90] SetParameter: VDEC_DRV_PIXEL_FORMAT_YUV_420_PLANER_MTK
11-01 14:06:09.488: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.491: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.493: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.494: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.496: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.499: E/OMXCodec(276): [OMX.MTK.VIDEO.DECODER.AVC] +waitForBufferFilled_l: 0/2
11-01 14:06:09.506: E/VDO_LOG(276): [Vdec_Drv_H264_open] VAL_CHIP_NAME_MT6752, VAL_CHIP_NAME_MT6582, VAL_CHIP_NAME_MT8135, VAL_CHIP_NAME_MT6592, VAL_CHIP_NAME_MT8127, VAL_CHIP_NAME_ROME, VAL_CHIP_NAME_MT6795
11-01 14:06:09.506: E/VDO_LOG(276): [Info] NALU type 7!!
11-01 14:06:09.506: E/VDO_LOG(276): u4LevelIdc 30
11-01 14:06:09.506: E/VDO_LOG(276): [Warning] profile: 100, level: 30, bDirect8x8InferenceFlag should be 1 (0)
11-01 14:06:09.506: E/VDO_LOG(276): u4LevelIdc 30
11-01 14:06:09.506: E/VDO_LOG(276): vdec_drv_h264_decode, u4LevelIdc 30
11-01 14:06:09.506: E/VDO_LOG(276): getDpbSize u4NumRefFrames (1), u4DpbSize (6)!!
11-01 14:06:09.506: E/VDO_LOG(276): [Debug] getDpbSize final u4DpbSize (6)!!
11-01 14:06:09.511: E/RemoteController(955): Cannot set synchronization mode on an unregistered RemoteController
11-01 14:06:09.518: E/SpannableStringBuilder(8260): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
11-01 14:06:09.518: E/SpannableStringBuilder(8260): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
11-01 14:06:09.518: E/VDO_LOG(276): [Err, h264_dec_init] u4Width 640, u4Height 480, u4PicWidth 640, u4PicHeight 480
11-01 14:06:09.518: E/MtkOmxVdec(276): [0xab983d90] VAL_CHIP_NAME_MT6795
11-01 14:06:09.518: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.518: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.518: E/MtkOmxVdec(276): [0xab983d90] [Warning] Cannot get param: VDEC_DRV_GET_TYPE_GET_FRAME_CROP_INFO, using original width/height for cropping
11-01 14:06:09.519: E/OMXCodec(276): [OMX.MTK.VIDEO.DECODER.AVC] -waitForBufferFilled_l
11-01 14:06:09.519: E/OMXCodec(276): [OMX.MTK.VIDEO.DECODER.AVC] +waitForBufferFilled_l: 0/0
11-01 14:06:09.523: E/(276): nWaitMilliSec : 10
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.523: E/MtkOmxVdec(276): [0xab983d90] [CheckFreeBuffer] mFrameBuf = NULL
11-01 14:06:09.526: E/OMXNodeInstance(276): setParameter(33554433) ERROR: 0x80001005
11-01 14:06:09.526: E/OMXNodeInstance(276): setParameter(33554433) ERROR: 0x80001005
11-01 14:06:09.532: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.534: E/MJCFramework(276): ParseMjcConfig failed. Can't open /etc/mtk_clear_motion.cfg
11-01 14:06:09.534: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.534: E/MJCFramework(276): [0][1] BP 4 invaid drv param, IFR: 0, FMT: 1
11-01 14:06:09.534: E/MJCFramework(276): [0][1] Drv is NULL. BP
11-01 14:06:09.537: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.538: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.539: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.541: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.542: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.543: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.545: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.546: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.549: E/MtkOmxVdec(276): [0xab983d90] MtkOmxVdec::GetExtensionIndex Unknown parameter name: OMX.google.android.index.useAndroidNativeBuffer2
11-01 14:06:09.550: E/MtkOmxVdec(276): [0xab983d90] [ERROR] Cannot get param: VDEC_DRV_GET_TYPE_GET_FRAME_CROP_INFO
11-01 14:06:09.550: E/VDO_LOG(276): u4LevelIdc 30
11-01 14:06:09.550: E/VDO_LOG(276): [Warning] profile: 100, level: 30, bDirect8x8InferenceFlag should be 1 (0)
11-01 14:06:09.550: E/VDO_LOG(276): u4LevelIdc 30
11-01 14:06:09.550: E/VDO_LOG(276): handleSPSNALU() 1 u4LevelIdc 30
11-01 14:06:09.550: E/VDO_LOG(276): vdec_drv_h264_decode, u4LevelIdc 30
11-01 14:06:09.550: E/VDO_LOG(276): getDpbSize u4NumRefFrames (1), u4DpbSize (6)!!
11-01 14:06:09.550: E/VDO_LOG(276): [Debug] getDpbSize final u4DpbSize (6)!!
11-01 14:06:09.550: E/VDO_LOG(276): handleSPSNALU() 2 u4LevelIdc 30
11-01 14:06:09.550: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.550: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.550: E/OMXCodec(276): [OMX.MTK.VIDEO.DECODER.AVC] -waitForBufferFilled_l
11-01 14:06:09.550: E/OMXCodec(276): [OMX.MTK.VIDEO.DECODER.AVC] +waitForBufferFilled_l: 0/2
11-01 14:06:09.551: E/OMXCodec(276): [OMX.MTK.VIDEO.DECODER.AVC] -waitForBufferFilled_l
11-01 14:06:09.551: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.551: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.551: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.551: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.553: E/OMXNodeInstance(276): setParameter(2130706466) ERROR: 0x8000101a
11-01 14:06:09.553: E/VDO_LOG(276): pu4RefIdx0 < (pH264_Slice_Hdr_DataInst->u4NumRefIdxL0ActiveMinus1+1)(1) (0) (3)
11-01 14:06:09.553: E/VDO_LOG(276): pu4RefIdx0 < (pH264_Slice_Hdr_DataInst->u4NumRefIdxL0ActiveMinus1+1)(1) (0) (3)
11-01 14:06:09.555: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.555: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.556: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.556: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.558: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.558: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.559: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.559: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.561: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.561: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.563: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.563: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.598: E/OMXCodec(276): [OMX.google.aac.decoder] +waitForBufferFilled_l: 0/0
11-01 14:06:09.599: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.599: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.600: E/OMXCodec(276): [OMX.google.aac.decoder] OMX_EventError(0x80001001, 8195)
11-01 14:06:09.600: E/OMXCodec(276): [OMX.google.aac.decoder] -waitForBufferFilled_l
11-01 14:06:09.601: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.601: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.603: E/MediaPlayer(8260): error (260, -2147483648)
11-01 14:06:09.604: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
11-01 14:06:09.604: E/VDO_LOG(276): [DEBUG] VDEC_DRV_GET_TYPE_QUERY_VIDEO_DPB_SIZE 6
只是一个视频录像程序么?android实现视频录制有两种方法,一种是调用自带的视频功能,一种是使用MediaRecorder。
http://www.pm-road.com/index.php/2014/12/05/267/
研究下视频编码吧,比如MP4的视频编码AVC1,音频编码AAC2
AVI的视频编码有DIVX/DX50/WMV3/XVID/H264,音频编码有MP3/AAC2/MPEG1等等