10

有谁知道如何检测视频文件是 3D 电影?

我已经尝试使用 ffmpeg 工具,但我没有成功找出如何去做。

样本

4

1 回答 1

7

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

  1. Extract the h.264 stream using mp4box -raw 1 82-3D-LHelEIJVxiE.mp4 (http://gpac.wp.mines-telecom.fr/mp4box/)

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;
}
于 2013-02-12T00:09:05.957 回答