1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
|
/*****************************************************************************
* *
* OpenNI 2.x Alpha *
* Copyright (C) 2012 PrimeSense Ltd. *
* *
* This file is part of OpenNI. *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
* You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* *
*****************************************************************************/
#ifndef OPENNI_ONIRECORDER_H_
#define OPENNI_ONIRECORDER_H_ 1
#include "XnErrorLogger.h"
#include "XnLockable.h"
#include "XnString.h"
#include "XnPriorityQueue.h"
// These come from OniFile/Formats
#include "Xn16zEmbTablesCodec.h"
#include "XnJpegCodec.h"
#include "XnUncompressedCodec.h"
#include "OniCommon.h"
#include "OniFrameManager.h"
#include "OniDataRecords.h"
#include "OniStream.h"
#include "OniCTypes.h"
ONI_NAMESPACE_IMPLEMENTATION_BEGIN
class VideoStream;
/**
* The private implementation of a recorder.
*/
class Recorder
{
public:
/**
* Constructs a recorder, given an ErrorLogger and a handle.
* @note The newly constructed recorder becomes the owner of the handle.
* @note The handle might be NULL.
*/
Recorder(FrameManager& frameManager, xnl::ErrorLogger& errorLogger, OniRecorderHandle handle = NULL);
/**
* Destroys the recorder and stops recording if needed.
*/
~Recorder();
/**
* Initializes the recorder.
* @param fileName The file that will store the recording.
*/
OniStatus initialize(const char* fileName);
/**
* Attaches a stream to the recorder. Can not be done if Start() has been
* called at least once.
*/
OniStatus attachStream(VideoStream& stream, OniBool allowLossyCompression);
/**
* Detaches a stream from the recorder.
*/
OniStatus detachStream(VideoStream& stream);
/**
* Detaches all streams from the recorder.
*/
OniStatus detachAllStreams();
/**
* Starts recording.
* @note There's a known side effect related to AttachStream(Stream&).
* @see AttachStream(Stream&)
*/
OniStatus start();
/**
* Stops recording.
*/
void stop();
/**
* Records a frame into the given stream.
*/
OniStatus record(VideoStream& stream, OniFrame& aFrame);
/**
*
*/
OniStatus recordStreamProperty(
VideoStream& stream,
int propertyId,
const void* pData,
int dataSize);
private:
XN_DISABLE_COPY_AND_ASSIGN(Recorder)
// Messages are sent to Recorder's message loop and executed asynchronously.
// Please note: not all the fields are valid for every message. For example,
// Message::MESSAGE_DETACH relies only upon the nodeId field of the message, other
// fields are invalid and irrelevant for that message.
struct Message
{
enum Type
{
MESSAGE_NO_OPERATION, ///< Does not use any of Message fields. Does nothing.
MESSAGE_INITIALIZE, ///< Does not use any of Message fields.
MESSAGE_TERMINATE, ///< Does not use any of Message fields.
MESSAGE_ATTACH, ///< Uses: nodeId, pStream
MESSAGE_DETACH, ///< Uses: nodeId
MESSAGE_START, ///< Does not use any of Message fields.
MESSAGE_RECORD, ///< Uses: nodeId, pFrame
MESSAGE_RECORDPROPERTY,
}
type;
XnUInt32 nodeId;
VideoStream* pStream;
union {
const void* pData;
OniFrame* pFrame;
};
XnUInt32 propertyId;
XnSizeT dataSize;
};
// Used for undo functionality.
class Memento;
friend class Memento;
// The main function of Recorder's thread.
static XN_THREAD_PROC threadMain(XN_THREAD_PARAM pThreadParam);
// Obtains the next message from the queue of messages and executes an
// action associated with that message.
void messagePump();
// Sends a message to the threadMain.
void send(
Message::Type type,
VideoStream* pStream = NULL,
const void* pData = NULL,
XnUInt32 propertyId = 0u,
XnSizeT dataSize = 0u,
int priority = ms_priorityNormal);
// Message handlers:
void onInitialize();
void onTerminate();
void onAttach(XnUInt32 nodeId, VideoStream* pStream);
void onDetach(XnUInt32 nodeId);
void onStart (XnUInt32 nodeId);
void onRecord(XnUInt32 nodeId, XnCodecBase* pCodec, const OniFrame* pFrame, XnUInt32 frameId, XnUInt64 timestamp);
void onRecordProperty(
XnUInt32 nodeId,
XnUInt32 propertyId,
const void* pData,
XnSizeT dataSize);
FrameManager& m_frameManager;
// Error logger.
xnl::ErrorLogger& m_errorLogger;
// There's a 1:1 mapping between a Recorder object and a handle to that object.
// The Recorder object owns its handle.
OniRecorderHandle m_handle;
// Stores utility information about a stream. Currently the structure is
// pretty simple, but it might evolve in future.
struct AttachedStreamInfo
{
XnUInt32 nodeId;
XnUInt32 frameId;
XnCodecBase* pCodec;
OniBool allowLossyCompression;
XnUInt64 lastInputTimestamp;
XnUInt64 lastOutputTimestamp;
// needed for overriding the NODE_ADDED record when detaching the stream
XnUInt64 nodeAddedRecordPosition;
XnUInt32 nodeType;
XnUInt32 codecId;
// needed for keeping track of undoRecordPos field
XnUInt64 lastNewDataRecordPosition;
xnl::Hash<const char *, XnUInt64>
lastPropertyRecordPosition;
// needed for generating the SeekTable in the end
DataIndexEntryList dataIndex;
};
// A map of stream -> stream information.
typedef xnl::Lockable< xnl::Hash<VideoStream*, AttachedStreamInfo> > AttachedStreams;
AttachedStreams m_streams;
// A helper function for the properties' undoRecordPos
XnUInt64 getLastPropertyRecordPos(XnUInt32 nodeId, const char *propName, XnUInt64 newRecordPos);
// The maximum ID of a stream. This number grows with the every next stream
// attached to this Recorder and never decreases.
XnUInt32 m_maxId;
// increased any time when a property changes in ANY attached stream,
// to avoid the player seeking with the tables when a configuration has changed.
XnUInt32 m_configurationId;
// A message queue, used by threadMain and Send().
typedef xnl::Lockable<xnl::PriorityQueue<Message, 3> > MessageQueue;
MessageQueue m_queue;
int m_propertyPriority;
static const int ms_priorityLow = 2;
static const int ms_priorityNormal = 1;
static const int ms_priorityHigh = 0;
// The Recorder uses RecordAssembler to assemble records correctly and to
// serialize them to a file.
RecordAssembler m_assembler;
XN_THREAD_HANDLE m_thread;
FileHeaderData m_fileHeader; //< Will be patched during termination.
xnl::String m_fileName;
XN_FILE_HANDLE m_file;
XnBool m_running; //< TRUE whenever the threadMain is running.
XnBool m_started; //< TRUE whenever the recorder has started.
XnBool m_wasStarted; //< TRUE if the recorder has been started once.
// Get rid of macros:
#undef ONI_DISABLE_COPY_AND_ASSIGN
};
ONI_NAMESPACE_IMPLEMENTATION_END
#endif // OPENNI_ONIRECORDER_H_
|