mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-30 11:08:34 +00:00
pbutils: New Profile library
https://bugzilla.gnome.org/show_bug.cgi?id=627476
This commit is contained in:
parent
3457bc7149
commit
82b4f9bfef
14 changed files with 3021 additions and 0 deletions
|
@ -4,6 +4,7 @@ SUBDIRS =
|
|||
EXTRA_DIST = \
|
||||
design-audiosinks.txt \
|
||||
design-decodebin.txt \
|
||||
design-encoding.txt \
|
||||
design-orc-integration.txt \
|
||||
draft-keyframe-force.txt \
|
||||
draft-va.txt \
|
||||
|
|
571
docs/design/design-encoding.txt
Normal file
571
docs/design/design-encoding.txt
Normal file
|
@ -0,0 +1,571 @@
|
|||
Encoding and Muxing
|
||||
-------------------
|
||||
|
||||
Summary
|
||||
-------
|
||||
A. Problems
|
||||
B. Goals
|
||||
1. EncodeBin
|
||||
2. Encoding Profile System
|
||||
3. Helper Library for Profiles
|
||||
I. Use-cases researched
|
||||
|
||||
|
||||
A. Problems this proposal attempts to solve
|
||||
-------------------------------------------
|
||||
|
||||
* Duplication of pipeline code for gstreamer-based applications
|
||||
wishing to encode and or mux streams, leading to subtle differences
|
||||
and inconsistencies accross those applications.
|
||||
|
||||
* No unified system for describing encoding targets for applications
|
||||
in a user-friendly way.
|
||||
|
||||
* No unified system for creating encoding targets for applications,
|
||||
resulting in duplication of code accross all applications,
|
||||
differences and inconsistencies that come with that duplication,
|
||||
and applications hardcoding element names and settings resulting in
|
||||
poor portability.
|
||||
|
||||
|
||||
|
||||
B. Goals
|
||||
--------
|
||||
|
||||
1. Convenience encoding element
|
||||
|
||||
Create a convenience GstBin for encoding and muxing several streams,
|
||||
hereafter called 'EncodeBin'.
|
||||
|
||||
This element will only contain one single property, which is a
|
||||
profile.
|
||||
|
||||
2. Define a encoding profile system
|
||||
|
||||
2. Encoding profile helper library
|
||||
|
||||
Create a helper library to:
|
||||
* create EncodeBin instances based on profiles, and
|
||||
* help applications to create/load/save/browse those profiles.
|
||||
|
||||
|
||||
|
||||
|
||||
1. EncodeBin
|
||||
------------
|
||||
|
||||
1.1 Proposed API
|
||||
----------------
|
||||
|
||||
EncodeBin is a GstBin subclass.
|
||||
|
||||
It implements the GstTagSetter interface, by which it will proxy the
|
||||
calls to the muxer.
|
||||
|
||||
Only two introspectable property (i.e. usable without extra API):
|
||||
* A GstEncodingProfile*
|
||||
* The name of the profile to use
|
||||
|
||||
When a profile is selected, encodebin will:
|
||||
* Add REQUEST sinkpads for all the GstStreamProfile
|
||||
* Create the muxer and expose the source pad
|
||||
|
||||
Whenever a request pad is created, encodebin will:
|
||||
* Create the chain of elements for that pad
|
||||
* Ghost the sink pad
|
||||
* Return that ghost pad
|
||||
|
||||
This allows reducing the code to the minimum for applications
|
||||
wishing to encode a source for a given profile:
|
||||
|
||||
...
|
||||
|
||||
encbin = gst_element_factory_make("encodebin, NULL);
|
||||
g_object_set (encbin, "profile", "N900/H264 HQ", NULL);
|
||||
gst_element_link (encbin, filesink);
|
||||
|
||||
...
|
||||
|
||||
vsrcpad = gst_element_get_src_pad(source, "src1");
|
||||
vsinkpad = gst_element_get_request_pad (encbin, "video_%d");
|
||||
gst_pad_link(vsrcpad, vsinkpad);
|
||||
|
||||
...
|
||||
|
||||
|
||||
1.2 Explanation of the Various stages in EncodeBin
|
||||
--------------------------------------------------
|
||||
|
||||
This describes the various stages which can happen in order to end
|
||||
up with a multiplexed stream that can then be stored or streamed.
|
||||
|
||||
1.2.1 Incoming streams
|
||||
|
||||
The streams fed to EncodeBin can be of various types:
|
||||
|
||||
* Video
|
||||
* Uncompressed (but maybe subsampled)
|
||||
* Compressed
|
||||
* Audio
|
||||
* Uncompressed (audio/x-raw-{int|float})
|
||||
* Compressed
|
||||
* Timed text
|
||||
* Private streams
|
||||
|
||||
|
||||
1.2.2 Steps involved for raw video encoding
|
||||
|
||||
(0) Incoming Stream
|
||||
|
||||
(1) Transform raw video feed (optional)
|
||||
|
||||
Here we modify the various fundamental properties of a raw video
|
||||
stream to be compatible with the intersection of:
|
||||
* The encoder GstCaps and
|
||||
* The specified "Stream Restriction" of the profile/target
|
||||
|
||||
The fundamental properties that can be modified are:
|
||||
* width/height
|
||||
This is done with a video scaler.
|
||||
The DAR (Display Aspect Ratio) MUST be respected.
|
||||
If needed, black borders can be added to comply with the target DAR.
|
||||
* framerate
|
||||
* format/colorspace/depth
|
||||
All of this is done with a colorspace converter
|
||||
|
||||
(2) Actual encoding (optional for raw streams)
|
||||
|
||||
An encoder (with some optional settings) is used.
|
||||
|
||||
(3) Muxing
|
||||
|
||||
A muxer (with some optional settings) is used.
|
||||
|
||||
(4) Outgoing encoded and muxed stream
|
||||
|
||||
|
||||
1.2.3 Steps involved for raw audio encoding
|
||||
|
||||
This is roughly the same as for raw video, expect for (1)
|
||||
|
||||
(1) Transform raw audo feed (optional)
|
||||
|
||||
We modify the various fundamental properties of a raw audio stream to
|
||||
be compatible with the intersection of:
|
||||
* The encoder GstCaps and
|
||||
* The specified "Stream Restriction" of the profile/target
|
||||
|
||||
The fundamental properties that can be modifier are:
|
||||
* Number of channels
|
||||
* Type of raw audio (integer or floating point)
|
||||
* Depth (number of bits required to encode one sample)
|
||||
|
||||
|
||||
1.2.4 Steps involved for encoded audio/video streams
|
||||
|
||||
Steps (1) and (2) are replaced by a parser if a parser is available
|
||||
for the given format.
|
||||
|
||||
|
||||
1.2.5 Steps involved for other streams
|
||||
|
||||
Other streams will just be forwarded as-is to the muxer, provided the
|
||||
muxer accepts the stream type.
|
||||
|
||||
|
||||
|
||||
|
||||
2. Encoding Profile System
|
||||
--------------------------
|
||||
|
||||
This work is based on:
|
||||
* The existing GstPreset system for elements [0]
|
||||
* The gnome-media GConf audio profile system [1]
|
||||
* The investigation done into device profiles by Arista and
|
||||
Transmageddon [2 and 3]
|
||||
|
||||
2.2 Terminology
|
||||
---------------
|
||||
|
||||
* Encoding Target Category
|
||||
A Target Category is a classification of devices/systems/use-cases
|
||||
for encoding.
|
||||
|
||||
Such a classification is required in order for:
|
||||
* Applications with a very-specific use-case to limit the number of
|
||||
profiles they can offer the user. A screencasting application has
|
||||
no use with the online services targets for example.
|
||||
* Offering the user some initial classification in the case of a
|
||||
more generic encoding application (like a video editor or a
|
||||
transcoder).
|
||||
|
||||
Ex:
|
||||
Consumer devices
|
||||
Online service
|
||||
Intermediate Editing Format
|
||||
Screencast
|
||||
Capture
|
||||
Computer
|
||||
|
||||
* Encoding Profile Target
|
||||
A Profile Target describes a specific entity for which we wish to
|
||||
encode.
|
||||
A Profile Target must belong to at least one Target Category.
|
||||
It will define at least one Encoding Profile.
|
||||
|
||||
Ex (with category):
|
||||
Nokia N900 (Consumer device)
|
||||
Sony PlayStation 3 (Consumer device)
|
||||
Youtube (Online service)
|
||||
DNxHD (Intermediate editing format)
|
||||
HuffYUV (Screencast)
|
||||
Theora (Computer)
|
||||
|
||||
* Encoding Profile
|
||||
A specific combination of muxer, encoders, presets and limitations.
|
||||
|
||||
Ex:
|
||||
Nokia N900/H264 HQ
|
||||
Ipod/High Quality
|
||||
DVD/Pal
|
||||
Youtube/High Quality
|
||||
HTML5/Low Bandwith
|
||||
DNxHD
|
||||
|
||||
2.3 Encoding Profile
|
||||
--------------------
|
||||
|
||||
An encoding profile requires the following information:
|
||||
|
||||
* Name
|
||||
This string is not translatable and must be unique.
|
||||
A recommendation to guarantee uniqueness of the naming could be:
|
||||
<target>/<name>
|
||||
* Description
|
||||
This is a translatable string describing the profile
|
||||
* Muxing format
|
||||
This is a string containing the GStreamer media-type of the
|
||||
container format.
|
||||
* Muxing preset
|
||||
This is an optional string describing the preset(s) to use on the
|
||||
muxer.
|
||||
* Multipass setting
|
||||
This is a boolean describing whether the profile requires several
|
||||
passes.
|
||||
* List of Stream Profile
|
||||
|
||||
2.3.1 Stream Profiles
|
||||
|
||||
A Stream Profile consists of:
|
||||
|
||||
* Type
|
||||
The type of stream profile (audio, video, text, private-data)
|
||||
* Encoding Format
|
||||
This is a string containing the GStreamer media-type of the encoding
|
||||
format to be used. If encoding is not to be applied, the raw audio
|
||||
media type will be used.
|
||||
* Encoding preset
|
||||
This is an optional string describing the preset(s) to use on the
|
||||
encoder.
|
||||
* Restriction
|
||||
This is an optional GstCaps containing the restriction of the
|
||||
stream that can be fed to the encoder.
|
||||
This will generally containing restrictions in video
|
||||
width/heigh/framerate or audio depth.
|
||||
* presence
|
||||
This is an integer specifying how many streams can be used in the
|
||||
containing profile. 0 means that any number of streams can be
|
||||
used.
|
||||
* pass
|
||||
This is an integer which is only meaningful if the multipass flag
|
||||
has been set in the profile. If it has been set it indicates which
|
||||
pass this Stream Profile corresponds to.
|
||||
|
||||
2.4 Example profile
|
||||
-------------------
|
||||
|
||||
The representation used here is XML only as an example. No decision is
|
||||
made as to which formatting to use for storing targets and profiles.
|
||||
|
||||
<gst-encoding-target>
|
||||
<name>Nokia N900</name>
|
||||
<category>Consumer Device</category>
|
||||
<profiles>
|
||||
<profile>Nokia N900/H264 HQ</profile>
|
||||
<profile>Nokia N900/MP3</profile>
|
||||
<profile>Nokia N900/AAC</profile>
|
||||
</profiles>
|
||||
</gst-encoding-target>
|
||||
|
||||
<gst-encoding-profile>
|
||||
<name>Nokia N900/H264 HQ</name>
|
||||
<description>
|
||||
High Quality H264/AAC for the Nokia N900
|
||||
</description>
|
||||
<format>video/quicktime,variant=iso</format>
|
||||
<streams>
|
||||
<stream-profile>
|
||||
<type>audio</type>
|
||||
<format>audio/mpeg,mpegversion=4</format>
|
||||
<preset>Quality High/Main</preset>
|
||||
<restriction>audio/x-raw-int,channels=[1,2]</restriction>
|
||||
<presence>1</presence>
|
||||
</stream-profile>
|
||||
<stream-profile>
|
||||
<type>video</type>
|
||||
<format>video/x-h264</format>
|
||||
<preset>Profile Baseline/Quality High</preset>
|
||||
<restriction>
|
||||
video/x-raw-yuv,width=[16, 800],\
|
||||
height=[16, 480],framerate=[1/1, 30000/1001]
|
||||
</restriction>
|
||||
<presence>1</presence>
|
||||
</stream-profile>
|
||||
</streams>
|
||||
|
||||
</gst-encoding-profile>
|
||||
|
||||
2.5 API
|
||||
-------
|
||||
A proposed C API is contained in the gstprofile.h file in this directory.
|
||||
|
||||
|
||||
2.6 Modifications required in the existing GstPreset system
|
||||
-----------------------------------------------------------
|
||||
|
||||
2.6.1. Temporary preset.
|
||||
|
||||
Currently a preset needs to be saved on disk in order to be
|
||||
used.
|
||||
|
||||
This makes it impossible to have temporary presets (that exist only
|
||||
during the lifetime of a process), which might be required in the
|
||||
new proposed profile system
|
||||
|
||||
2.6.2 Categorisation of presets.
|
||||
|
||||
Currently presets are just aliases of a group of property/value
|
||||
without any meanings or explanation as to how they exclude each
|
||||
other.
|
||||
|
||||
Take for example the H264 encoder. It can have presets for:
|
||||
* passes (1,2 or 3 passes)
|
||||
* profiles (Baseline, Main, ...)
|
||||
* quality (Low, medium, High)
|
||||
|
||||
In order to programmatically know which presets exclude each other,
|
||||
we here propose the categorisation of these presets.
|
||||
|
||||
This can be done in one of two ways
|
||||
1. in the name (by making the name be [<category>:]<name>)
|
||||
This would give for example: "Quality:High", "Profile:Baseline"
|
||||
2. by adding a new _meta key
|
||||
This would give for example: _meta/category:quality
|
||||
|
||||
2.6.3 Aggregation of presets.
|
||||
|
||||
There can be more than one choice of presets to be done for an
|
||||
element (quality, profile, pass).
|
||||
|
||||
This means that one can not currently describe the full
|
||||
configuration of an element with a single string but with many.
|
||||
|
||||
The proposal here is to extend the GstPreset API to be able to set
|
||||
all presets using one string and a well-known separator ('/').
|
||||
|
||||
This change only requires changes in the core preset handling code.
|
||||
|
||||
This would allow doing the following:
|
||||
gst_preset_load_preset (h264enc,
|
||||
"pass:1/profile:baseline/quality:high");
|
||||
|
||||
2.7 Points to be determined
|
||||
---------------------------
|
||||
|
||||
This document hasn't determined yet how to solve the following
|
||||
problems:
|
||||
|
||||
2.7.1 Storage of profiles
|
||||
|
||||
One proposal for storage would be to use a system wide directory
|
||||
(like $prefix/share/gstreamer-0.10/profiles) and store XML files for
|
||||
every individual profiles.
|
||||
|
||||
Users could then add their own profiles in ~/.gstreamer-0.10/profiles
|
||||
|
||||
This poses some limitations as to what to do if some applications
|
||||
want to have some profiles limited to their own usage.
|
||||
|
||||
|
||||
3. Helper library for profiles
|
||||
------------------------------
|
||||
|
||||
These helper methods could also be added to existing libraries (like
|
||||
GstPreset, GstPbUtils, ..).
|
||||
|
||||
The various API proposed are in the accompanying gstprofile.h file.
|
||||
|
||||
3.1 Getting user-readable names for formats
|
||||
|
||||
This is already provided by GstPbUtils.
|
||||
|
||||
3.2 Hierarchy of profiles
|
||||
|
||||
The goal is for applications to be able to present to the user a list
|
||||
of combo-boxes for choosing their output profile:
|
||||
|
||||
[ Category ] # optional, depends on the application
|
||||
[ Device/Site/.. ] # optional, depends on the application
|
||||
[ Profile ]
|
||||
|
||||
Convenience methods are offered to easily get lists of categories,
|
||||
devices, and profiles.
|
||||
|
||||
3.3 Creating Profiles
|
||||
|
||||
The goal is for applications to be able to easily create profiles.
|
||||
|
||||
The applications needs to be able to have a fast/efficient way to:
|
||||
* select a container format and see all compatible streams he can use
|
||||
with it.
|
||||
* select a codec format and see which container formats he can use
|
||||
with it.
|
||||
|
||||
The remaining parts concern the restrictions to encoder
|
||||
input.
|
||||
|
||||
3.4 Ensuring availability of plugins for Profiles
|
||||
|
||||
When an application wishes to use a Profile, it should be able to
|
||||
query whether it has all the needed plugins to use it.
|
||||
|
||||
This part will use GstPbUtils to query, and if needed install the
|
||||
missing plugins through the installed distribution plugin installer.
|
||||
|
||||
|
||||
I. Use-cases researched
|
||||
-----------------------
|
||||
|
||||
This is a list of various use-cases where encoding/muxing is being
|
||||
used.
|
||||
|
||||
* Transcoding
|
||||
|
||||
The goal is to convert with as minimal loss of quality any input
|
||||
file for a target use.
|
||||
A specific variant of this is transmuxing (see below).
|
||||
|
||||
Example applications: Arista, Transmageddon
|
||||
|
||||
* Rendering timelines
|
||||
|
||||
The incoming streams are a collection of various segments that need
|
||||
to be rendered.
|
||||
Those segments can vary in nature (i.e. the video width/height can
|
||||
change).
|
||||
This requires the use of identiy with the single-segment property
|
||||
activated to transform the incoming collection of segments to a
|
||||
single continuous segment.
|
||||
|
||||
Example applications: PiTiVi, Jokosher
|
||||
|
||||
* Encoding of live sources
|
||||
|
||||
The major risk to take into account is the encoder not encoding the
|
||||
incoming stream fast enough. This is outside of the scope of
|
||||
encodebin, and should be solved by using queues between the sources
|
||||
and encodebin, as well as implementing QoS in encoders and sources
|
||||
(the encoders emitting QoS events, and the upstream elements
|
||||
adapting themselves accordingly).
|
||||
|
||||
Example applications: camerabin, cheese
|
||||
|
||||
* Screencasting applications
|
||||
|
||||
This is similar to encoding of live sources.
|
||||
The difference being that due to the nature of the source (size and
|
||||
amount/frequency of updates) one might want to do the encoding in
|
||||
two parts:
|
||||
* The actual live capture is encoded with a 'almost-lossless' codec
|
||||
(such as huffyuv)
|
||||
* Once the capture is done, the file created in the first step is
|
||||
then rendered to the desired target format.
|
||||
|
||||
Fixing sources to only emit region-updates and having encoders
|
||||
capable of encoding those streams would fix the need for the first
|
||||
step but is outside of the scope of encodebin.
|
||||
|
||||
Example applications: Istanbul, gnome-shell, recordmydesktop
|
||||
|
||||
* Live transcoding
|
||||
|
||||
This is the case of an incoming live stream which will be
|
||||
broadcasted/transmitted live.
|
||||
One issue to take into account is to reduce the encoding latency to
|
||||
a minimum. This should mostly be done by picking low-latency
|
||||
encoders.
|
||||
|
||||
Example applications: Rygel, Coherence
|
||||
|
||||
* Transmuxing
|
||||
|
||||
Given a certain file, the aim is to remux the contents WITHOUT
|
||||
decoding into either a different container format or the same
|
||||
container format.
|
||||
Remuxing into the same container format is useful when the file was
|
||||
not created properly (for example, the index is missing).
|
||||
Whenever available, parsers should be applied on the encoded streams
|
||||
to validate and/or fix the streams before muxing them.
|
||||
|
||||
Metadata from the original file must be kept in the newly created
|
||||
file.
|
||||
|
||||
Example applications: Arista, Transmaggedon
|
||||
|
||||
* Loss-less cutting
|
||||
|
||||
Given a certain file, the aim is to extract a certain part of the
|
||||
file without going through the process of decoding and re-encoding
|
||||
that file.
|
||||
This is similar to the transmuxing use-case.
|
||||
|
||||
Example applications: PiTiVi, Transmageddon, Arista, ...
|
||||
|
||||
* Multi-pass encoding
|
||||
|
||||
Some encoders allow doing a multi-pass encoding.
|
||||
The initial pass(es) are only used to collect encoding estimates and
|
||||
are not actually muxed and outputted.
|
||||
The final pass uses previously collected information, and the output
|
||||
is then muxed and outputted.
|
||||
|
||||
* Archiving and intermediary format
|
||||
|
||||
The requirement is to have lossless
|
||||
|
||||
* CD ripping
|
||||
|
||||
Example applications: Sound-juicer
|
||||
|
||||
* DVD ripping
|
||||
|
||||
Example application: Thoggen
|
||||
|
||||
|
||||
|
||||
* Research links
|
||||
|
||||
Some of these are still active documents, some other not
|
||||
|
||||
[0] GstPreset API documentation
|
||||
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstPreset.html
|
||||
|
||||
[1] gnome-media GConf profiles
|
||||
http://www.gnome.org/~bmsmith/gconf-docs/C/gnome-media.html
|
||||
|
||||
[2] Research on a Device Profile API
|
||||
http://gstreamer.freedesktop.org/wiki/DeviceProfile
|
||||
|
||||
[3] Research on defining presets usage
|
||||
http://gstreamer.freedesktop.org/wiki/PresetDesign
|
||||
|
|
@ -206,6 +206,7 @@
|
|||
<xi:include href="xml/gstpbutilsmissingplugins.xml" />
|
||||
<xi:include href="xml/gstpbutilsinstallplugins.xml" />
|
||||
<xi:include href="xml/gstdiscoverer.xml" />
|
||||
<xi:include href="xml/encoding-profile.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="gstreamer-video">
|
||||
|
|
|
@ -1907,6 +1907,91 @@ gst_codec_utils_mpeg4video_get_level
|
|||
gst_codec_utils_mpeg4video_caps_set_level_and_profile
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>encoding-profile</FILE>
|
||||
<INCLUDE>gst/pbutils/encoding-profile.h</INCLUDE>
|
||||
GstEncodingProfile
|
||||
gst_encoding_profile_unref
|
||||
gst_encoding_profile_ref
|
||||
gst_encoding_profile_get_name
|
||||
gst_encoding_profile_get_description
|
||||
gst_encoding_profile_get_format
|
||||
gst_encoding_profile_get_preset
|
||||
gst_encoding_profile_get_presence
|
||||
gst_encoding_profile_get_restriction
|
||||
gst_encoding_profile_set_name
|
||||
gst_encoding_profile_set_description
|
||||
gst_encoding_profile_set_format
|
||||
gst_encoding_profile_set_preset
|
||||
gst_encoding_profile_set_restriction
|
||||
gst_encoding_profile_set_presence
|
||||
gst_encoding_profile_is_equal
|
||||
gst_encoding_profile_get_output_caps
|
||||
gst_encoding_profile_get_type_nick
|
||||
<SUBSECTION container>
|
||||
GstEncodingContainerProfile
|
||||
gst_encoding_container_profile_new
|
||||
gst_encoding_container_profile_add_profile
|
||||
gst_encoding_container_profile_contains_profile
|
||||
gst_encoding_container_profile_get_profiles
|
||||
<SUBSECTION audio>
|
||||
GstEncodingAudioProfile
|
||||
gst_encoding_audio_profile_new
|
||||
<SUBSECTION video>
|
||||
GstEncodingVideoProfile
|
||||
gst_encoding_video_profile_new
|
||||
gst_encoding_video_profile_get_pass
|
||||
gst_encoding_video_profile_get_variableframerate
|
||||
gst_encoding_video_profile_set_pass
|
||||
gst_encoding_video_profile_set_variableframerate
|
||||
<SUBSECTION targets>
|
||||
GST_ENCODING_CATEGORY_DEVICE
|
||||
GST_ENCODING_CATEGORY_ONLINE_SERVICE
|
||||
GST_ENCODING_CATEGORY_STORAGE_EDITING
|
||||
GST_ENCODING_CATEGORY_CAPTURE
|
||||
GstEncodingTarget
|
||||
gst_encoding_target_unref
|
||||
gst_encoding_target_ref
|
||||
gst_encoding_target_new
|
||||
gst_encoding_target_get_name
|
||||
gst_encoding_target_get_category
|
||||
gst_encoding_target_get_description
|
||||
gst_encoding_target_get_profiles
|
||||
gst_encoding_target_add_profile
|
||||
gst_encoding_target_save
|
||||
gst_encoding_target_save_to
|
||||
gst_encoding_target_load
|
||||
gst_encoding_target_load_from
|
||||
<SUBSECTION Standard>
|
||||
GST_ENCODING_PROFILE
|
||||
GST_IS_ENCODING_PROFILE
|
||||
GST_TYPE_ENCODING_PROFILE
|
||||
gst_encoding_profile_get_type
|
||||
GST_ENCODING_TARGET
|
||||
GST_IS_ENCODING_TARGET
|
||||
GST_TYPE_ENCODING_TARGET
|
||||
gst_encoding_target_get_type
|
||||
GstEncodingProfileClass
|
||||
GST_TYPE_ENCODING_CONTAINER_PROFILE
|
||||
GST_ENCODING_CONTAINER_PROFILE
|
||||
gst_encoding_container_profile_get_type
|
||||
GST_TYPE_ENCODING_VIDEO_PROFILE
|
||||
GST_ENCODING_VIDEO_PROFILE
|
||||
GST_IS_ENCODING_VIDEO_PROFILE
|
||||
GstEncodingVideoProfileClass
|
||||
gst_encoding_video_profile_get_type
|
||||
GST_TYPE_ENCODING_AUDIO_PROFILE
|
||||
GST_ENCODING_AUDIO_PROFILE
|
||||
GST_IS_ENCODING_AUDIO_PROFILE
|
||||
GstEncodingAudioProfileClass
|
||||
gst_encoding_audio_profile_get_type
|
||||
GST_IS_ENCODING_CONTAINER_PROFILE
|
||||
GstEncodingContainerProfileClass
|
||||
GstEncodingTargetClass
|
||||
</SECTION>
|
||||
|
||||
|
||||
|
||||
# video
|
||||
|
||||
<SECTION>
|
||||
|
|
|
@ -59,3 +59,14 @@ gst_video_sink_get_type
|
|||
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
gst_discoverer_get_type
|
||||
|
||||
#include <gst/pbutils/encoding-profile.h>
|
||||
#include <gst/pbutils/encoding-target.h>
|
||||
gst_encoding_profile_get_type
|
||||
gst_encoding_video_profile_get_type
|
||||
gst_encoding_video_profile_get_type
|
||||
gst_encoding_audio_profile_get_type
|
||||
gst_encoding_container_profile_get_type
|
||||
gst_encoding_target_get_type
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ headers_pbutils = \
|
|||
pbutils.h \
|
||||
codec-utils.h \
|
||||
descriptions.h \
|
||||
encoding-profile.h \
|
||||
encoding-target.h \
|
||||
install-plugins.h \
|
||||
missing-plugins.h \
|
||||
gstdiscoverer.h
|
||||
|
@ -22,6 +24,8 @@ libgstpbutils_@GST_MAJORMINOR@_la_SOURCES = \
|
|||
pbutils.c \
|
||||
codec-utils.c \
|
||||
descriptions.c \
|
||||
encoding-profile.c \
|
||||
encoding-target.c \
|
||||
install-plugins.c \
|
||||
missing-plugins.c \
|
||||
gstdiscoverer.c \
|
||||
|
|
834
gst-libs/gst/pbutils/encoding-profile.c
Normal file
834
gst-libs/gst/pbutils/encoding-profile.c
Normal file
|
@ -0,0 +1,834 @@
|
|||
/* GStreamer encoding profiles library
|
||||
* Copyright (C) 2009-2010 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||
* (C) 2009-2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:encoding-profile
|
||||
* @short_description: Encoding profile library
|
||||
*
|
||||
* <refsect2>
|
||||
* <para>
|
||||
* Functions to create and handle encoding profiles.
|
||||
* </para>
|
||||
* <para>
|
||||
* Encoding profiles describe the media types and settings one wishes to use for
|
||||
* an encoding process. The top-level profiles are commonly
|
||||
* #GstEncodingContainerProfile(s) (which contains user-readable name and
|
||||
* description along with which container format to use) which references one or
|
||||
* more #GstEncodingProfile(s) which indicate which encoding format should be
|
||||
* used on each individual streams.
|
||||
* </para>
|
||||
* <para>
|
||||
* #GstEncodingProfile(s) can be provided to the 'encodebin' element, which will take
|
||||
* care of selecting and setting up the required elements to produce an output stream
|
||||
* conforming to the specifications of the profile.
|
||||
* </para>
|
||||
* <para>
|
||||
* Unlike other systems, the encoding profiles do not specify which #GstElement to use
|
||||
* for the various encoding and muxing steps, but instead relies on specifying the format
|
||||
* one wishes to use.
|
||||
* </para>
|
||||
* <para>
|
||||
* Encoding profiles can be created at runtime by the application or loaded from (and saved
|
||||
* to) file using the #GstEncodingTarget API.
|
||||
* </para>
|
||||
* </refsect2>
|
||||
* <refsect2>
|
||||
* <title>Example: Creating a profile</title>
|
||||
* <para>
|
||||
* |[
|
||||
* #include <gst/pbutils/encoding-profile.h>
|
||||
* ...
|
||||
* GstEncodingProfile *
|
||||
* create_ogg_theora_profile(void)
|
||||
*{
|
||||
* GstEncodingContainerProfile *prof;
|
||||
* GstCaps *caps;
|
||||
*
|
||||
* caps = gst_caps_from_string("application/ogg");
|
||||
* prof = gst_encoding_container_profile_new("Ogg audio/video",
|
||||
* "Standard OGG/THEORA/VORBIS",
|
||||
* caps, NULL);
|
||||
* gst_caps_unref (caps);
|
||||
*
|
||||
* caps = gst_caps_from_string("video/x-theora");
|
||||
* sprof = gst_encoding_container_profile_add_profile(
|
||||
* (GstEncodingProfile*) gst_encoding_video_profile_new(caps, NULL, NULL, 0));
|
||||
* gst_caps_unref (caps);
|
||||
*
|
||||
* caps = gst_caps_from_string("audio/x-vorbis");
|
||||
* sprof = gst_encoding_container_profile_add_profile(
|
||||
* (GstEncodingProfile*) gst_encoding_audio_profile_new(caps, NULL, NULL, 0));
|
||||
* gst_caps_unref (caps);
|
||||
*
|
||||
* return (GstEncodingProfile*) prof;
|
||||
*}
|
||||
*
|
||||
*
|
||||
* ]|
|
||||
* </para>
|
||||
* </refsect2>
|
||||
* <refsect2>
|
||||
* <title>Example: Loading a profile from disk</title>
|
||||
* <para>
|
||||
* |[
|
||||
* #include <gst/pbutils/encoding-profile.h>
|
||||
* ...
|
||||
*GstEncodingProfile *
|
||||
*get_ogg_theora_profile(const gchar *path, const gchar *profilename)
|
||||
*{
|
||||
* GstEncodingProfile *prof = NULL;
|
||||
* GstEncodingTarget *target = NULL;
|
||||
* GList *tmp;
|
||||
*
|
||||
* target = gst_encoding_target_load_from (path);
|
||||
* if (target == NULL)
|
||||
* return NULL;
|
||||
*
|
||||
* for (tmp = target->profiles; tmp; tmp = tmp->next) {
|
||||
* GstEncodingProfile *ptmp = (GstEncodingProfile*) tmp->data;
|
||||
*
|
||||
* if (!strcmp(gst_encoding_profile_get_name(ptmp), profilename)) {
|
||||
* prof = ptmp;
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* return prof;
|
||||
*}
|
||||
* ]|
|
||||
* </para>
|
||||
* </refsect2>
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "encoding-profile.h"
|
||||
|
||||
/* GstEncodingProfile API */
|
||||
|
||||
struct _GstEncodingProfile
|
||||
{
|
||||
GstMiniObject parent;
|
||||
|
||||
/*< public > */
|
||||
gchar *name;
|
||||
gchar *description;
|
||||
GstCaps *format;
|
||||
gchar *preset;
|
||||
guint presence;
|
||||
GstCaps *restriction;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstEncodingProfile, gst_encoding_profile, GST_TYPE_MINI_OBJECT);
|
||||
|
||||
static void
|
||||
gst_encoding_profile_init (GstEncodingProfile * prof)
|
||||
{
|
||||
/* Nothing to initialize */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_profile_finalize (GstEncodingProfile * prof)
|
||||
{
|
||||
if (prof->name)
|
||||
g_free (prof->name);
|
||||
if (prof->format)
|
||||
gst_caps_unref (prof->format);
|
||||
if (prof->preset)
|
||||
g_free (prof->preset);
|
||||
if (prof->description)
|
||||
g_free (prof->description);
|
||||
if (prof->restriction)
|
||||
gst_caps_unref (prof->restriction);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_profile_class_init (GstMiniObjectClass * klass)
|
||||
{
|
||||
klass->finalize =
|
||||
(GstMiniObjectFinalizeFunction) gst_encoding_profile_finalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_name:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: the name of the profile, can be %NULL.
|
||||
*/
|
||||
const gchar *
|
||||
gst_encoding_profile_get_name (GstEncodingProfile * profile)
|
||||
{
|
||||
return profile->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_description:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: the description of the profile, can be %NULL.
|
||||
*/
|
||||
const gchar *
|
||||
gst_encoding_profile_get_description (GstEncodingProfile * profile)
|
||||
{
|
||||
return profile->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_format:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: the media format used in the profile.
|
||||
*/
|
||||
const GstCaps *
|
||||
gst_encoding_profile_get_format (GstEncodingProfile * profile)
|
||||
{
|
||||
return profile->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_preset:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: the preset to be used in the profile.
|
||||
*/
|
||||
const gchar *
|
||||
gst_encoding_profile_get_preset (GstEncodingProfile * profile)
|
||||
{
|
||||
return profile->preset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_presence:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The number of time the profile is used in its parent
|
||||
* container profile. If 0, it is not a mandatory stream
|
||||
*/
|
||||
const guint
|
||||
gst_encoding_profile_get_presence (GstEncodingProfile * profile)
|
||||
{
|
||||
return profile->presence;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_restriction:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The restriction #GstCaps to apply before the encoder
|
||||
* that will be used in the profile. Does not apply to #GstEncodingContainerProfile.
|
||||
* Can be %NULL.
|
||||
*/
|
||||
const GstCaps *
|
||||
gst_encoding_profile_get_restriction (GstEncodingProfile * profile)
|
||||
{
|
||||
return profile->restriction;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_set_name:
|
||||
* @profile: a #GstEncodingProfile
|
||||
* @name: the name to set on the profile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Set @name as the given name for the @profile. A copy of @name will be made
|
||||
* internally.
|
||||
*/
|
||||
void
|
||||
gst_encoding_profile_set_name (GstEncodingProfile * profile, const gchar * name)
|
||||
{
|
||||
if (profile->name)
|
||||
g_free (profile->name);
|
||||
profile->name = g_strdup (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_set_description:
|
||||
* @profile: a #GstEncodingProfile
|
||||
* @description: the description to set on the profile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Set @description as the given description for the @profile. A copy of @description will be made
|
||||
* internally.
|
||||
*/
|
||||
void
|
||||
gst_encoding_profile_set_description (GstEncodingProfile * profile,
|
||||
const gchar * description)
|
||||
{
|
||||
if (profile->description)
|
||||
g_free (profile->description);
|
||||
profile->description = g_strdup (description);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_set_format:
|
||||
* @profile: a #GstEncodingProfile
|
||||
* @format: the media format to use in the profile.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Sets the media format used in the profile.
|
||||
*/
|
||||
void
|
||||
gst_encoding_profile_set_format (GstEncodingProfile * profile, GstCaps * format)
|
||||
{
|
||||
if (profile->format)
|
||||
gst_caps_unref (profile->format);
|
||||
profile->format = gst_caps_ref (format);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_set_preset:
|
||||
* @profile: a #GstEncodingProfile
|
||||
* @preset: the element preset to use
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Sets the preset to use for the profile.
|
||||
*/
|
||||
void
|
||||
gst_encoding_profile_set_preset (GstEncodingProfile * profile,
|
||||
const gchar * preset)
|
||||
{
|
||||
if (profile->preset)
|
||||
g_free (profile->preset);
|
||||
profile->preset = g_strdup (preset);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_set_presence:
|
||||
* @profile: a #GstEncodingProfile
|
||||
* @presence: the number of time the profile can be used
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Set the number of time the profile is used in its parent
|
||||
* container profile. If 0, it is not a mandatory stream
|
||||
*/
|
||||
void
|
||||
gst_encoding_profile_set_presence (GstEncodingProfile * profile, guint presence)
|
||||
{
|
||||
profile->presence = presence;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_set_restriction:
|
||||
* @profile: a #GstEncodingProfile
|
||||
* @restriction: the restriction to apply
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Set the restriction #GstCaps to apply before the encoder
|
||||
* that will be used in the profile. Does not apply to #GstEncodingContainerProfile.
|
||||
*/
|
||||
void
|
||||
gst_encoding_profile_set_restriction (GstEncodingProfile * profile,
|
||||
GstCaps * restriction)
|
||||
{
|
||||
if (profile->restriction)
|
||||
gst_caps_unref (profile->restriction);
|
||||
profile->restriction = restriction;
|
||||
}
|
||||
|
||||
/* Container profiles */
|
||||
|
||||
struct _GstEncodingContainerProfile
|
||||
{
|
||||
GstEncodingProfile parent;
|
||||
|
||||
GList *encodingprofiles;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstEncodingContainerProfile, gst_encoding_container_profile,
|
||||
GST_TYPE_ENCODING_PROFILE);
|
||||
|
||||
static void
|
||||
gst_encoding_container_profile_init (GstEncodingContainerProfile * prof)
|
||||
{
|
||||
/* Nothing to initialize */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_container_profile_finalize (GstEncodingContainerProfile * prof)
|
||||
{
|
||||
g_list_foreach (prof->encodingprofiles, (GFunc) gst_mini_object_unref, NULL);
|
||||
g_list_free (prof->encodingprofiles);
|
||||
|
||||
GST_MINI_OBJECT_CLASS (gst_encoding_container_profile_parent_class)->finalize
|
||||
((GstMiniObject *) prof);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_container_profile_class_init (GstMiniObjectClass * klass)
|
||||
{
|
||||
klass->finalize =
|
||||
(GstMiniObjectFinalizeFunction) gst_encoding_container_profile_finalize;
|
||||
}
|
||||
|
||||
const GList *
|
||||
gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *
|
||||
profile)
|
||||
{
|
||||
return profile->encodingprofiles;
|
||||
}
|
||||
|
||||
/* Video profiles */
|
||||
|
||||
struct _GstEncodingVideoProfile
|
||||
{
|
||||
GstEncodingProfile parent;
|
||||
|
||||
guint pass;
|
||||
gboolean variableframerate;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstEncodingVideoProfile, gst_encoding_video_profile,
|
||||
GST_TYPE_ENCODING_PROFILE);
|
||||
|
||||
static void
|
||||
gst_encoding_video_profile_init (GstEncodingVideoProfile * prof)
|
||||
{
|
||||
/* Nothing to initialize */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_video_profile_class_init (GstMiniObjectClass * klass)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_video_profile_get_pass:
|
||||
* @prof: a #GstEncodingVideoProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The pass number if this is part of a multi-pass profile. Starts at
|
||||
* 1 for multi-pass. 0 if this is not a multi-pass profile
|
||||
**/
|
||||
guint
|
||||
gst_encoding_video_profile_get_pass (GstEncodingVideoProfile * prof)
|
||||
{
|
||||
return prof->pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_video_profile_get_variableframerate:
|
||||
* @prof: a #GstEncodingVideoProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: Whether non-constant video framerate is allowed for encoding.
|
||||
*/
|
||||
gboolean
|
||||
gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *
|
||||
prof)
|
||||
{
|
||||
return prof->variableframerate;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_video_profile_set_pass:
|
||||
* @prof: a #GstEncodingVideoProfile
|
||||
* @pass: the pass number for this profile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Sets the pass number of this video profile. The first pass profile should have
|
||||
* this value set to 1. If this video profile isn't part of a multi-pass profile,
|
||||
* you may set it to 0 (the default value).
|
||||
*/
|
||||
void
|
||||
gst_encoding_video_profile_set_pass (GstEncodingVideoProfile * prof, guint pass)
|
||||
{
|
||||
prof->pass = pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_video_profile_set_variableframerate:
|
||||
* @prof: a #GstEncodingVideoProfile
|
||||
* @variableframerate: a boolean
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* If set to %TRUE, then the incoming streamm will be allowed to have non-constant
|
||||
* framerate. If set to %FALSE (default value), then the incoming stream will
|
||||
* be normalized by dropping/duplicating frames in order to produce a
|
||||
* constance framerate.
|
||||
*/
|
||||
void
|
||||
gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *
|
||||
prof, gboolean variableframerate)
|
||||
{
|
||||
prof->variableframerate = variableframerate;
|
||||
}
|
||||
|
||||
/* Audio profiles */
|
||||
|
||||
struct _GstEncodingAudioProfile
|
||||
{
|
||||
GstEncodingProfile parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstEncodingAudioProfile, gst_encoding_audio_profile,
|
||||
GST_TYPE_ENCODING_PROFILE);
|
||||
|
||||
static void
|
||||
gst_encoding_audio_profile_init (GstEncodingAudioProfile * prof)
|
||||
{
|
||||
/* Nothing to initialize */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_audio_profile_class_init (GstMiniObjectClass * klass)
|
||||
{
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
_gst_caps_is_equal_safe (GstCaps * a, GstCaps * b)
|
||||
{
|
||||
if (a == b)
|
||||
return TRUE;
|
||||
if ((a == NULL) || (b == NULL))
|
||||
return FALSE;
|
||||
return gst_caps_is_equal (a, b);
|
||||
}
|
||||
|
||||
static gint
|
||||
_compare_container_encoding_profiles (GstEncodingContainerProfile * ca,
|
||||
GstEncodingContainerProfile * cb)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
if (g_list_length (ca->encodingprofiles) !=
|
||||
g_list_length (cb->encodingprofiles))
|
||||
return -1;
|
||||
|
||||
for (tmp = ca->encodingprofiles; tmp; tmp = tmp->next) {
|
||||
GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data;
|
||||
if (!gst_encoding_container_profile_contains_profile (ca, prof))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gint
|
||||
_compare_encoding_profiles (const GstEncodingProfile * a,
|
||||
const GstEncodingProfile * b)
|
||||
{
|
||||
if ((G_TYPE_FROM_INSTANCE (a) != G_TYPE_FROM_INSTANCE (b)) ||
|
||||
!_gst_caps_is_equal_safe (a->format, b->format) ||
|
||||
(g_strcmp0 (a->preset, b->preset) != 0) ||
|
||||
(g_strcmp0 (a->name, b->name) != 0) ||
|
||||
(g_strcmp0 (a->description, b->description) != 0))
|
||||
return -1;
|
||||
|
||||
if (GST_IS_ENCODING_CONTAINER_PROFILE (a))
|
||||
return
|
||||
_compare_container_encoding_profiles (GST_ENCODING_CONTAINER_PROFILE
|
||||
(a), GST_ENCODING_CONTAINER_PROFILE (b));
|
||||
|
||||
if (GST_IS_ENCODING_VIDEO_PROFILE (a)) {
|
||||
GstEncodingVideoProfile *va = (GstEncodingVideoProfile *) a;
|
||||
GstEncodingVideoProfile *vb = (GstEncodingVideoProfile *) b;
|
||||
|
||||
if ((va->pass != vb->pass)
|
||||
|| (va->variableframerate != vb->variableframerate))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_container_profile_contains_profile:
|
||||
* @container: a #GstEncodingContainerProfile
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Checks if @container contains a #GstEncodingProfile identical to
|
||||
* @profile.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: %TRUE if @container contains a #GstEncodingProfile identical
|
||||
* to @profile, else %FALSE.
|
||||
*/
|
||||
gboolean
|
||||
gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile *
|
||||
container, GstEncodingProfile * profile)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
|
||||
g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
|
||||
|
||||
return (g_list_find_custom (container->encodingprofiles, profile,
|
||||
(GCompareFunc) _compare_encoding_profiles) != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_container_profile_add_profile:
|
||||
* @container: the #GstEncodingContainerProfile to use
|
||||
* @profile: the #GstEncodingProfile to add.
|
||||
*
|
||||
* Add a #GstEncodingProfile to the list of profiles handled by @container.
|
||||
*
|
||||
* No copy of @profile will be made, if you wish to use it elsewhere after this
|
||||
* method you should increment its reference count.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: %TRUE if the @stream was properly added, else %FALSE.
|
||||
*/
|
||||
gboolean
|
||||
gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *
|
||||
container, GstEncodingProfile * profile)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE);
|
||||
g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
|
||||
|
||||
if (g_list_find_custom (container->encodingprofiles, profile,
|
||||
(GCompareFunc) _compare_encoding_profiles)) {
|
||||
GST_ERROR
|
||||
("Encoding profile already contains an identical GstEncodingProfile");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
container->encodingprofiles =
|
||||
g_list_append (container->encodingprofiles, profile);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstEncodingProfile *
|
||||
common_creation (GType objtype, GstCaps * format, const gchar * preset,
|
||||
const gchar * name, const gchar * description, GstCaps * restriction,
|
||||
guint presence)
|
||||
{
|
||||
GstEncodingProfile *prof;
|
||||
|
||||
prof = (GstEncodingProfile *) gst_mini_object_new (objtype);
|
||||
|
||||
if (name)
|
||||
prof->name = g_strdup (name);
|
||||
if (description)
|
||||
prof->description = g_strdup (description);
|
||||
if (preset)
|
||||
prof->preset = g_strdup (preset);
|
||||
if (format)
|
||||
prof->format = gst_caps_ref (format);
|
||||
if (restriction)
|
||||
prof->restriction = gst_caps_ref (restriction);
|
||||
prof->presence = presence;
|
||||
|
||||
return prof;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_container_profile_new:
|
||||
* @name: The name of the container profile, can be %NULL
|
||||
* @description: The description of the container profile, can be %NULL
|
||||
* @format: The format to use for this profile
|
||||
* @preset: The preset to use for this profile
|
||||
*
|
||||
* Creates a new #GstEncodingContainerProfile.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The newly created #GstEncodingContainerProfile.
|
||||
*/
|
||||
GstEncodingContainerProfile *
|
||||
gst_encoding_container_profile_new (const gchar * name,
|
||||
const gchar * description, GstCaps * format, const gchar * preset)
|
||||
{
|
||||
return (GstEncodingContainerProfile *)
|
||||
common_creation (GST_TYPE_ENCODING_CONTAINER_PROFILE, format, preset,
|
||||
name, description, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_video_profile_new:
|
||||
* @format: the #GstCaps
|
||||
* @preset: the preset(s) to use on the encoder, can be #NULL
|
||||
* @restriction: the #GstCaps used to restrict the input to the encoder, can be
|
||||
* NULL.
|
||||
* @presence: the number of time this stream must be used. 0 means any number of
|
||||
* times (including never)
|
||||
*
|
||||
* Creates a new #GstEncodingVideoProfile
|
||||
*
|
||||
* All provided allocatable arguments will be internally copied, so can be
|
||||
* safely freed/unreferenced after calling this method.
|
||||
*
|
||||
* If you wish to control the pass number (in case of multi-pass scenarios),
|
||||
* please refer to the gst_encoding_video_profile_set_pass() documentation.
|
||||
*
|
||||
* If you wish to use/force a constant framerate please refer to the
|
||||
* gst_encoding_video_profile_set_variableframerate() documentation.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: the newly created #GstEncodingVideoProfile.
|
||||
*/
|
||||
GstEncodingVideoProfile *
|
||||
gst_encoding_video_profile_new (GstCaps * format, const gchar * preset,
|
||||
GstCaps * restriction, guint presence)
|
||||
{
|
||||
return (GstEncodingVideoProfile *)
|
||||
common_creation (GST_TYPE_ENCODING_VIDEO_PROFILE, format, preset, NULL,
|
||||
NULL, restriction, presence);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_audio_profile_new:
|
||||
* @format: the #GstCaps
|
||||
* @preset: the preset(s) to use on the encoder, can be #NULL
|
||||
* @restriction: the #GstCaps used to restrict the input to the encoder, can be
|
||||
* NULL.
|
||||
* @presence: the number of time this stream must be used. 0 means any number of
|
||||
* times (including never)
|
||||
*
|
||||
* Creates a new #GstEncodingAudioProfile
|
||||
*
|
||||
* All provided allocatable arguments will be internally copied, so can be
|
||||
* safely freed/unreferenced after calling this method.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: the newly created #GstEncodingAudioProfile.
|
||||
*/
|
||||
GstEncodingAudioProfile *
|
||||
gst_encoding_audio_profile_new (GstCaps * format, const gchar * preset,
|
||||
GstCaps * restriction, guint presence)
|
||||
{
|
||||
return (GstEncodingAudioProfile *)
|
||||
common_creation (GST_TYPE_ENCODING_AUDIO_PROFILE, format, preset, NULL,
|
||||
NULL, restriction, presence);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_is_equal:
|
||||
* @a: a #GstEncodingProfile
|
||||
* @b: a #GstEncodingProfile
|
||||
*
|
||||
* Checks whether the two #GstEncodingProfile are equal
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: %TRUE if @a and @b are equal, else %FALSE.
|
||||
*/
|
||||
gboolean
|
||||
gst_encoding_profile_is_equal (GstEncodingProfile * a, GstEncodingProfile * b)
|
||||
{
|
||||
return (_compare_encoding_profiles (a, b) == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_output_caps:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Computes the full output caps that this @profile will be able to consume.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The full caps the given @profile can consume. Call gst_caps_unref()
|
||||
* when you are done with the caps.
|
||||
*/
|
||||
GstCaps *
|
||||
gst_encoding_profile_get_output_caps (GstEncodingProfile * profile)
|
||||
{
|
||||
GstCaps *out, *tmp;
|
||||
GList *ltmp;
|
||||
GstStructure *st, *outst;
|
||||
GQuark out_name;
|
||||
guint i, len;
|
||||
const GstCaps *fcaps;
|
||||
|
||||
if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
|
||||
GstCaps *res = gst_caps_new_empty ();
|
||||
|
||||
for (ltmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles;
|
||||
ltmp; ltmp = ltmp->next) {
|
||||
GstEncodingProfile *sprof = (GstEncodingProfile *) ltmp->data;
|
||||
gst_caps_merge (res, gst_encoding_profile_get_output_caps (sprof));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
fcaps = profile->format;
|
||||
|
||||
/* fast-path */
|
||||
if ((profile->restriction == NULL) || gst_caps_is_any (profile->restriction))
|
||||
return gst_caps_copy (fcaps);
|
||||
|
||||
/* Combine the format with the restriction caps */
|
||||
outst = gst_caps_get_structure (fcaps, 0);
|
||||
out_name = gst_structure_get_name_id (outst);
|
||||
tmp = gst_caps_new_empty ();
|
||||
len = gst_caps_get_size (profile->restriction);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
st = gst_structure_copy (gst_caps_get_structure (profile->restriction, i));
|
||||
st->name = out_name;
|
||||
gst_caps_append_structure (tmp, st);
|
||||
}
|
||||
|
||||
out = gst_caps_intersect (tmp, fcaps);
|
||||
gst_caps_unref (tmp);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_get_type_nick:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: the human-readable name of the type of @profile.
|
||||
*/
|
||||
const gchar *
|
||||
gst_encoding_profile_get_type_nick (GstEncodingProfile * profile)
|
||||
{
|
||||
if (GST_IS_ENCODING_CONTAINER_PROFILE (profile))
|
||||
return "container";
|
||||
if (GST_IS_ENCODING_VIDEO_PROFILE (profile))
|
||||
return "video";
|
||||
if (GST_IS_ENCODING_AUDIO_PROFILE (profile))
|
||||
return "audio";
|
||||
return NULL;
|
||||
}
|
184
gst-libs/gst/pbutils/encoding-profile.h
Normal file
184
gst-libs/gst/pbutils/encoding-profile.h
Normal file
|
@ -0,0 +1,184 @@
|
|||
/* GStreamer encoding profiles library
|
||||
* Copyright (C) 2009-2010 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||
* (C) 2009-2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_PROFILE_H__
|
||||
#define __GST_PROFILE_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#include <gst/pbutils/pbutils-enumtypes.h>
|
||||
|
||||
/**
|
||||
* GstEncodingProfile:
|
||||
*
|
||||
* The opaque base class object for all encoding profiles. This contains generic
|
||||
* information like name, description, format and preset.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
|
||||
#define GST_TYPE_ENCODING_PROFILE \
|
||||
(gst_encoding_profile_get_type ())
|
||||
#define GST_ENCODING_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_PROFILE, GstEncodingProfile))
|
||||
#define GST_IS_ENCODING_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_PROFILE))
|
||||
typedef struct _GstEncodingProfile GstEncodingProfile;
|
||||
typedef GstMiniObjectClass GstEncodingProfileClass;
|
||||
GType gst_encoding_profile_get_type (void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* GstEncodingContainerProfile:
|
||||
*
|
||||
* Encoding profiles for containers. Keeps track of a list of #GstEncodingProfile
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define GST_TYPE_ENCODING_CONTAINER_PROFILE \
|
||||
(gst_encoding_container_profile_get_type ())
|
||||
#define GST_ENCODING_CONTAINER_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_CONTAINER_PROFILE, GstEncodingContainerProfile))
|
||||
#define GST_IS_ENCODING_CONTAINER_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_CONTAINER_PROFILE))
|
||||
typedef struct _GstEncodingContainerProfile GstEncodingContainerProfile;
|
||||
typedef GstEncodingProfileClass GstEncodingContainerProfileClass;
|
||||
GType gst_encoding_container_profile_get_type (void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* GstEncodingVideoProfile:
|
||||
*
|
||||
* Variant of #GstEncodingProfile for video streams, allows specifying the @pass.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define GST_TYPE_ENCODING_VIDEO_PROFILE \
|
||||
(gst_encoding_video_profile_get_type ())
|
||||
#define GST_ENCODING_VIDEO_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_VIDEO_PROFILE, GstEncodingVideoProfile))
|
||||
#define GST_IS_ENCODING_VIDEO_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_VIDEO_PROFILE))
|
||||
typedef struct _GstEncodingVideoProfile GstEncodingVideoProfile;
|
||||
typedef GstEncodingProfileClass GstEncodingVideoProfileClass;
|
||||
GType gst_encoding_video_profile_get_type (void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* GstEncodingAudioProfile:
|
||||
*
|
||||
* Variant of #GstEncodingProfile for audio streams.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define GST_TYPE_ENCODING_AUDIO_PROFILE \
|
||||
(gst_encoding_audio_profile_get_type ())
|
||||
#define GST_ENCODING_AUDIO_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_AUDIO_PROFILE, GstEncodingAudioProfile))
|
||||
#define GST_IS_ENCODING_AUDIO_PROFILE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_AUDIO_PROFILE))
|
||||
typedef struct _GstEncodingAudioProfile GstEncodingAudioProfile;
|
||||
typedef GstEncodingProfileClass GstEncodingAudioProfileClass;
|
||||
GType gst_encoding_audio_profile_get_type (void);
|
||||
|
||||
|
||||
|
||||
/* GstEncodingProfile API */
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_unref:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Decreases the reference count of the @profile, possibly freeing the @profile.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define gst_encoding_profile_unref(profile) (gst_mini_object_unref ((GstMiniObject*) profile))
|
||||
|
||||
/**
|
||||
* gst_encoding_profile_ref:
|
||||
* @profile: a #GstEncodingProfile
|
||||
*
|
||||
* Increases the reference count of the @profile.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define gst_encoding_profile_ref(profile) (gst_mini_object_ref ((GstMiniObject*) profile))
|
||||
|
||||
const gchar * gst_encoding_profile_get_name(GstEncodingProfile *profile);
|
||||
const gchar * gst_encoding_profile_get_description(GstEncodingProfile *profile);
|
||||
const GstCaps * gst_encoding_profile_get_format(GstEncodingProfile *profile);
|
||||
const gchar * gst_encoding_profile_get_preset(GstEncodingProfile *profile);
|
||||
const guint gst_encoding_profile_get_presence(GstEncodingProfile *profile);
|
||||
const GstCaps * gst_encoding_profile_get_restriction(GstEncodingProfile *profile);
|
||||
|
||||
void gst_encoding_profile_set_name(GstEncodingProfile *profile, const gchar *name);
|
||||
void gst_encoding_profile_set_description(GstEncodingProfile *profile, const gchar *description);
|
||||
void gst_encoding_profile_set_format(GstEncodingProfile *profile, GstCaps *format);
|
||||
void gst_encoding_profile_set_preset(GstEncodingProfile *profile, const gchar *preset);
|
||||
void gst_encoding_profile_set_restriction(GstEncodingProfile *profile, GstCaps *restriction);
|
||||
void gst_encoding_profile_set_presence(GstEncodingProfile *profile, guint presence);
|
||||
|
||||
gboolean gst_encoding_profile_is_equal (GstEncodingProfile *a,
|
||||
GstEncodingProfile *b);
|
||||
GstCaps * gst_encoding_profile_get_output_caps (GstEncodingProfile *profile);
|
||||
|
||||
const gchar *gst_encoding_profile_get_type_nick (GstEncodingProfile *profile);
|
||||
|
||||
/* GstEncodingContainerProfile API */
|
||||
gboolean gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *container,
|
||||
GstEncodingProfile *profile);
|
||||
gboolean gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile * container,
|
||||
GstEncodingProfile *profile);
|
||||
const GList *gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *profile);
|
||||
|
||||
|
||||
GstEncodingContainerProfile * gst_encoding_container_profile_new (const gchar *name,
|
||||
const gchar *description,
|
||||
GstCaps *format,
|
||||
const gchar *preset);
|
||||
|
||||
|
||||
/* Invidual stream encodingprofile API */
|
||||
GstEncodingVideoProfile * gst_encoding_video_profile_new (GstCaps *format,
|
||||
const gchar *preset,
|
||||
GstCaps *restriction,
|
||||
guint presence);
|
||||
GstEncodingAudioProfile * gst_encoding_audio_profile_new (GstCaps *format,
|
||||
const gchar *preset,
|
||||
GstCaps *restriction,
|
||||
guint presence);
|
||||
|
||||
guint gst_encoding_video_profile_get_pass (GstEncodingVideoProfile *prof);
|
||||
gboolean gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *prof);
|
||||
|
||||
void gst_encoding_video_profile_set_pass (GstEncodingVideoProfile *prof,
|
||||
guint pass);
|
||||
void gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *prof,
|
||||
gboolean variableframerate);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_PROFILE_H__ */
|
724
gst-libs/gst/pbutils/encoding-target.c
Normal file
724
gst-libs/gst/pbutils/encoding-target.c
Normal file
|
@ -0,0 +1,724 @@
|
|||
/* GStreamer encoding profile registry
|
||||
* Copyright (C) 2010 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||
* (C) 2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <locale.h>
|
||||
#include "encoding-target.h"
|
||||
|
||||
/*
|
||||
* File format
|
||||
*
|
||||
* GKeyFile style.
|
||||
*
|
||||
* [_gstencodingtarget_]
|
||||
* name : <name>
|
||||
* category : <category>
|
||||
* description : <description> #translatable
|
||||
*
|
||||
* [profile-<profile1name>]
|
||||
* name : <name>
|
||||
* description : <description> #optional
|
||||
* format : <format>
|
||||
* preset : <preset>
|
||||
*
|
||||
* [streamprofile-<id>]
|
||||
* parent : <encodingprofile.name>[,<encodingprofile.name>..]
|
||||
* type : <type> # "audio", "video", "text"
|
||||
* format : <format>
|
||||
* preset : <preset>
|
||||
* restriction : <restriction>
|
||||
* presence : <presence>
|
||||
* pass : <pass>
|
||||
* variableframerate : <variableframerate>
|
||||
* */
|
||||
|
||||
#define GST_ENCODING_TARGET_HEADER "_gstencodingtarget_"
|
||||
|
||||
struct _GstEncodingTarget
|
||||
{
|
||||
GstMiniObject parent;
|
||||
|
||||
gchar *name;
|
||||
gchar *category;
|
||||
gchar *description;
|
||||
GList *profiles;
|
||||
|
||||
/*< private > */
|
||||
gchar *keyfile;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstEncodingTarget, gst_encoding_target, GST_TYPE_MINI_OBJECT);
|
||||
|
||||
static void
|
||||
gst_encoding_target_init (GstEncodingTarget * target)
|
||||
{
|
||||
/* Nothing to initialize */
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_target_finalize (GstEncodingTarget * target)
|
||||
{
|
||||
GST_DEBUG ("Finalizing");
|
||||
|
||||
if (target->name)
|
||||
g_free (target->name);
|
||||
if (target->category)
|
||||
g_free (target->category);
|
||||
if (target->description)
|
||||
g_free (target->description);
|
||||
|
||||
g_list_foreach (target->profiles, (GFunc) gst_mini_object_unref, NULL);
|
||||
g_list_free (target->profiles);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_encoding_target_class_init (GstMiniObjectClass * klass)
|
||||
{
|
||||
klass->finalize =
|
||||
(GstMiniObjectFinalizeFunction) gst_encoding_target_finalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_get_name:
|
||||
* @target: a #GstEncodingTarget
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The name of the @target.
|
||||
*/
|
||||
const gchar *
|
||||
gst_encoding_target_get_name (GstEncodingTarget * target)
|
||||
{
|
||||
return target->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_get_category:
|
||||
* @target: a #GstEncodingTarget
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The category of the @target.
|
||||
*/
|
||||
const gchar *
|
||||
gst_encoding_target_get_category (GstEncodingTarget * target)
|
||||
{
|
||||
return target->category;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_get_description:
|
||||
* @target: a #GstEncodingTarget
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The description of the @target.
|
||||
*/
|
||||
const gchar *
|
||||
gst_encoding_target_get_description (GstEncodingTarget * target)
|
||||
{
|
||||
return target->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_get_profiles:
|
||||
* @target: a #GstEncodingTarget
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: A list of #GstEncodingProfile(s) this @target handles.
|
||||
*/
|
||||
const GList *
|
||||
gst_encoding_target_get_profiles (GstEncodingTarget * target)
|
||||
{
|
||||
return target->profiles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_encoding_target_new:
|
||||
* @name: The name of the target.
|
||||
* @category: The name of the category to which this @target belongs.
|
||||
* @description: A description of #GstEncodingTarget in the current locale.
|
||||
* @profiles: A #GList of #GstEncodingProfile.
|
||||
*
|
||||
* Creates a new #GstEncodingTarget.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The newly created #GstEncodingTarget or %NULL if there was an
|
||||
* error.
|
||||
*/
|
||||
|
||||
GstEncodingTarget *
|
||||
gst_encoding_target_new (const gchar * name, const gchar * category,
|
||||
const gchar * description, const GList * profiles)
|
||||
{
|
||||
GstEncodingTarget *res;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
g_return_val_if_fail (category != NULL, NULL);
|
||||
g_return_val_if_fail (description != NULL, NULL);
|
||||
|
||||
res = (GstEncodingTarget *) gst_mini_object_new (GST_TYPE_ENCODING_TARGET);
|
||||
res->name = g_strdup (name);
|
||||
res->category = g_strdup (category);
|
||||
res->description = g_strdup (description);
|
||||
|
||||
while (profiles) {
|
||||
GstEncodingProfile *prof = (GstEncodingProfile *) profiles->data;
|
||||
|
||||
res->profiles =
|
||||
g_list_append (res->profiles, gst_encoding_profile_ref (prof));
|
||||
profiles = profiles->next;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_add_profile:
|
||||
* @target: the #GstEncodingTarget to add a profile to
|
||||
* @profile: the #GstEncodingProfile to add
|
||||
*
|
||||
* Adds the given @profile to the @target.
|
||||
*
|
||||
* The @target will steal a reference to the @profile. If you wish to use
|
||||
* the profile after calling this method, you should increase its reference
|
||||
* count.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: %TRUE if the profile was added, else %FALSE.
|
||||
**/
|
||||
|
||||
gboolean
|
||||
gst_encoding_target_add_profile (GstEncodingTarget * target,
|
||||
GstEncodingProfile * profile)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ENCODING_TARGET (target), FALSE);
|
||||
g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE);
|
||||
|
||||
/* Make sure profile isn't already controlled by this target */
|
||||
for (tmp = target->profiles; tmp; tmp = tmp->next) {
|
||||
GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data;
|
||||
|
||||
if (!g_strcmp0 (gst_encoding_profile_get_name (profile),
|
||||
gst_encoding_profile_get_name (prof))) {
|
||||
GST_WARNING ("Profile already present in target");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
target->profiles = g_list_append (target->profiles, profile);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
serialize_stream_profiles (GKeyFile * out, GstEncodingProfile * sprof,
|
||||
const gchar * profilename, guint id)
|
||||
{
|
||||
gchar *sprofgroupname;
|
||||
gchar *tmpc;
|
||||
const GstCaps *format, *restriction;
|
||||
const gchar *preset, *name, *description;
|
||||
|
||||
sprofgroupname = g_strdup_printf ("streamprofile-%s-%d", profilename, id);
|
||||
|
||||
/* Write the parent profile */
|
||||
g_key_file_set_value (out, sprofgroupname, "parent", profilename);
|
||||
|
||||
g_key_file_set_value (out, sprofgroupname, "type",
|
||||
gst_encoding_profile_get_type_nick (sprof));
|
||||
|
||||
format = gst_encoding_profile_get_format (sprof);
|
||||
if (format) {
|
||||
tmpc = gst_caps_to_string (format);
|
||||
g_key_file_set_value (out, sprofgroupname, "format", tmpc);
|
||||
g_free (tmpc);
|
||||
}
|
||||
|
||||
name = gst_encoding_profile_get_name (sprof);
|
||||
if (name)
|
||||
g_key_file_set_string (out, sprofgroupname, "name", name);
|
||||
|
||||
description = gst_encoding_profile_get_description (sprof);
|
||||
if (description)
|
||||
g_key_file_set_string (out, sprofgroupname, "description", description);
|
||||
|
||||
preset = gst_encoding_profile_get_preset (sprof);
|
||||
if (preset)
|
||||
g_key_file_set_string (out, sprofgroupname, "preset", preset);
|
||||
|
||||
restriction = gst_encoding_profile_get_restriction (sprof);
|
||||
if (restriction) {
|
||||
tmpc = gst_caps_to_string (restriction);
|
||||
g_key_file_set_value (out, sprofgroupname, "restriction", tmpc);
|
||||
g_free (tmpc);
|
||||
}
|
||||
g_key_file_set_integer (out, sprofgroupname, "presence",
|
||||
gst_encoding_profile_get_presence (sprof));
|
||||
|
||||
if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) {
|
||||
GstEncodingVideoProfile *vp = (GstEncodingVideoProfile *) sprof;
|
||||
|
||||
g_key_file_set_integer (out, sprofgroupname, "pass",
|
||||
gst_encoding_video_profile_get_pass (vp));
|
||||
g_key_file_set_boolean (out, sprofgroupname, "variableframerate",
|
||||
gst_encoding_video_profile_get_variableframerate (vp));
|
||||
}
|
||||
|
||||
g_free (sprofgroupname);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Serialize the top-level profiles
|
||||
* Note: They don't have to be containerprofiles */
|
||||
static gboolean
|
||||
serialize_encoding_profile (GKeyFile * out, GstEncodingProfile * prof)
|
||||
{
|
||||
gchar *profgroupname;
|
||||
const GList *tmp;
|
||||
guint i;
|
||||
const gchar *profname, *profdesc, *profpreset, *proftype;
|
||||
const GstCaps *profformat, *profrestriction;
|
||||
|
||||
profname = gst_encoding_profile_get_name (prof);
|
||||
profdesc = gst_encoding_profile_get_description (prof);
|
||||
profformat = gst_encoding_profile_get_format (prof);
|
||||
profpreset = gst_encoding_profile_get_preset (prof);
|
||||
proftype = gst_encoding_profile_get_type_nick (prof);
|
||||
profrestriction = gst_encoding_profile_get_restriction (prof);
|
||||
|
||||
profgroupname = g_strdup_printf ("profile-%s", profname);
|
||||
|
||||
g_key_file_set_string (out, profgroupname, "name", profname);
|
||||
|
||||
g_key_file_set_value (out, profgroupname, "type",
|
||||
gst_encoding_profile_get_type_nick (prof));
|
||||
|
||||
if (profdesc)
|
||||
g_key_file_set_locale_string (out, profgroupname, "description",
|
||||
setlocale (LC_ALL, NULL), profdesc);
|
||||
if (profformat) {
|
||||
gchar *tmpc = gst_caps_to_string (profformat);
|
||||
g_key_file_set_string (out, profgroupname, "format", tmpc);
|
||||
g_free (tmpc);
|
||||
}
|
||||
if (profpreset)
|
||||
g_key_file_set_string (out, profgroupname, "preset", profpreset);
|
||||
|
||||
/* stream profiles */
|
||||
if (GST_IS_ENCODING_CONTAINER_PROFILE (prof)) {
|
||||
for (tmp =
|
||||
gst_encoding_container_profile_get_profiles
|
||||
(GST_ENCODING_CONTAINER_PROFILE (prof)), i = 0; tmp;
|
||||
tmp = tmp->next, i++) {
|
||||
GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data;
|
||||
|
||||
if (!serialize_stream_profiles (out, sprof, profname, i))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
g_free (profgroupname);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
serialize_target (GKeyFile * out, GstEncodingTarget * target)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
g_key_file_set_string (out, GST_ENCODING_TARGET_HEADER, "name", target->name);
|
||||
g_key_file_set_string (out, GST_ENCODING_TARGET_HEADER, "category",
|
||||
target->category);
|
||||
g_key_file_set_string (out, GST_ENCODING_TARGET_HEADER, "description",
|
||||
target->description);
|
||||
|
||||
for (tmp = target->profiles; tmp; tmp = tmp->next) {
|
||||
GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data;
|
||||
if (!serialize_encoding_profile (out, prof))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_encoding_profile:
|
||||
* @in: a #GKeyFile
|
||||
* @parentprofilename: the parent profile name (including 'profile-' or 'streamprofile-' header)
|
||||
* @profilename: the profile name group to parse
|
||||
* @nbgroups: the number of top-level groups
|
||||
* @groups: the top-level groups
|
||||
*/
|
||||
static GstEncodingProfile *
|
||||
parse_encoding_profile (GKeyFile * in, gchar * parentprofilename,
|
||||
gchar * profilename, gsize nbgroups, gchar ** groups)
|
||||
{
|
||||
GstEncodingProfile *sprof = NULL;
|
||||
gchar **parent;
|
||||
gchar *proftype, *format, *preset, *restriction, *pname, *description;
|
||||
GstCaps *formatcaps = NULL;
|
||||
GstCaps *restrictioncaps = NULL;
|
||||
gboolean variableframerate;
|
||||
gint pass, presence;
|
||||
gsize i, nbencprofiles;
|
||||
|
||||
GST_DEBUG ("parentprofilename : %s , profilename : %s",
|
||||
parentprofilename, profilename);
|
||||
|
||||
if (parentprofilename) {
|
||||
gboolean found = FALSE;
|
||||
|
||||
parent =
|
||||
g_key_file_get_string_list (in, profilename, "parent",
|
||||
&nbencprofiles, NULL);
|
||||
if (!parent || !nbencprofiles) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if this streamprofile is used in <profilename> */
|
||||
for (i = 0; i < nbencprofiles; i++) {
|
||||
if (!g_strcmp0 (parent[i], parentprofilename)) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_strfreev (parent);
|
||||
|
||||
if (!found) {
|
||||
GST_DEBUG ("Stream profile '%s' isn't used in profile '%s'",
|
||||
profilename, parentprofilename);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pname = g_key_file_get_value (in, profilename, "name", NULL);
|
||||
|
||||
/* First try to get localized description */
|
||||
description =
|
||||
g_key_file_get_locale_string (in, profilename, "description",
|
||||
setlocale (LC_ALL, NULL), NULL);
|
||||
if (description == NULL)
|
||||
description = g_key_file_get_value (in, profilename, "description", NULL);
|
||||
|
||||
/* Parse the remaining fields */
|
||||
proftype = g_key_file_get_value (in, profilename, "type", NULL);
|
||||
if (!proftype) {
|
||||
GST_WARNING ("Missing 'type' field for streamprofile %s", profilename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
format = g_key_file_get_value (in, profilename, "format", NULL);
|
||||
if (format) {
|
||||
formatcaps = gst_caps_from_string (format);
|
||||
g_free (format);
|
||||
}
|
||||
|
||||
preset = g_key_file_get_value (in, profilename, "preset", NULL);
|
||||
|
||||
restriction = g_key_file_get_value (in, profilename, "restriction", NULL);
|
||||
if (restriction) {
|
||||
restrictioncaps = gst_caps_from_string (restriction);
|
||||
g_free (restriction);
|
||||
}
|
||||
|
||||
presence = g_key_file_get_integer (in, profilename, "presence", NULL);
|
||||
pass = g_key_file_get_integer (in, profilename, "pass", NULL);
|
||||
variableframerate =
|
||||
g_key_file_get_boolean (in, profilename, "variableframerate", NULL);
|
||||
|
||||
/* Build the streamprofile ! */
|
||||
if (!g_strcmp0 (proftype, "container")) {
|
||||
GstEncodingProfile *pprof;
|
||||
|
||||
sprof =
|
||||
(GstEncodingProfile *) gst_encoding_container_profile_new (pname,
|
||||
description, formatcaps, preset);
|
||||
/* Now look for the stream profiles */
|
||||
for (i = 0; i < nbgroups; i++) {
|
||||
if (!g_ascii_strncasecmp (groups[i], "streamprofile-", 13)) {
|
||||
pprof = parse_encoding_profile (in, pname, groups[i], nbgroups, groups);
|
||||
if (pprof) {
|
||||
gst_encoding_container_profile_add_profile (
|
||||
(GstEncodingContainerProfile *) sprof, pprof);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!g_strcmp0 (proftype, "video")) {
|
||||
sprof =
|
||||
(GstEncodingProfile *) gst_encoding_video_profile_new (formatcaps,
|
||||
preset, restrictioncaps, presence);
|
||||
gst_encoding_video_profile_set_variableframerate ((GstEncodingVideoProfile
|
||||
*) sprof, variableframerate);
|
||||
gst_encoding_video_profile_set_pass ((GstEncodingVideoProfile *) sprof,
|
||||
pass);
|
||||
} else if (!g_strcmp0 (proftype, "audio")) {
|
||||
sprof =
|
||||
(GstEncodingProfile *) gst_encoding_audio_profile_new (formatcaps,
|
||||
preset, restrictioncaps, presence);
|
||||
} else
|
||||
GST_ERROR ("Unknown profile format '%s'", proftype);
|
||||
|
||||
if (restrictioncaps)
|
||||
gst_caps_unref (restrictioncaps);
|
||||
if (formatcaps)
|
||||
gst_caps_unref (formatcaps);
|
||||
|
||||
if (pname)
|
||||
g_free (pname);
|
||||
if (description)
|
||||
g_free (description);
|
||||
if (preset)
|
||||
g_free (preset);
|
||||
if (proftype)
|
||||
g_free (proftype);
|
||||
|
||||
return sprof;
|
||||
}
|
||||
|
||||
static GstEncodingTarget *
|
||||
parse_keyfile (GKeyFile * in, gchar * targetname, gchar * categoryname,
|
||||
gchar * description)
|
||||
{
|
||||
GstEncodingTarget *res = NULL;
|
||||
GstEncodingProfile *prof;
|
||||
gchar **groups;
|
||||
gsize i, nbgroups;
|
||||
|
||||
res = gst_encoding_target_new (targetname, categoryname, description, NULL);
|
||||
|
||||
/* Figure out the various profiles */
|
||||
groups = g_key_file_get_groups (in, &nbgroups);
|
||||
for (i = 0; i < nbgroups; i++) {
|
||||
if (!g_ascii_strncasecmp (groups[i], "profile-", 8)) {
|
||||
prof = parse_encoding_profile (in, NULL, groups[i], nbgroups, groups);
|
||||
if (prof)
|
||||
gst_encoding_target_add_profile (res, prof);
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (groups);
|
||||
|
||||
if (targetname)
|
||||
g_free (targetname);
|
||||
if (categoryname)
|
||||
g_free (categoryname);
|
||||
if (description)
|
||||
g_free (description);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GKeyFile *
|
||||
load_file_and_read_header (const gchar * path, gchar ** targetname,
|
||||
gchar ** categoryname, gchar ** description, GError ** error)
|
||||
{
|
||||
GKeyFile *in;
|
||||
gboolean res;
|
||||
|
||||
in = g_key_file_new ();
|
||||
|
||||
GST_DEBUG ("path:%s", path);
|
||||
|
||||
res =
|
||||
g_key_file_load_from_file (in, path,
|
||||
G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, error);
|
||||
if (!res || error != NULL)
|
||||
goto load_error;
|
||||
|
||||
*targetname =
|
||||
g_key_file_get_value (in, GST_ENCODING_TARGET_HEADER, "name", error);
|
||||
if (!*targetname)
|
||||
goto empty_name;
|
||||
|
||||
*categoryname =
|
||||
g_key_file_get_value (in, GST_ENCODING_TARGET_HEADER, "category", NULL);
|
||||
*description =
|
||||
g_key_file_get_value (in, GST_ENCODING_TARGET_HEADER, "description",
|
||||
NULL);
|
||||
|
||||
return in;
|
||||
|
||||
load_error:
|
||||
{
|
||||
GST_WARNING ("Unable to read GstEncodingTarget file %s: %s",
|
||||
path, (*error)->message);
|
||||
g_key_file_free (in);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
empty_name:
|
||||
{
|
||||
GST_WARNING ("Wrong header in file %s: %s", path, (*error)->message);
|
||||
g_key_file_free (in);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_load_from:
|
||||
* @path: The file to load the #GstEncodingTarget from
|
||||
* @error: If an error occured, this field will be filled in.
|
||||
*
|
||||
* Opens the provided file and returns the contained #GstEncodingTarget.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The #GstEncodingTarget contained in the file, else %NULL
|
||||
*/
|
||||
|
||||
GstEncodingTarget *
|
||||
gst_encoding_target_load_from (const gchar * path, GError ** error)
|
||||
{
|
||||
GKeyFile *in;
|
||||
gchar *targetname, *categoryname, *description;
|
||||
GstEncodingTarget *res = NULL;
|
||||
|
||||
in = load_file_and_read_header (path, &targetname, &categoryname,
|
||||
&description, error);
|
||||
if (!in)
|
||||
goto beach;
|
||||
|
||||
res = parse_keyfile (in, targetname, categoryname, description);
|
||||
|
||||
g_key_file_free (in);
|
||||
|
||||
beach:
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_load:
|
||||
* @name: the name of the #GstEncodingTarget to load.
|
||||
* @error: If an error occured, this field will be filled in.
|
||||
*
|
||||
* Searches for the #GstEncodingTarget with the given name, loads it
|
||||
* and returns it.
|
||||
*
|
||||
* Warning: NOT IMPLEMENTED.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: The #GstEncodingTarget if available, else %NULL
|
||||
*/
|
||||
|
||||
GstEncodingTarget *
|
||||
gst_encoding_target_load (const gchar * name, GError ** error)
|
||||
{
|
||||
/* FIXME : IMPLEMENT */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_save:
|
||||
* @target: a #GstEncodingTarget
|
||||
* @error: If an error occured, this field will be filled in.
|
||||
*
|
||||
* Saves the @target to the default location.
|
||||
*
|
||||
* Warning: NOT IMPLEMENTED.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: %TRUE if the target was correctly saved, else %FALSE.
|
||||
**/
|
||||
|
||||
gboolean
|
||||
gst_encoding_target_save (GstEncodingTarget * target, GError ** error)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_ENCODING_TARGET (target), FALSE);
|
||||
|
||||
/* FIXME : IMPLEMENT */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_encoding_target_save_to:
|
||||
* @target: a #GstEncodingTarget
|
||||
* @path: the location to store the @target at.
|
||||
* @error: If an error occured, this field will be filled in.
|
||||
*
|
||||
* Saves the @target to the provided location.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*
|
||||
* Returns: %TRUE if the target was correctly saved, else %FALSE.
|
||||
**/
|
||||
|
||||
gboolean
|
||||
gst_encoding_target_save_to (GstEncodingTarget * target, const gchar * path,
|
||||
GError ** error)
|
||||
{
|
||||
GKeyFile *out;
|
||||
gchar *data;
|
||||
gsize data_size;
|
||||
|
||||
g_return_val_if_fail (GST_IS_ENCODING_TARGET (target), FALSE);
|
||||
g_return_val_if_fail (path != NULL, FALSE);
|
||||
|
||||
/* FIXME : Check path is valid and writable
|
||||
* FIXME : Strip out profiles already present in system target */
|
||||
|
||||
/* Get unique name... */
|
||||
|
||||
/* Create output GKeyFile */
|
||||
out = g_key_file_new ();
|
||||
|
||||
if (!serialize_target (out, target))
|
||||
goto serialize_failure;
|
||||
|
||||
if (!(data = g_key_file_to_data (out, &data_size, error)))
|
||||
goto convert_failed;
|
||||
|
||||
if (!g_file_set_contents (path, data, data_size, error))
|
||||
goto write_failed;
|
||||
|
||||
g_key_file_free (out);
|
||||
g_free (data);
|
||||
|
||||
return TRUE;
|
||||
|
||||
serialize_failure:
|
||||
{
|
||||
GST_ERROR ("Failure serializing target");
|
||||
g_key_file_free (out);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
convert_failed:
|
||||
{
|
||||
GST_ERROR ("Failure converting keyfile: %s", (*error)->message);
|
||||
g_key_file_free (out);
|
||||
g_free (data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
write_failed:
|
||||
{
|
||||
GST_ERROR ("Unable to write file %s: %s", path, (*error)->message);
|
||||
g_key_file_free (out);
|
||||
g_free (data);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
104
gst-libs/gst/pbutils/encoding-target.h
Normal file
104
gst-libs/gst/pbutils/encoding-target.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* GStreamer encoding profile registry
|
||||
* Copyright (C) 2010 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||
* (C) 2010 Nokia Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_PROFILE_REGISTRY_H__
|
||||
#define __GST_PROFILE_REGISTRY_H__
|
||||
|
||||
#include <gst/pbutils/encoding-profile.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
/* FIXME/UNKNOWNS
|
||||
*
|
||||
* Should encoding categories be well-known strings/quarks ?
|
||||
*
|
||||
*/
|
||||
|
||||
#define GST_ENCODING_CATEGORY_DEVICE "device"
|
||||
#define GST_ENCODING_CATEGORY_ONLINE_SERVICE "online-service"
|
||||
#define GST_ENCODING_CATEGORY_STORAGE_EDITING "storage-editing"
|
||||
#define GST_ENCODING_CATEGORY_CAPTURE "capture"
|
||||
|
||||
/**
|
||||
* GstEncodingTarget:
|
||||
*
|
||||
* Collection of #GstEncodingProfile for a specific target or use-case.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define GST_TYPE_ENCODING_TARGET \
|
||||
(gst_encoding_target_get_type ())
|
||||
#define GST_ENCODING_TARGET(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_TARGET, GstEncodingTarget))
|
||||
#define GST_IS_ENCODING_TARGET(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_TARGET))
|
||||
|
||||
typedef struct _GstEncodingTarget GstEncodingTarget;
|
||||
typedef GstMiniObjectClass GstEncodingTargetClass;
|
||||
|
||||
GType gst_encoding_target_get_type (void);
|
||||
|
||||
/**
|
||||
* gst_encoding_target_unref:
|
||||
* @target: a #GstEncodingTarget
|
||||
*
|
||||
* Decreases the reference count of the @target, possibly freeing it.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define gst_encoding_target_unref(target) \
|
||||
(gst_mini_object_unref ((GstMiniObject*) target))
|
||||
|
||||
/**
|
||||
* gst_encoding_target_ref:
|
||||
* @target: a #GstEncodingTarget
|
||||
*
|
||||
* Increases the reference count of the @target.
|
||||
*
|
||||
* Since: 0.10.32
|
||||
*/
|
||||
#define gst_encoding_target_ref(target) \
|
||||
(gst_mini_object_ref ((GstMiniObject*) target))
|
||||
|
||||
GstEncodingTarget *
|
||||
gst_encoding_target_new (const gchar *name, const gchar *category,
|
||||
const gchar *description, const GList *profiles);
|
||||
const gchar *gst_encoding_target_get_name (GstEncodingTarget *target);
|
||||
const gchar *gst_encoding_target_get_category (GstEncodingTarget *target);
|
||||
const gchar *gst_encoding_target_get_description (GstEncodingTarget *target);
|
||||
const GList *gst_encoding_target_get_profiles (GstEncodingTarget *target);
|
||||
|
||||
gboolean
|
||||
gst_encoding_target_add_profile (GstEncodingTarget *target, GstEncodingProfile *profile);
|
||||
|
||||
gboolean gst_encoding_target_save (GstEncodingTarget *target,
|
||||
GError **error);
|
||||
gboolean gst_encoding_target_save_to (GstEncodingTarget *target,
|
||||
const gchar *path,
|
||||
GError **error);
|
||||
GstEncodingTarget *gst_encoding_target_load (const gchar *name,
|
||||
GError **error);
|
||||
GstEncodingTarget *gst_encoding_target_load_from (const gchar *path,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_PROFILE_REGISTRY_H__ */
|
|
@ -127,6 +127,7 @@ check_PROGRAMS = \
|
|||
libs/navigation \
|
||||
libs/netbuffer \
|
||||
libs/pbutils \
|
||||
libs/profile \
|
||||
libs/rtp \
|
||||
libs/tag \
|
||||
libs/video \
|
||||
|
@ -238,6 +239,12 @@ libs_pbutils_LDADD = \
|
|||
$(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \
|
||||
$(GST_BASE_LIBS) $(LDADD)
|
||||
|
||||
libs_profile_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(AM_CFLAGS)
|
||||
libs_profile_LDADD = \
|
||||
$(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la $(LDADD)
|
||||
|
||||
elements_appsink_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(AM_CFLAGS)
|
||||
|
|
1
tests/check/libs/.gitignore
vendored
1
tests/check/libs/.gitignore
vendored
|
@ -6,6 +6,7 @@ mixer
|
|||
navigation
|
||||
netbuffer
|
||||
pbutils
|
||||
profile
|
||||
rtp
|
||||
tag
|
||||
utils
|
||||
|
|
454
tests/check/libs/profile.c
Normal file
454
tests/check/libs/profile.c
Normal file
|
@ -0,0 +1,454 @@
|
|||
/* GStreamer unit test for gstprofile
|
||||
*
|
||||
* Copyright (C) <2009> Edward Hervey <edward.hervey@collabora.co.uk>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* #include <fcntl.h> */
|
||||
#include <unistd.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
|
||||
#include <gst/pbutils/encoding-profile.h>
|
||||
#include <gst/pbutils/encoding-target.h>
|
||||
|
||||
#define CHECK_PROFILE(profile, name, description, format, preset, presence, restriction) \
|
||||
{ \
|
||||
fail_if(profile == NULL); \
|
||||
fail_unless_equals_string (gst_encoding_profile_get_name (profile), name); \
|
||||
fail_unless_equals_string (gst_encoding_profile_get_description (profile), description); \
|
||||
fail_unless (gst_caps_is_equal (gst_encoding_profile_get_format (profile), format)); \
|
||||
fail_unless_equals_string (gst_encoding_profile_get_preset (profile), preset); \
|
||||
fail_unless_equals_int (gst_encoding_profile_get_presence (profile), presence); \
|
||||
fail_unless (gst_caps_is_equal (gst_encoding_profile_get_restriction (profile), restriction)); \
|
||||
}
|
||||
|
||||
GST_START_TEST (test_profile_creation)
|
||||
{
|
||||
GstEncodingProfile *encprof;
|
||||
GstEncodingAudioProfile *audioprof;
|
||||
GstEncodingVideoProfile *videoprof;
|
||||
GstCaps *ogg, *vorbis, *theora;
|
||||
GstCaps *test1, *test2;
|
||||
|
||||
ogg = gst_caps_new_simple ("application/ogg", NULL);
|
||||
vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL);
|
||||
theora = gst_caps_new_simple ("video/x-theora", NULL);
|
||||
|
||||
encprof = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *)
|
||||
"ogg-theora-vorbis", "dumb-profile", ogg, (gchar *) "dumb-preset");
|
||||
CHECK_PROFILE (encprof, "ogg-theora-vorbis", "dumb-profile", ogg,
|
||||
"dumb-preset", 0, NULL);
|
||||
|
||||
audioprof = gst_encoding_audio_profile_new (vorbis, (gchar *) "HQ", NULL, 0);
|
||||
CHECK_PROFILE ((GstEncodingProfile *) audioprof, NULL, NULL, vorbis, "HQ", 0,
|
||||
NULL);
|
||||
|
||||
videoprof = gst_encoding_video_profile_new (theora, (gchar *) "HQ", NULL, 0);
|
||||
CHECK_PROFILE ((GstEncodingProfile *) videoprof, NULL, NULL, theora, "HQ",
|
||||
0, NULL);
|
||||
|
||||
fail_unless (gst_encoding_container_profile_add_profile (
|
||||
(GstEncodingContainerProfile *) encprof,
|
||||
(GstEncodingProfile *) audioprof));
|
||||
fail_unless (gst_encoding_container_profile_add_profile (
|
||||
(GstEncodingContainerProfile *) encprof,
|
||||
(GstEncodingProfile *) videoprof));
|
||||
|
||||
/* Test caps */
|
||||
test1 = gst_caps_from_string ("video/x-theora; audio/x-vorbis");
|
||||
test2 = gst_encoding_profile_get_output_caps (encprof);
|
||||
fail_unless (gst_caps_is_equal (test1, test2));
|
||||
gst_caps_unref (test1);
|
||||
gst_caps_unref (test2);
|
||||
|
||||
gst_encoding_profile_unref (encprof);
|
||||
gst_caps_unref (ogg);
|
||||
gst_caps_unref (theora);
|
||||
gst_caps_unref (vorbis);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (test_profile_output_caps)
|
||||
{
|
||||
GstEncodingProfile *sprof;
|
||||
GstCaps *vorbis;
|
||||
GstCaps *out, *restriction, *test1;
|
||||
|
||||
vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL);
|
||||
|
||||
/* Simple case, no restriction */
|
||||
sprof = (GstEncodingProfile *)
|
||||
gst_encoding_audio_profile_new (vorbis, NULL, NULL, 0);
|
||||
fail_if (sprof == NULL);
|
||||
|
||||
out = gst_encoding_profile_get_output_caps (sprof);
|
||||
fail_if (out == NULL);
|
||||
fail_unless (gst_caps_is_equal (out, vorbis));
|
||||
gst_caps_unref (out);
|
||||
gst_encoding_profile_unref (sprof);
|
||||
|
||||
/* One simple restriction */
|
||||
restriction = gst_caps_from_string ("audio/x-raw-int,channels=2,rate=44100");
|
||||
test1 = gst_caps_from_string ("audio/x-vorbis,channels=2,rate=44100");
|
||||
fail_if (restriction == NULL);
|
||||
|
||||
sprof = (GstEncodingProfile *)
|
||||
gst_encoding_audio_profile_new (vorbis, NULL, restriction, 0);
|
||||
fail_if (sprof == NULL);
|
||||
|
||||
out = gst_encoding_profile_get_output_caps (sprof);
|
||||
fail_if (out == NULL);
|
||||
GST_DEBUG ("got caps %" GST_PTR_FORMAT, out);
|
||||
fail_unless (gst_caps_is_equal (out, test1));
|
||||
gst_caps_unref (out);
|
||||
gst_caps_unref (restriction);
|
||||
gst_caps_unref (test1);
|
||||
gst_encoding_profile_unref (sprof);
|
||||
|
||||
gst_caps_unref (vorbis);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_containerless_profile)
|
||||
{
|
||||
GstEncodingProfile *encprof;
|
||||
GstEncodingAudioProfile *audioprof;
|
||||
GstCaps *container = NULL, *vorbis;
|
||||
GstCaps *test1, *test2;
|
||||
|
||||
vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL);
|
||||
|
||||
GST_DEBUG ("Creating container profile without any caps");
|
||||
encprof = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *)
|
||||
"container-vorbis", "dumb-profile", container, (gchar *) "dumb-preset");
|
||||
CHECK_PROFILE (encprof, "container-vorbis", "dumb-profile", NULL,
|
||||
"dumb-preset", 0, 0);
|
||||
|
||||
GST_DEBUG ("Creating audio profile");
|
||||
audioprof = gst_encoding_audio_profile_new (vorbis, (gchar *) "HQ", NULL, 0);
|
||||
CHECK_PROFILE ((GstEncodingProfile *) audioprof, NULL, NULL, vorbis, "HQ", 0,
|
||||
0);
|
||||
|
||||
GST_DEBUG ("Adding audio profile to container");
|
||||
/* We can add one stream profile to container-less profiles.. */
|
||||
fail_unless (gst_encoding_container_profile_add_profile (
|
||||
(GstEncodingContainerProfile *) encprof,
|
||||
(GstEncodingProfile *) audioprof));
|
||||
GST_DEBUG ("Adding audio profile to container a second time (should fail)");
|
||||
/* .. but not two */
|
||||
fail_if (gst_encoding_container_profile_add_profile (
|
||||
(GstEncodingContainerProfile *) encprof,
|
||||
(GstEncodingProfile *) audioprof));
|
||||
|
||||
GST_DEBUG ("Checking caps");
|
||||
/* Test caps */
|
||||
test1 = gst_caps_from_string ("audio/x-vorbis");
|
||||
test2 = gst_encoding_profile_get_output_caps (encprof);
|
||||
fail_unless (gst_caps_is_equal (test1, test2));
|
||||
gst_caps_unref (test1);
|
||||
gst_caps_unref (test2);
|
||||
|
||||
gst_encoding_profile_unref (encprof);
|
||||
gst_caps_unref (vorbis);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static GstEncodingTarget *
|
||||
create_saveload_target (void)
|
||||
{
|
||||
GstEncodingTarget *target;
|
||||
GstEncodingProfile *profile, *sprof;
|
||||
GstCaps *caps, *caps2;
|
||||
|
||||
GST_DEBUG ("Creating target");
|
||||
|
||||
target = gst_encoding_target_new ("myponytarget", "herding",
|
||||
"Plenty of pony glitter profiles", NULL);
|
||||
caps = gst_caps_from_string ("animal/x-pony");
|
||||
profile =
|
||||
(GstEncodingProfile *) gst_encoding_container_profile_new ("pony",
|
||||
"I don't want a description !", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
gst_encoding_target_add_profile (target, profile);
|
||||
|
||||
caps = gst_caps_from_string ("audio/x-pony-song,pretty=True");
|
||||
caps2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
|
||||
sprof =
|
||||
(GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL, caps2,
|
||||
1);
|
||||
gst_encoding_container_profile_add_profile ((GstEncodingContainerProfile *)
|
||||
profile, sprof);
|
||||
gst_caps_unref (caps);
|
||||
gst_caps_unref (caps2);
|
||||
|
||||
caps = gst_caps_from_string ("video/x-glitter,sparkling=True");
|
||||
caps2 =
|
||||
gst_caps_from_string
|
||||
("video/x-raw-yuv,width=640,height=480,framerate=15/1");
|
||||
sprof = (GstEncodingProfile *)
|
||||
gst_encoding_video_profile_new (caps, "seriously glittery", caps2, 0);
|
||||
gst_encoding_video_profile_set_variableframerate ((GstEncodingVideoProfile *)
|
||||
sprof, TRUE);
|
||||
gst_encoding_container_profile_add_profile ((GstEncodingContainerProfile *)
|
||||
profile, sprof);
|
||||
gst_caps_unref (caps);
|
||||
gst_caps_unref (caps2);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_saving_profile)
|
||||
{
|
||||
GstEncodingTarget *orig, *loaded = NULL;
|
||||
GstEncodingProfile *proforig, *profloaded;
|
||||
gchar *profile_file_name;
|
||||
|
||||
/* Create and store a target */
|
||||
profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10",
|
||||
"profile", "TestProfile2.profile", NULL);
|
||||
orig = create_saveload_target ();
|
||||
GST_DEBUG ("Saving target to '%s'", profile_file_name);
|
||||
fail_unless (gst_encoding_target_save_to (orig, profile_file_name, NULL));
|
||||
|
||||
/* Check we can load it */
|
||||
GST_DEBUG ("Loading target from '%s'", profile_file_name);
|
||||
loaded = gst_encoding_target_load_from (profile_file_name, NULL);
|
||||
fail_unless (loaded != NULL);
|
||||
g_free (profile_file_name);
|
||||
|
||||
GST_DEBUG ("Checking targets are equal");
|
||||
/* Check targets are identical */
|
||||
/* 1. at the target level */
|
||||
fail_unless_equals_string (gst_encoding_target_get_name (orig),
|
||||
gst_encoding_target_get_name (loaded));
|
||||
fail_unless_equals_string (gst_encoding_target_get_category (orig),
|
||||
gst_encoding_target_get_category (loaded));
|
||||
fail_unless_equals_string (gst_encoding_target_get_description (orig),
|
||||
gst_encoding_target_get_description (loaded));
|
||||
fail_unless_equals_int (g_list_length ((GList *)
|
||||
gst_encoding_target_get_profiles (loaded)), 1);
|
||||
|
||||
/* 2. at the profile level */
|
||||
profloaded =
|
||||
(GstEncodingProfile *) gst_encoding_target_get_profiles (loaded)->data;
|
||||
proforig =
|
||||
(GstEncodingProfile *) gst_encoding_target_get_profiles (orig)->data;
|
||||
|
||||
fail_unless_equals_int (G_TYPE_FROM_INSTANCE (profloaded),
|
||||
G_TYPE_FROM_INSTANCE (proforig));
|
||||
GST_DEBUG ("Comparing loaded:%p to original:%p", profloaded, proforig);
|
||||
fail_unless (gst_encoding_profile_is_equal (profloaded, proforig));
|
||||
|
||||
gst_encoding_target_unref (orig);
|
||||
gst_encoding_target_unref (loaded);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_loading_profile)
|
||||
{
|
||||
GstEncodingTarget *target;
|
||||
gchar *profile_file_name;
|
||||
GstEncodingProfile *prof;
|
||||
GstCaps *tmpcaps, *tmpcaps2;
|
||||
GstEncodingProfile *sprof1, *sprof2;
|
||||
|
||||
profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10",
|
||||
"profile", "TestProfile.profile", NULL);
|
||||
|
||||
GST_DEBUG ("Loading target from '%s'", profile_file_name);
|
||||
target = gst_encoding_target_load_from (profile_file_name, NULL);
|
||||
g_free (profile_file_name);
|
||||
fail_unless (target != NULL);
|
||||
|
||||
GST_DEBUG ("Checking the target properties");
|
||||
/* Check the target */
|
||||
fail_unless_equals_string (gst_encoding_target_get_name (target),
|
||||
"myponytarget");
|
||||
fail_unless_equals_string (gst_encoding_target_get_category (target),
|
||||
"herding");
|
||||
fail_unless_equals_string (gst_encoding_target_get_description (target),
|
||||
"Plenty of pony glitter profiles");
|
||||
|
||||
GST_DEBUG ("Checking the number of profiles the target contains");
|
||||
fail_unless_equals_int (g_list_length ((GList *)
|
||||
gst_encoding_target_get_profiles (target)), 1);
|
||||
|
||||
|
||||
GST_DEBUG ("Checking the container profile");
|
||||
/* Check the profile */
|
||||
prof = (GstEncodingProfile *) gst_encoding_target_get_profiles (target)->data;
|
||||
tmpcaps = gst_caps_from_string ("animal/x-pony");
|
||||
CHECK_PROFILE (prof, "pony", "I don't want a description !", tmpcaps, NULL, 0,
|
||||
0);
|
||||
gst_caps_unref (tmpcaps);
|
||||
|
||||
GST_DEBUG ("Checking the container profile has 2 stream profiles");
|
||||
/* Check the stream profiles */
|
||||
fail_unless_equals_int (g_list_length ((GList *)
|
||||
gst_encoding_container_profile_get_profiles (
|
||||
(GstEncodingContainerProfile *) prof)), 2);
|
||||
|
||||
GST_DEBUG ("Checking the container profile has the audio/x-pony-song stream");
|
||||
tmpcaps = gst_caps_from_string ("audio/x-pony-song,pretty=True");
|
||||
tmpcaps2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
|
||||
sprof1 =
|
||||
(GstEncodingProfile *) gst_encoding_audio_profile_new (tmpcaps, NULL,
|
||||
tmpcaps2, 1);
|
||||
fail_unless (gst_encoding_container_profile_contains_profile (
|
||||
(GstEncodingContainerProfile *) prof, sprof1));
|
||||
gst_encoding_profile_unref (sprof1);
|
||||
gst_caps_unref (tmpcaps);
|
||||
gst_caps_unref (tmpcaps2);
|
||||
|
||||
GST_DEBUG ("Checking the container profile has the video//x-glitter stream");
|
||||
tmpcaps = gst_caps_from_string ("video/x-glitter,sparkling=True");
|
||||
tmpcaps2 =
|
||||
gst_caps_from_string
|
||||
("video/x-raw-yuv,width=640,height=480,framerate=15/1");
|
||||
sprof2 = (GstEncodingProfile *)
|
||||
gst_encoding_video_profile_new (tmpcaps, "seriously glittery", tmpcaps2,
|
||||
0);
|
||||
gst_encoding_video_profile_set_variableframerate ((GstEncodingVideoProfile *)
|
||||
sprof2, TRUE);
|
||||
fail_unless (gst_encoding_container_profile_contains_profile (
|
||||
(GstEncodingContainerProfile *) prof, sprof2));
|
||||
gst_encoding_profile_unref (sprof2);
|
||||
gst_caps_unref (tmpcaps);
|
||||
gst_caps_unref (tmpcaps2);
|
||||
|
||||
gst_encoding_target_unref (target);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static const gchar *profile_string = "\
|
||||
[_gstencodingtarget_]\n\
|
||||
name=myponytarget\n\
|
||||
category=herding\n\
|
||||
description=Plenty of pony glitter profiles\n\
|
||||
\n\
|
||||
[profile-pony1]\n\
|
||||
name=pony\n\
|
||||
type=container\n\
|
||||
description=I don't want a description !\n\
|
||||
format=animal/x-pony\n\
|
||||
\n\
|
||||
[streamprofile-pony11]\n\
|
||||
parent=pony\n\
|
||||
type=audio\n\
|
||||
format=audio/x-pony-song,pretty=True\n\
|
||||
restriction=audio/x-raw-int,channels=1,rate=44100\n\
|
||||
presence=1\n\
|
||||
\n\
|
||||
[streamprofile-pony12]\n\
|
||||
parent=pony\n\
|
||||
type=video\n\
|
||||
preset=seriously glittery\n\
|
||||
format=video/x-glitter,sparkling=True\n\
|
||||
restriction=video/x-raw-yuv,width=640,height=480,framerate=15/1\n\
|
||||
presence=0\n\
|
||||
variableframerate=true\n\
|
||||
";
|
||||
|
||||
static void
|
||||
remove_profile_file (void)
|
||||
{
|
||||
gchar *profile_file_name;
|
||||
|
||||
profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10",
|
||||
"profile", "TestProfile.profile", NULL);
|
||||
g_unlink (profile_file_name);
|
||||
g_free (profile_file_name);
|
||||
profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10",
|
||||
"profile", "TestProfile2.profile", NULL);
|
||||
g_unlink (profile_file_name);
|
||||
g_free (profile_file_name);
|
||||
}
|
||||
|
||||
static void
|
||||
create_profile_file (void)
|
||||
{
|
||||
gchar *profile_file_name;
|
||||
gchar *profile_dir;
|
||||
GError *error = NULL;
|
||||
|
||||
profile_dir =
|
||||
g_build_filename (g_get_home_dir (), ".gstreamer-0.10", "profile", NULL);
|
||||
profile_file_name =
|
||||
g_build_filename (g_get_home_dir (), ".gstreamer-0.10", "profile",
|
||||
"TestProfile.profile", NULL);
|
||||
g_mkdir_with_parents (profile_dir, S_IRUSR | S_IWUSR | S_IXUSR);
|
||||
if (!g_file_set_contents (profile_file_name, profile_string,
|
||||
strlen (profile_string), &error))
|
||||
GST_WARNING ("Couldn't write contents to file : %s", error->message);
|
||||
g_free (profile_dir);
|
||||
g_free (profile_file_name);
|
||||
}
|
||||
|
||||
static void
|
||||
test_setup (void)
|
||||
{
|
||||
create_profile_file ();
|
||||
}
|
||||
|
||||
static void
|
||||
test_teardown (void)
|
||||
{
|
||||
remove_profile_file ();
|
||||
}
|
||||
|
||||
|
||||
static Suite *
|
||||
profile_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("profile support library");
|
||||
TCase *tc_chain = tcase_create ("general");
|
||||
gboolean can_write;
|
||||
gchar *gst_dir;
|
||||
|
||||
/* cehck if we can create profiles */
|
||||
gst_dir = g_build_filename (g_get_home_dir (), ".gstreamer-0.10", NULL);
|
||||
can_write = (g_access (gst_dir, R_OK | W_OK | X_OK) == 0);
|
||||
g_free (gst_dir);
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
|
||||
tcase_add_test (tc_chain, test_profile_creation);
|
||||
tcase_add_test (tc_chain, test_profile_output_caps);
|
||||
tcase_add_test (tc_chain, test_containerless_profile);
|
||||
if (can_write) {
|
||||
tcase_add_test (tc_chain, test_loading_profile);
|
||||
tcase_add_test (tc_chain, test_saving_profile);
|
||||
}
|
||||
|
||||
tcase_add_unchecked_fixture (tc_chain, test_setup, test_teardown);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (profile);
|
|
@ -58,6 +58,46 @@ EXPORTS
|
|||
gst_discoverer_video_info_get_width
|
||||
gst_discoverer_video_info_is_image
|
||||
gst_discoverer_video_info_is_interlaced
|
||||
gst_encoding_audio_profile_get_type
|
||||
gst_encoding_audio_profile_new
|
||||
gst_encoding_container_profile_add_profile
|
||||
gst_encoding_container_profile_contains_profile
|
||||
gst_encoding_container_profile_get_profiles
|
||||
gst_encoding_container_profile_get_type
|
||||
gst_encoding_container_profile_new
|
||||
gst_encoding_profile_get_description
|
||||
gst_encoding_profile_get_format
|
||||
gst_encoding_profile_get_name
|
||||
gst_encoding_profile_get_output_caps
|
||||
gst_encoding_profile_get_presence
|
||||
gst_encoding_profile_get_preset
|
||||
gst_encoding_profile_get_restriction
|
||||
gst_encoding_profile_get_type
|
||||
gst_encoding_profile_get_type_nick
|
||||
gst_encoding_profile_is_equal
|
||||
gst_encoding_profile_set_description
|
||||
gst_encoding_profile_set_format
|
||||
gst_encoding_profile_set_name
|
||||
gst_encoding_profile_set_presence
|
||||
gst_encoding_profile_set_preset
|
||||
gst_encoding_profile_set_restriction
|
||||
gst_encoding_target_add_profile
|
||||
gst_encoding_target_get_category
|
||||
gst_encoding_target_get_description
|
||||
gst_encoding_target_get_name
|
||||
gst_encoding_target_get_profiles
|
||||
gst_encoding_target_get_type
|
||||
gst_encoding_target_load
|
||||
gst_encoding_target_load_from
|
||||
gst_encoding_target_new
|
||||
gst_encoding_target_save
|
||||
gst_encoding_target_save_to
|
||||
gst_encoding_video_profile_get_pass
|
||||
gst_encoding_video_profile_get_type
|
||||
gst_encoding_video_profile_get_variableframerate
|
||||
gst_encoding_video_profile_new
|
||||
gst_encoding_video_profile_set_pass
|
||||
gst_encoding_video_profile_set_variableframerate
|
||||
gst_install_plugins_async
|
||||
gst_install_plugins_context_free
|
||||
gst_install_plugins_context_get_type
|
||||
|
|
Loading…
Reference in a new issue