gusucode.com > audiovideo工具箱matlab源码程序 > audiovideo/@VideoReader/VideoReader.m
classdef (CaseInsensitiveProperties=true, TruncatedProperties=true) ... VideoReader < hgsetget & matlab.mixin.CustomDisplay % VIDEOREADER Create a multimedia reader object. % % OBJ = VIDEOREADER(FILENAME) constructs a multimedia reader object, OBJ, that % can read in video data from a multimedia file. FILENAME is a string % specifying the name of a multimedia file. There are no restrictions % on file extensions. By default, MATLAB looks for the file FILENAME on % the MATLAB path. % % OBJ = VIDEOREADER(FILENAME, 'P1', V1, 'P2', V2, ...) % constructs a multimedia reader object, assigning values V1, V2, etc. to % the specified properties P1, P2, etc. Note that the property value % pairs can be in any format supported by the SET function, e.g. % parameter-value string pairs, structures, or parameter-value cell array % pairs. % % Methods: % readFrame - Read the next available frame from a video file. % hasFrame - Determine if there is a frame available to read % from a video file. % getFileFormats - List of known supported video file formats. % % Properties: % Name - Name of the file to be read. % Path - Path of the file to be read. % Duration - Total length of file in seconds. % CurrentTime - Location from the start of the file of the current % frame to be read in seconds. % Tag - Generic string for the user to set. % UserData - Generic field for any user-defined data. % % Height - Height of the video frame in pixels. % Width - Width of the video frame in pixels. % BitsPerPixel - Bits per pixel of the video data. % VideoFormat - Video format as it is represented in MATLAB. % FrameRate - Frame rate of the video in frames per second. % % Example: % % Construct a multimedia reader object associated with file % % 'xylophone.mp4'. % vidObj = VideoReader('xylophone.mp4'); % % % Specify that reading should start at 0.5 seconds from the % % beginning. % vidObj.CurrentTime = 0.5; % % % Create an axes % currAxes = axes; % % % Read video frames until available % while hasFrame(vidObj) % vidFrame = readFrame(vidObj); % image(vidFrame, 'Parent', currAxes); % currAxes.Visible = 'off'; % pause(1/vidObj.FrameRate); % end % % See also AUDIOVIDEO, VIDEOREADER/READFRAME, VIDEOREADER/HASFRAME, MMFILEINFO. % % Authors: NH DL % Copyright 2005-2015 The MathWorks, Inc. %------------------------------------------------------------------ % General properties (in alphabetic order) %------------------------------------------------------------------ properties(GetAccess='public', SetAccess='private', Dependent) Duration % Total length of file in seconds. Name % Name of the file to be read. Path % Path of the file to be read. end properties(GetAccess='public', SetAccess='public') Tag = ''; % Generic string for the user to set. end properties(GetAccess='public', SetAccess='public') UserData % Generic field for any user-defined data. end %------------------------------------------------------------------ % Video properties (in alphabetic order) %------------------------------------------------------------------ properties(GetAccess='public', SetAccess='private', Dependent) BitsPerPixel % Bits per pixel of the video data. FrameRate % Frame rate of the video in frames per second. Height % Height of the video frame in pixels. VideoFormat % Video format as it is represented in MATLAB. Width % Width of the video frame in pixels. end properties(Access='public', Dependent) CurrentTime % Location, in seconds, from the start of the % file of the current frame to be read. end %------------------------------------------------------------------ % Undocumented properties %------------------------------------------------------------------ properties(GetAccess='public', SetAccess='private', Dependent, Hidden) AudioCompression NumberOfAudioChannels VideoCompression % NUMBEROFFRAMES property will be removed in a future release. Use % CURRENTTIME property instead. NumberOfFrames % Total number of frames in the video stream. end %------------------------------------------------------------------ % Private properties %------------------------------------------------------------------ properties(Access='private', Hidden) % To help support future forward compatibility. SchemaVersion = 8.3; % To handle construction on load. LoadArgs end properties(Access='private', Hidden, Transient) % Underlying implementation object. VideoReaderImpl % Enable frame counting % This property will be removed as it is no longer relevant. EnableFrameCounting; % Flag to determine if frame-based operations are being performed % on the file. % Once frame-based operations have been enabled, time-based % operations are not permitted. IsFrameBased = false; % Flag to determine if frame counting has been performed. % This is used avoid counting of frames during every query of % NumberOfFrames property. IsFramesCounted = false; % Flag to determine if time-based operations are being performed % on the file. % Once time-based operations have been enabled, frame-based % operations are not permitted. IsStreamingBased = false; end %------------------------------------------------------------------ % Documented methods %------------------------------------------------------------------ methods(Access='public') %------------------------------------------------------------------ % Lifetime %------------------------------------------------------------------ function obj = VideoReader(fileName, varargin) % If no file name provided. if nargin == 0 error(message('MATLAB:audiovideo:VideoReader:noFile')); end try validateattributes(fileName, {'char'}, {'row', 'vector'}, 'VideoReader'); catch ME throwAsCaller(ME); end % Initialize the object. % The duration of the file needs to be determined before the % CurrentTime can be set. obj.init(fileName); % Set properties that user passed in. if nargin > 1 set(obj, varargin{:}); end end %------------------------------------------------------------------ % Operations %------------------------------------------------------------------ inspect(obj) varargout = readFrame(obj, varargin) eof = hasFrame(obj) %------------------------------------------------------------------ % Overrides of builtins %------------------------------------------------------------------ c = horzcat(varargin) c = vertcat(varargin) c = cat(varargin) end methods(Access='public', Hidden) varargout = read(obj, varargin) end methods(Static) %------------------------------------------------------------------ % Operations %------------------------------------------------------------------ function formats = getFileFormats() % GETFILEFORMATS % % FORMATS = VIDEOREADER.GETFILEFORMATS() returns an object % array of audiovideo.FileFormatInfo objects which are the % formats VIDEOREADER is known to support on the current % platform. % % The properties of an audiovideo.FileFormatInfo object are: % % Extension - The file extension for this file format % Description - A text description of the file format % ContainsVideo - The File Format can hold video data % ContainsAudio - The File Format can hold audio data % extensions = audiovideo.mmreader.getSupportedFormats(); formats = audiovideo.FileFormatInfo.empty(); for ii=1:length(extensions) formats(ii) = audiovideo.FileFormatInfo( extensions{ii}, ... VideoReader.translateDescToLocale(extensions{ii}), ... true, ... false ); end % sort file extension [~, sortedIndex] = sort({formats.Extension}); formats = formats(sortedIndex); end end methods(Static, Hidden) %------------------------------------------------------------------ % Persistence %------------------------------------------------------------------ obj = loadobj(B) end %------------------------------------------------------------------ % Custom Getters/Setters %------------------------------------------------------------------ methods % Properties that are not dependent on underlying object. function set.Tag(obj, value) validateattributes( value, {'char'}, {}, 'set', 'Tag'); obj.Tag = value; end % Properties that are dependent on underlying object. function value = get.Duration(obj) try value = obj.getImplValue('Duration'); catch exception VideoReader.handleImplException(exception); end % Duration property is set to empty if it cannot be determined % from the video. Generate a warning to indicate this. if isempty(value) warnState=warning('off','backtrace'); c = onCleanup(@()warning(warnState)); warning(message('MATLAB:audiovideo:VideoReader:unknownDuration')); end end function set.Duration(obj, value) obj.errorAsNotSettable('Duration', value); end function value = get.Name(obj) value = obj.getImplValue('Name'); end function set.Name(obj, value) obj.errorAsNotSettable('Name', value); end function value = get.Path(obj) value = obj.getImplValue('Path'); end function set.Path(obj, value) obj.errorAsNotSettable('Path', value); end function value = get.BitsPerPixel(obj) value = obj.getImplValue('BitsPerPixel'); end function set.BitsPerPixel(obj, value) obj.errorAsNotSettable('BitsPerPixel', value); end function value = get.FrameRate(obj) value = obj.getImplValue('FrameRate'); end function set.FrameRate(obj, value) obj.errorAsNotSettable('FrameRate', value); end function value = get.Height(obj) value = obj.getImplValue('Height'); end function set.Height(obj, value) obj.errorAsNotSettable('Height', value); end function value = get.NumberOfFrames(obj) if obj.IsStreamingBased error( message('MATLAB:audiovideo:VideoReader:GetNumFramesNotAllowed') ); end % If the video has been scanned to count the number of frames, % do no repeat the operaton. if ~obj.IsFramesCounted obj.populateNumFrames(); obj.IsFramesCounted = true; end value = obj.getImplValue('NumberOfFrames'); % NumberOfFrames property is set to empty if it cannot be % determined by from the video. Generate a warning in this % case. if isempty(value) warnState=warning('off','backtrace'); c = onCleanup(@()warning(warnState)); warning(message('MATLAB:audiovideo:VideoReader:unknownNumFrames')); end end function set.NumberOfFrames(obj, value) obj.errorAsNotSettable('NumberOfFrames', value); end function value = get.VideoFormat(obj) value = obj.getImplValue('VideoFormat'); end function set.VideoFormat(obj, value) obj.errorAsNotSettable('VideoFormat', value); end function value = get.Width(obj) value = obj.getImplValue('Width'); end function set.Width(obj, value) obj.errorAsNotSettable('Width', value); end function value = get.AudioCompression(obj) value = obj.getImplValue('AudioCompression'); end function set.AudioCompression(obj, value) obj.errorAsNotSettable('AudioCompression', value); end function value = get.NumberOfAudioChannels(obj) value = obj.getImplValue('NumberOfAudioChannels'); end function set.NumberOfAudioChannels(obj, value) obj.errorAsNotSettable('NumberOfAudioChannels', value); end function value = get.VideoCompression(obj) value = obj.getImplValue('VideoCompression'); end function set.VideoCompression(obj, value) obj.errorAsNotSettable('VideoCompression', value); end function value = get.CurrentTime(obj) try value = obj.getImplValue('CurrentTime'); catch ME VideoReader.handleImplException(ME); end end function set.CurrentTime(obj, value) if obj.IsFrameBased error( message('MATLAB:audiovideo:VideoReader:SetCurrentTimeNotAllowed') ); end % Check that the duration of the file is known. if ~isempty(obj.Duration) try validateattributes( value, {'double'}, ... {'scalar', 'nonnegative', '<=', obj.Duration}, ... 'set', 'CurrentTime'); catch ME throwAsCaller(ME); end end currentTimeOC = onCleanup( @() set(obj, 'IsStreamingBased', 'true') ); try obj.getImpl().CurrentTime = value; catch exception VideoReader.handleImplException(exception); end end end %------------------------------------------------------------------ % Overrides for Custom Display %------------------------------------------------------------------ methods (Access='protected') function propGroups = getPropertyGroups(~) import matlab.mixin.util.PropertyGroup; propGroups(1) = PropertyGroup( {'Name', 'Path', 'Duration', 'CurrentTime', 'Tag', 'UserData'}, ... getString( message('MATLAB:audiovideo:VideoReader:GeneralProperties') ) ); propGroups(2) = PropertyGroup( {'Width', 'Height', 'FrameRate', 'BitsPerPixel', 'VideoFormat'}, ... getString( message('MATLAB:audiovideo:VideoReader:VideoProperties') ) ); end end %------------------------------------------------------------------ % Overrides for Custom Display when calling get(vidObj) %------------------------------------------------------------------ methods (Hidden) function getdisp(obj) display(obj); end end %------------------------------------------------------------------ % Undocumented methods %------------------------------------------------------------------ methods (Access='public', Hidden) %------------------------------------------------------------------ % Lifetime %------------------------------------------------------------------ function delete(obj) % Delete VideoReader object. try delete(obj.getImpl()); catch exception VideoReader.handleImplException( exception ); end end %------------------------------------------------------------------ % Operations %------------------------------------------------------------------ function result = hasAudio(obj) try result = hasAudio(obj.getImpl()); catch exception VideoReader.handleImplException( exception ); end end function result = hasVideo(obj) try result = hasVideo(obj.getImpl()); catch exception VideoReader.handleImplException( exception ); end end end methods (Static, Access='public', Hidden) function handleImplException(implException) messageArgs = { implException.identifier }; if (~isempty(implException.message)) messageArgs{end+1} = implException.message; end msgObj = message(messageArgs{:}); throwAsCaller(MException(implException.identifier, '%s',msgObj.getString)); end end methods (Static, Access='private', Hidden) function errorIfImageFormat( fileName ) isImageFormat = false; try % see if imfinfo recognizes this file as an image imfinfo( fileName ); isImageFormat = true; catch exception %#ok<NASGU> % imfinfo does not recognize this file, don't error % since it is most likely a valid multimedia file end if isImageFormat % If imfinfo does not error, then show this error error(message('MATLAB:audiovideo:VideoReader:unsupportedImage')); end end function errorIfTextFormat(fileName) %Don't try to open text files with known text extensions. [~,~,ext] = fileparts(fileName); textExts = {'txt','text','csv','html','xml','m'}; if ~isempty(ext) && any(strcmpi(ext(2:end),textExts)) error(message('MATLAB:audiovideo:VideoReader:unsupportedText')); end end function fileDesc = translateDescToLocale(fileExtension) switch upper(fileExtension) case 'M4V' fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatM4V')); case 'MJ2' fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatMJ2')); case 'MOV' fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatMOV')); case 'MP4' fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatMP4')); case 'MPG' fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatMPG')); case 'OGV' fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatOGV')); case 'WMV' fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatWMV')); otherwise % This includes formats such as AVI, ASF, ASX. fileDesc = getString(message('MATLAB:audiovideo:VideoReader:formatGeneric', upper(fileExtension))); end end function outputFormat = validateOutputFormat(outputFormat, callerFcn) validFormats = {'native', 'default'}; outputFormat = validatestring( outputFormat, validFormats, callerFcn,'outputformat'); end function outputFrames = convertToOutputFormat( inputFrames, inputFormat, outputFormat, colormap) switch outputFormat case 'default' outputFrames = VideoReader.convertToDefault(inputFrames, inputFormat, colormap); case 'native' outputFrames = VideoReader.convertToNative(inputFrames, inputFormat, colormap); otherwise assert(false, 'Unexpected outputFormat %s', outputFormat); end end function outputFrames = convertToDefault(inputFrames, inputFormat, colormap) if ~ismember(inputFormat, {'Indexed', 'Grayscale'}) % No conversion necessary, return the native data outputFrames = inputFrames; return; end % Return 'Indexed' data as RGB24 when asking for % the 'Default' output. This is done to preserve % RGB24 compatibility for customers using versions of % VideoReader prior to R2013a. outputFrames = zeros(size(inputFrames), 'uint8'); if strcmp(inputFormat, 'Grayscale') for ii=1:size(inputFrames, 4) % Indexed to Grayscale Image conversion (ind2gray) is part of IPT % and not base-MATLAB. tempFrame = ind2rgb( inputFrames(:,:,:,ii), colormap); outputFrames(:,:,ii) = tempFrame(:, :, 1); end else outputFrames = repmat(outputFrames, [1, 1, 3, 1]); for ii=1:size(inputFrames, 4) outputFrames(:,:,:,ii) = ind2rgb( inputFrames(:,:,:,ii), colormap); end end end function outputFrames = convertToNative(inputFrames, inputFormat, colormap) if ~ismember(inputFormat, {'Indexed', 'Grayscale'}) % No conversion necessary, return the native data outputFrames = inputFrames; return; end % normalize the colormap colormap = double(colormap)/255; numFrames = size(inputFrames, 4); outputFrames(1:numFrames) = struct; for ii = 1:numFrames; outputFrames(ii).cdata = inputFrames(:,:,:,ii); outputFrames(ii).colormap = colormap; end end end %------------------------------------------------------------------ % Helpers %------------------------------------------------------------------ methods (Access='private', Hidden) function init(obj, fileName, varargin) % Properly initialize the object on construction or load. currentTime = []; if nargin == 3 assert( isa(varargin{1}, 'double') && isscalar(varargin{1}), 'Last input argument is the current time'); currentTime = varargin{1}; end % Expand the path, using the matlab path if necessary fullName = audiovideo.internal.absolutePathForReading(... fileName, ... 'MATLAB:audiovideo:VideoReader:FileNotFound', ... 'MATLAB:audiovideo:VideoReader:FilePermissionDenied'); VideoReader.errorIfImageFormat(fullName); VideoReader.errorIfTextFormat(fullName); % Create underlying implementation. try obj.VideoReaderImpl = audiovideo.mmreader(fullName); catch exception VideoReader.handleImplException( exception ); end if ~isempty(currentTime) obj.CurrentTime = currentTime; end end function populateNumFrames(obj) try if ~obj.IsFrameBased populateNumFrames(obj.getImpl()); obj.IsFrameBased = true; else return; end catch exception VideoReader.handleImplException( exception ); end end function impl = getImpl(obj) impl = obj.VideoReaderImpl; end function value = getImplValue(obj, propName) value = obj.getImpl().(propName); end function errorAsNotSettable(obj, propName, value) %#ok<INUSD> % All underlying properties are read only. Make the error % the same as a standard MATLAB error when setting externally. % TODO: Remove when g449420 is done and used when calling % set() in the constructor. err = MException('MATLAB:class:SetProhibited',... 'Setting the ''%s'' property of the ''%s'' class is not allowed.',... propName, class(obj)); throwAsCaller(err); end function [headings, indices] = getCategoryInfo(obj, propNames) % Returns headings and property indices for each category. headings = {'General Settings' 'Video Settings', 'Audio Settings'}; indices = {[] [] []}; for pi=1:length(propNames) propInfo = findprop(getImpl(obj), propNames{pi}); if isempty(propInfo) || strcmpi(propInfo.Category, 'none') category = 'general'; else category = propInfo.Category; end switch category case 'general' indices{1}(end+1) = pi; case 'video' indices{2}(end+1) = pi; case 'audio' indices{3}(end+1) = pi; end end end end end