有谁知道如何检测视频文件是 3D 电影?
我已经尝试使用 ffmpeg 工具,但我没有成功找出如何去做。
It depends on the format.
On stream level: For AVC you could look for frame packing arrangement SEI messages. For MVC you could look for slice extension NALs (type=20).
http://www.merl.com/reports/docs/TR2011-022.pdf
I looked at your file. It is AVC 3D with frame packing type 3 (side by side - L is on the left, R on the right). I extraced the H.264 stream and I found at byte offset 0x23: 00 00 00 01 06 2D this is a SEI message (06) of type frame packing arrangement (2D). Indeed your file contains information indicating 3D
Comannd line tool to detect 3D
take the H.264 elementary stream 82-3D-LHelEIJVxiE_track1.h264 and run it throught the followin code:
#include <iostream>
#include <fstream>
typedef unsigned char uint8_t;
enum ResultCode
{
E_Error = -1,
E_OK = 0,
E_No3D = 2,
E_Found3D = 3,
};
enum NALType
{
NALType_Unknown = 0,
NALType_Slice = 1,
NALType_Slice_DPA = 2,
NALType_Slice_DPB = 3,
NALType_Slice_DPC = 4,
NALType_Slice_IDR = 5,
NALType_SEI = 6,
NALType_SPS = 7,
NALType_PPS = 8,
NALType_AU_Delimiter = 9,
NALType_SequenceEnd = 10,
NALType_StreamEnd = 11,
NALType_FillerData = 12,
NALType_CodedSliceExtension = 20,
NALType_MAX = 0x1f
};
enum SEIType
{
SEIType_FramePackingArrangement = 0x2D
};
enum StartCodeState
{
StartCodeState_none,
StartCodeState_0,
StartCodeState_0_0,
StartCodeState_0_0_1
};
int Is3D(std::ifstream & inputFile)
{
int nResult = E_OK;
StartCodeState eStartCodeState = StartCodeState_none;
while( (E_OK == nResult) && ( ! inputFile.eof() ) )
{
uint8_t byte = inputFile.get();
switch(eStartCodeState)
{
case StartCodeState_none :
eStartCodeState = (byte == 0) ? StartCodeState_0 : StartCodeState_none;
break;
case StartCodeState_0 :
eStartCodeState = (byte == 0) ? StartCodeState_0_0 : StartCodeState_none;
break;
case StartCodeState_0_0 :
switch(byte)
{
case 0 : eStartCodeState = StartCodeState_0_0; break;
case 1 : eStartCodeState = StartCodeState_0_0_1; break;
default : eStartCodeState = StartCodeState_none;
}
default:
;
}
if( eStartCodeState == StartCodeState_0_0_1 )
{
uint8_t cNALType = inputFile.get();
cNALType &= NALType_MAX;
switch(cNALType)
{
case NALType_CodedSliceExtension :
nResult = E_Found3D;
break;
case NALType_SEI :
{
uint8_t cSEIType = inputFile.get();
if( cSEIType == SEIType_FramePackingArrangement )
{
nResult = E_Found3D;
}
break;
}
default:
;
}
eStartCodeState = StartCodeState_none;
}
}
return nResult;
}
int main(int argc, char * argv[])
{
int nResult = E_OK;
if( argc != 2 )
{
nResult = E_Error;
std::cerr << "Usage: "
<< argv[0]
<< " <H.264 elementary stream input file>"
<< std::endl;
}
if( E_OK == nResult )
{
std::ifstream inputFile(argv[1], std::ios::binary);
if( inputFile.is_open() )
{
if( E_Found3D == Is3D(inputFile) )
{
std::cout << "File: "
<< argv[1]
<< " contains 3D."
<< std::endl;
nResult = E_Found3D;
}
else
{
std::cout << "No 3D found" << std::endl;
nResult = E_No3D;
}
}
else
{
std::cerr << "Error opening input file: "
<< argv[1]
<< std::endl;
nResult = E_Error;
}
}
return nResult;
}