2012-05-02 32 views
9

Có ai biết cách phát hiện tệp video đó là phim 3D không?Làm cách nào để phát hiện phim là 3D?

Tôi đã thử sử dụng công cụ ffmpeg, nhưng tôi đã không thành công để tìm hiểu cách thực hiện.

sample

+0

Không chắc chắn nếu nó giúp: Phát hiện tỷ lệ khung hình. Phim 3D có chiều rộng gấp đôi, ví dụ: 3840 x 1080 – Raptor

+0

Bạn nhận được gì khi chạy 'ffprobe 3dvideo.mp4'? – d33pika

Trả lời

6

Tùy theo định dạng.

Ở mức luồng: Đối với AVC, bạn có thể tìm kiếm các gói SEI sắp xếp đóng gói. Đối với MVC bạn có thể tìm kiếm phần mở rộng của slice NAL (loại = 20).

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

Tôi đã xem tệp của bạn. Đó là AVC 3D với khung đóng gói loại 3 (cạnh nhau - L ở bên trái, R bên phải). Tôi extraced các dòng H.264 và tôi tìm thấy tại byte offset 0x23: 00 00 00 01 06 2D đây là một tin nhắn SEI (06) sắp xếp đóng gói khung loại (2D). Thật vậy tập tin của bạn có chứa thông tin chỉ ra 3D

công cụ dòng Comannd để phát hiện 3D

  1. Giải nén dòng h.264 sử dụng mp4box -raw 1 82-3D-LHelEIJVxiE.mp4 (http://gpac.wp.mines-telecom.fr/mp4box/)

lấy luồng cơ bản H.264 82-3D-LHelEIJVxiE_track1.h264 và chạy nó theo mã sau:

#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

Bạn có thể chạy mp4box + một đoạn mã của tôi không? Bạn cần mã nguồn hoặc mã nhị phân? Nền tảng gì? –

0

Công cụ đường Comannd đến phát hiện 3D:

  1. Giải nén dòng h.264 sử dụng mp4box -raw 1 82-3D-LHelEIJVxiE.mp4 (http://gpac.wp.mines-telecom.fr/mp4box/)

lấy H.264 tiểu suối 82-3D-LHelEIJVxiE_track1.h264 và chạy nó thông qua mã sau:

#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; 
} 
Các vấn đề liên quan