2012-05-02 8 views
9

Czy ktoś wie, jak wykryć, że plik wideo jest filmem 3D?Jak wykryć, że film jest 3D?

Próbowałem używać narzędzia ffmpeg, ale nie udało mi się znaleźć sposobu.

sample

+0

Nie wiem, czy to pomaga: Wykryj współczynnik kształtu. Film 3D ma podwójną szerokość, np. 3840 x 1080 – Raptor

+0

Co otrzymasz, gdy uruchomisz 'ffprobe 3dvideo.mp4'? – d33pika

Odpowiedz

6

To zależy od formatu.

Na poziomie strumienia: W przypadku AVC można wyszukać komunikaty SEI dotyczące rozmieszczenia ramek. Dla MVC możesz szukać NAL-ów dla przedłużenia plasterek (typ = 20).

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

Spojrzałem na pliku. Jest to AVC 3D z ramą typu pakowania 3 (obok siebie - L jest po lewej, R po prawej). Wyodrębniłem strumień H.264 i znalazłem przy przesunięciu bajtu 0x23: 00 00 00 01 06 2D jest to komunikat SEI (06) układu pakowania ramek typu (2D). Rzeczywiście plik zawiera informacje wskazujące 3D

Comannd narzędzie do wykrywania linii 3D

  1. Extract strumień H.264 przy użyciu mp4box -Surowe 1 82-3D-LHelEIJVxiE.mp4 (http://gpac.wp.mines-telecom.fr/mp4box/)

podjąć elementarny strumień H.264 82-3D-LHelEIJVxiE_track1.h264 i uruchomić go przechadzkę kod followin:

#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

Czy możesz uruchomić mp4box + kawałek mojego kodu? Czy potrzebujesz kodu źródłowego lub plików binarnych? Jaka platforma? –

0

narzędzia Comannd linia wykryć 3D:

  1. Ekstrakt strumienia h.264 pomocą mp4box -Surowe 1 82-3D-LHelEIJVxiE.mp4 (http://gpac.wp.mines-telecom.fr/mp4box/)

się elementarny strumień H.264 82-3D-LHelEIJVxiE_track1.h264 i uruchom go za pomocą następującego kodu:

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