2012-05-02 6 views
9

누구나 비디오 파일이 3D 영화인지 어떻게 알 수 있습니까?동영상이 3D인지 어떻게 감지합니까?

ffmpeg 도구를 사용해 보았지만 수행 방법을 찾지 못했습니다.

sample

+0

도움이 될지 확실하지 않은 경우 : 가로 세로 비율을 감지하십시오. 3D 영화의 너비는 두 배입니다. 3840 x 1080 – Raptor

+0

'ffprobe 3dvideo.mp4'를 실행하면 어떻게됩니까? – d33pika

답변

6

그것은 형식에 따라 달라집니다.

온 스트림 레벨 : AVC의 경우 프레임 포장 배열 SEI 메시지를 찾을 수 있습니다. MVC의 경우 슬라이스 확장 NAL (유형 = 20)을 찾을 수 있습니다.

http://www.merl.com/reports/docs/TR2011-022.pdf

나는 파일 보았다. 프레임 포장 유형 3 (나란히, L은 왼쪽, R은 오른쪽)은 AVC 3D입니다. 나는 H.264 스트림을 엑스트라 싱했고 바이트 오프셋 0x23 : 00 00 01 06 2D에서 이것을 발견했습니다. 이것은 유형 프레임 포장 배열 (2D)의 SEI 메시지 (06)입니다. 실제로 파일은 3D

mp4box에게 -raw 1 82-3D-LHelEIJVxiE.mp4 ( http://gpac.wp.mines-telecom.fr/mp4box/)

를 사용하여 H.264 스트림을 추출 3D

  1. 을 감지 할 수

    Comannd 줄 도구를 나타내는 정보를 포함 에

    #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; 
    } 
    
+0

mp4box + 내 코드를 실행할 수 있습니까? 소스 코드 나 바이너리가 필요합니까? 어떤 플랫폼? –

0

Comannd 줄 도구 :가 따라와 코드를 축복하는 H.264 기본 스트림 82-3D-LHelEIJVxiE_track1.h264을 실행 3D 검출 :

  1. 가 mp4box에게 -raw 1 82-3D-LHelEIJVxiE.mp4을 이용한 H.264 스트림을 추출 (http://gpac.wp.mines-telecom.fr/mp4box/)

는 H.264 기본 스트림 82-3D-LHelEIJVxiE_track1.h264 걸릴 다음 코드를 통해 실행하십시오 :

#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; 
} 
관련 문제