vidinput_avc.cxx

来自「开源代码的pwlib的1.10.0版本,使用openh323的1.18.0版本毕」· CXX 代码 · 共 572 行 · 第 1/2 页

CXX
572
字号
/*
 * This file is essentially a rewrite of video4dc1394.cxx
 * Check that one for more explanations
 *
 * A lot of code "borrowed" from
 * - dvgrab.c from libdv (http://libdv.sf.net/)
 * - kino (http://kino.schirmacher.de/)
 * - video4dc1394.cxx from ptlib
 * - ... probably others too
 *
 * The code is highly experimental.
 * You should expect any of :
 * - plenty of segfaults
 * - loss of performance
 * - not working at all for you
 * 
 * Known Bugs / Limitations / Room for improvement (feel free to patch/suggest)
 * - Colors are no good after a Convert 
 *   Can someone look at the code and tell me what I have to tell the convert function
 *   that my source colors are? I thought it is pure RGB24, but obviously not.
 *   Dumping the binary data directly to a PPM file works like a charm, though :-/
 * - Occasional segfaults (I think these are fixed, but don't be surprised if it works not)
 * - grabs first camera by default (not sure how to go about selection of cameras/ports)
 * - still haven't figured what the channel parameter in start_iso_rcv(handle,channel) means,
 *   but it seems that we are in for a long wait if channel != 63
 * - code depends on libavc1394 to figure out if a device is a camera
 *   I am not really sure there isn't a smarter way of going about it
 *   since capturing video only requires libraw1394 (for the moment)
 *   Maybe we can drop that dependency?
 * - Still not sure how to go about setting frame size.
 *   Resizing manually at the moment, since the frame size of a captured frame
 *   from an AVC camera is not settable.
 *   An AVC camera supports either NTSC (720x480) or PAL (720x576) resolution
 *   and the only way to check which one it is, seems to be to parse the header
 *   of a captured frame. Will wait for a suggestion on the proper way to handle it.
 * - bus resets not handled (yet?)
 * - Still not sure what to use the device name for (beats me :( )
 * - not sure if TRY_1394AVC and TRY_1394DC will not break something if used at the same time
 * - Overuse of PTRACE?
 * - I am not sure how most of the stuff works
 * - ... everything else
 *
 * Technical Notes
 * ------------------------------------------------------------
 *
 * Test Environment:
 * This module was tested against:
 * Hardware:
 *   AthlonXP 1800+
 *   Asus A7S333
 *   Sony DCR-TRV20 NTSC (http://www.sony.jp/products/Consumer/VD/DCR-TRV20/)
 *   Texas Instruments TSB12LV26 IEEE-1394 Controller 
 * Software:
 *   Linux vanilla kernel 2.4.20
 *   libraw1394 0.9.0
 *   libavc1394 0.4.1
 *   libdv 0.98
 *
 * Author: Georgi Georgiev <chutz@gg3.net>
 *
 */

#pragma implementation "vidinput_avc.h"

#include "vidinput_avc.h"

#ifndef RAW_BUFFER_SIZE
#define RAW_BUFFER_SIZE 512
#endif 

PCREATE_VIDINPUT_PLUGIN(1394AVC);

static PMutex mutex;
static PDictionary<PString, PString> *dico;
static u_int8_t raw_buffer[RAW_BUFFER_SIZE];

///////////////////////////////////////////////////////////////////////////////
// PVideoInput1394AVC

PVideoInputDevice_1394AVC::PVideoInputDevice_1394AVC()
{
  handle = NULL;
  is_capturing = FALSE;
  dv_decoder = NULL;
}

PVideoInputDevice_1394AVC::~PVideoInputDevice_1394AVC()
{
  Close();
}

BOOL PVideoInputDevice_1394AVC::Open(const PString & devName, BOOL startImmediate)
{
  PTRACE(3, "trying to open " << devName);

  if (IsOpen())
    Close();

  UseDMA = TRUE; // FIXME: useful?

  handle = raw1394_new_handle();
  if (handle == NULL) {
    PTRACE(3, "No handle.");
    return FALSE;
  }
  
  mutex.Wait();
  if(dico != NULL && sscanf((char *)dico->GetAt(devName), "%d", &port) == 1)
    ; // well, got it
  else
    port = 0;
  mutex.Signal();
  
  if(raw1394_set_port(handle, port) != 0) {
    PTRACE(3, "couldn't set the port");
    Close();
    return FALSE;
  }
  
  frameWidth = CIFWidth;
  frameHeight = CIFHeight;
  colourFormat = "RGB24";
  nativeVerticalFlip = true;
  desiredFrameHeight = CIFHeight;
  desiredFrameWidth = CIFWidth;
  desiredColourFormat = "RGB24";
  
  deviceName = devName; // FIXME: looks useless
  
  if (!SetChannel(channelNumber)
      || !SetVideoFormat(videoFormat)) {
    PTRACE(3, "SetChannel() or SetVideoFormat() failed");
    Close();
    return FALSE;
  }
  
  if (startImmediate && !Start()) {
    Close();
    return FALSE;
  }
  
  PTRACE(3, "Successfully opened avc1394");
  return TRUE;
}

BOOL PVideoInputDevice_1394AVC::IsOpen() 
{
  return handle != NULL;
}

BOOL PVideoInputDevice_1394AVC::Close()
{
  PTRACE(3, "Close()");
  if (IsOpen()) {
    if (IsCapturing())
      Stop();
    raw1394_destroy_handle(handle);
    handle = NULL;
    return TRUE;
  }
  else
    return FALSE;
}

BOOL PVideoInputDevice_1394AVC::Start()
{
  if (!IsOpen()) return FALSE;
  if (IsCapturing()) return TRUE;
  
  if (raw1394_set_iso_handler(handle, 63, &RawISOHandler)!= NULL) {
    PTRACE (3, "Cannot set_iso_handler");
    return FALSE;
  }
  
  is_capturing = TRUE;
  return TRUE;
}

BOOL PVideoInputDevice_1394AVC::Stop()
{
  if (IsCapturing()) {
    is_capturing = FALSE;
    return TRUE;
  }
  else
    return FALSE;
}

BOOL PVideoInputDevice_1394AVC::IsCapturing()
{
  return is_capturing;
}

PStringList PVideoInputDevice_1394AVC::GetInputDeviceNames()
{
  PStringList Result;
  raw1394handle_t hdl = NULL;
  
  hdl = raw1394_new_handle();
  
  if (hdl == NULL)
    return Result;
  
  // scan all nodes of all ports, check the real name of the device
  int nb_ports = raw1394_get_port_info(hdl, NULL, 0);
  for(int pt = 0; pt < nb_ports; pt++) {
    if (raw1394_set_port(hdl, pt) >= 0) {
      int nb_nodes = raw1394_get_nodecount(hdl);
      for (int nd = 0; nd < nb_nodes; nd++) {
        rom1394_directory dir;
        rom1394_get_directory(hdl, nd, &dir);
        if (rom1394_get_node_type(&dir) == ROM1394_NODE_TYPE_AVC) {
          PString ufname = (PString)dir.label;
          PString *devname = new PString(pt);
          mutex.Wait();
          if (dico == NULL)
            dico = new PDictionary<PString, PString>;
          if (dico->Contains(ufname) && *dico->GetAt(ufname) != *devname) {
            PString altname = ufname+ " (2)";
            int i = 2;
            while(dico->Contains(altname) && *dico->GetAt(altname) != *devname) {
              i++;
              altname = ufname+ " ("+(PString)i+")";
            }
            dico->SetAt(altname, devname);
            Result.AppendString(altname);
          }
          else {
            dico->SetAt(ufname, devname);
            Result.AppendString(ufname);
          }
          mutex.Signal();
        }
      }
    }
  }
  
  raw1394_destroy_handle(hdl);
  return Result;
}

BOOL PVideoInputDevice_1394AVC::SetVideoFormat(VideoFormat newFormat)
{
  // FIXME: isn't it inherited from PVideoDevice anyway?
  if (!PVideoDevice::SetVideoFormat(newFormat)) {
    PTRACE(3,"PVideoDevice::SetVideoFormat failed");
    return FALSE;
  }
  else
    return TRUE;
}

int PVideoInputDevice_1394AVC::GetBrightness()
{
  return -1;
}

BOOL PVideoInputDevice_1394AVC::SetBrightness(unsigned newBrightness)
{
  return FALSE;
}

int PVideoInputDevice_1394AVC::GetHue()
{
  return -1;
}

BOOL PVideoInputDevice_1394AVC::SetHue(unsigned newHue)
{
  return FALSE;
}

int PVideoInputDevice_1394AVC::GetContrast()
{
  return -1;
}

BOOL PVideoInputDevice_1394AVC::SetContrast(unsigned newContrast)
{
  return FALSE;
}

BOOL PVideoInputDevice_1394AVC::SetColour(unsigned newColour) 
{
  return -1;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?