gst_plugins_good/gst/qtmux/gstqtmuxmap.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* Quicktime muxer plugin for GStreamer
       
     2  * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
       
     3  * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.net>
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 /*
       
    21  * Unless otherwise indicated, Source Code is licensed under MIT license.
       
    22  * See further explanation attached in License Statement (distributed in the file
       
    23  * LICENSE).
       
    24  *
       
    25  * Permission is hereby granted, free of charge, to any person obtaining a copy of
       
    26  * this software and associated documentation files (the "Software"), to deal in
       
    27  * the Software without restriction, including without limitation the rights to
       
    28  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
       
    29  * of the Software, and to permit persons to whom the Software is furnished to do
       
    30  * so, subject to the following conditions:
       
    31  *
       
    32  * The above copyright notice and this permission notice shall be included in all
       
    33  * copies or substantial portions of the Software.
       
    34  *
       
    35  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    36  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    37  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       
    38  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    39  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    40  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
       
    41  * SOFTWARE.
       
    42  */
       
    43 
       
    44 #include "gstqtmuxmap.h"
       
    45 #include "fourcc.h"
       
    46 #include "ftypcc.h"
       
    47 
       
    48 /* static info related to various format */
       
    49 
       
    50 #define COMMON_VIDEO_CAPS \
       
    51   "width = (int) [ 16, 4096 ], " \
       
    52   "height = (int) [ 16, 4096 ], " \
       
    53   "framerate = (fraction) [ 0, MAX ]"
       
    54 
       
    55 #define COMMON_VIDEO_CAPS_NO_FRAMERATE \
       
    56   "width = (int) [ 16, 4096 ], " \
       
    57   "height = (int) [ 16, 4096 ] "
       
    58 
       
    59 #define H263_CAPS \
       
    60   "video/x-h263, " \
       
    61   COMMON_VIDEO_CAPS
       
    62 
       
    63 #define H264_CAPS \
       
    64   "video/x-h264, " \
       
    65   COMMON_VIDEO_CAPS
       
    66 
       
    67 #define MPEG4V_CAPS \
       
    68   "video/mpeg, " \
       
    69   "mpegversion = (int) 4, "\
       
    70   "systemstream = (boolean) false, " \
       
    71   COMMON_VIDEO_CAPS "; " \
       
    72   "video/x-divx, " \
       
    73   "divxversion = (int) 5, "\
       
    74   COMMON_VIDEO_CAPS
       
    75 
       
    76 #define COMMON_AUDIO_CAPS(c, r) \
       
    77   "channels = (int) [ 1, " G_STRINGIFY (c) " ], " \
       
    78   "rate = (int) [ 1, " G_STRINGIFY (r) " ]"
       
    79 
       
    80 #define PCM_CAPS \
       
    81   "audio/x-raw-int, " \
       
    82   "width = (int) 8, " \
       
    83   "depth = (int) 8, " \
       
    84   COMMON_AUDIO_CAPS (2, MAX) ", " \
       
    85   "signed = (boolean) { true, false }; " \
       
    86   "audio/x-raw-int, " \
       
    87   "width = (int) 16, " \
       
    88   "depth = (int) 16, " \
       
    89   "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
       
    90   COMMON_AUDIO_CAPS (2, MAX) ", " \
       
    91   "signed = (boolean) true " \
       
    92 
       
    93 #define PCM_CAPS_FULL \
       
    94   PCM_CAPS "; " \
       
    95   "audio/x-raw-int, " \
       
    96   "width = (int) 24, " \
       
    97   "depth = (int) 24, " \
       
    98   "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
       
    99   COMMON_AUDIO_CAPS (2, MAX) ", " \
       
   100   "signed = (boolean) true; " \
       
   101   "audio/x-raw-int, " \
       
   102   "width = (int) 32, " \
       
   103   "depth = (int) 32, " \
       
   104   "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
       
   105   COMMON_AUDIO_CAPS (2, MAX) ", " \
       
   106   "signed = (boolean) true "
       
   107 
       
   108 #define MP3_CAPS \
       
   109   "audio/mpeg, " \
       
   110   "mpegversion = (int) 1, " \
       
   111   "layer = (int) 3, " \
       
   112   COMMON_AUDIO_CAPS (2, MAX)
       
   113 
       
   114 #define AAC_CAPS \
       
   115   "audio/mpeg, " \
       
   116   "mpegversion = (int) 4, " \
       
   117   COMMON_AUDIO_CAPS (8, MAX)
       
   118 
       
   119 #define AMR_CAPS \
       
   120   "audio/AMR, " \
       
   121   "rate = (int) 8000, " \
       
   122   "channels = [ 1, 2 ]; " \
       
   123   "audio/AMR-WB, " \
       
   124   "rate = (int) 16000, " \
       
   125   "channels = [ 1, 2 ] "
       
   126 
       
   127 /* FIXME 0.11 - take a look at bugs #580005 and #340375 */
       
   128 GstQTMuxFormatProp gst_qt_mux_format_list[] = {
       
   129   /* original QuickTime format; see Apple site (e.g. qtff.pdf) */
       
   130   {
       
   131         GST_QT_MUX_FORMAT_QT,
       
   132         "qtmux",
       
   133         "QuickTime",
       
   134         "GstQTMux",
       
   135         GST_STATIC_CAPS ("video/quicktime, variant = (string) apple"),
       
   136         GST_STATIC_CAPS ("video/x-raw-rgb, "
       
   137             COMMON_VIDEO_CAPS "; "
       
   138             "video/x-raw-yuv, "
       
   139             "format = (fourcc) UYVY, "
       
   140             COMMON_VIDEO_CAPS "; "
       
   141             MPEG4V_CAPS "; "
       
   142             H263_CAPS "; "
       
   143             H264_CAPS "; "
       
   144             "video/x-dv, "
       
   145             "systemstream = (boolean) false, "
       
   146             COMMON_VIDEO_CAPS "; "
       
   147             "image/jpeg, "
       
   148             COMMON_VIDEO_CAPS_NO_FRAMERATE "; "
       
   149             "video/x-qt-part, " COMMON_VIDEO_CAPS),
       
   150         GST_STATIC_CAPS (PCM_CAPS_FULL "; "
       
   151             MP3_CAPS " ; "
       
   152             AAC_CAPS " ; "
       
   153             "audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; " AMR_CAPS)
       
   154       }
       
   155   ,
       
   156   /* ISO 14496-14: mp42 as ISO base media extension
       
   157    * (supersedes original ISO 144996-1 mp41) */
       
   158   {
       
   159         GST_QT_MUX_FORMAT_MP4,
       
   160         "mp4mux",
       
   161         "MP4",
       
   162         "GstMP4Mux",
       
   163         GST_STATIC_CAPS ("video/quicktime, variant = (string) iso"),
       
   164         GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS ";"
       
   165             "video/x-mp4-part," COMMON_VIDEO_CAPS),
       
   166         GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS)
       
   167       }
       
   168   ,
       
   169   /* 3GPP Technical Specification 26.244 V7.3.0
       
   170    * (extended in 3GPP2 File Formats for Multimedia Services) */
       
   171   {
       
   172         GST_QT_MUX_FORMAT_3GP,
       
   173         "gppmux",
       
   174         "3GPP",
       
   175         "GstGPPMux",
       
   176         GST_STATIC_CAPS ("video/quicktime, variant = (string) 3gpp"),
       
   177         GST_STATIC_CAPS (H263_CAPS "; " MPEG4V_CAPS "; " H264_CAPS),
       
   178         GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS)
       
   179       }
       
   180   ,
       
   181   /* ISO 15444-3: Motion-JPEG-2000 (also ISO base media extension) */
       
   182   {
       
   183         GST_QT_MUX_FORMAT_MJ2,
       
   184         "mj2mux",
       
   185         "MJ2",
       
   186         "GstMJ2Mux",
       
   187         GST_STATIC_CAPS ("video/mj2"),
       
   188         GST_STATIC_CAPS ("image/x-j2c, " COMMON_VIDEO_CAPS),
       
   189         GST_STATIC_CAPS (PCM_CAPS)
       
   190       }
       
   191   ,
       
   192   {
       
   193         GST_QT_MUX_FORMAT_NONE,
       
   194       }
       
   195   ,
       
   196 };
       
   197 
       
   198 /* pretty static, but may turn out needed a few times */
       
   199 AtomsTreeFlavor
       
   200 gst_qt_mux_map_format_to_flavor (GstQTMuxFormat format)
       
   201 {
       
   202   if (format == GST_QT_MUX_FORMAT_QT)
       
   203     return ATOMS_TREE_FLAVOR_MOV;
       
   204   else if (format == GST_QT_MUX_FORMAT_3GP)
       
   205     return ATOMS_TREE_FLAVOR_3GP;
       
   206   else
       
   207     return ATOMS_TREE_FLAVOR_ISOM;
       
   208 }
       
   209 
       
   210 static void
       
   211 gst_qt_mux_map_check_tracks (AtomMOOV * moov, gint * _video, gint * _audio,
       
   212     gboolean * _has_h264)
       
   213 {
       
   214   GList *it;
       
   215   gint video = 0, audio = 0;
       
   216   gboolean has_h264 = FALSE;
       
   217 
       
   218   for (it = moov->traks; it != NULL; it = g_list_next (it)) {
       
   219     AtomTRAK *track = it->data;
       
   220 
       
   221     if (track->is_video) {
       
   222       video++;
       
   223       if (track->is_h264)
       
   224         has_h264 = TRUE;
       
   225     } else
       
   226       audio++;
       
   227   }
       
   228 
       
   229   if (_video)
       
   230     *_video = video;
       
   231   if (_audio)
       
   232     *_audio = audio;
       
   233   if (_has_h264)
       
   234     *_has_h264 = has_h264;
       
   235 }
       
   236 
       
   237 /* pretty static, but possibly dynamic format info */
       
   238 
       
   239 /* notes:
       
   240  * - avc1 brand is not used, since the specific extensions indicated by it
       
   241  *   are not used (e.g. sample groupings, etc)
       
   242  * - TODO: maybe even more 3GPP brand fine-tuning ??
       
   243  *   (but that might need ftyp rewriting at the end) */
       
   244 void
       
   245 gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
       
   246     guint32 * _major, guint32 * _version, GList ** _compatible, AtomMOOV * moov,
       
   247     GstClockTime longest_chunk, gboolean faststart)
       
   248 {
       
   249   static guint32 qt_brands[] = { 0 };
       
   250   static guint32 mp4_brands[] = { FOURCC_mp41, FOURCC_isom, FOURCC_iso2, 0 };
       
   251   static guint32 gpp_brands[] = { FOURCC_isom, FOURCC_iso2, 0 };
       
   252   static guint32 mjp2_brands[] = { FOURCC_isom, FOURCC_iso2, 0 };
       
   253   static guint8 mjp2_prefix[] =
       
   254       { 0, 0, 0, 12, 'j', 'P', ' ', ' ', 0x0D, 0x0A, 0x87, 0x0A };
       
   255   guint32 *comp = NULL;
       
   256   guint32 major = 0, version = 0;
       
   257   GstBuffer *prefix = NULL;
       
   258   GList *result = NULL;
       
   259 
       
   260   g_return_if_fail (_prefix != NULL);
       
   261   g_return_if_fail (_major != NULL);
       
   262   g_return_if_fail (_version != NULL);
       
   263   g_return_if_fail (_compatible != NULL);
       
   264 
       
   265   switch (format) {
       
   266     case GST_QT_MUX_FORMAT_QT:
       
   267       major = FOURCC_qt__;
       
   268       comp = qt_brands;
       
   269       version = 0x20050300;
       
   270       break;
       
   271     case GST_QT_MUX_FORMAT_MP4:
       
   272       major = FOURCC_mp42;
       
   273       comp = mp4_brands;
       
   274       break;
       
   275     case GST_QT_MUX_FORMAT_3GP:
       
   276     {
       
   277       gint video, audio;
       
   278       gboolean has_h264;
       
   279 
       
   280       gst_qt_mux_map_check_tracks (moov, &video, &audio, &has_h264);
       
   281       /* only track restriction really matters for Basic Profile */
       
   282       if (video <= 1 && audio <= 1) {
       
   283         /* it seems only newer spec knows about H264 */
       
   284         major = has_h264 ? FOURCC_3gp6 : FOURCC_3gp4;
       
   285         version = has_h264 ? 0x100 : 0x200;
       
   286       } else {
       
   287         major = FOURCC_3gg6;
       
   288         version = 0x100;
       
   289       }
       
   290       comp = gpp_brands;
       
   291 
       
   292       /*
       
   293        * We assume that we have chunks in dts order
       
   294        */
       
   295       if (faststart && longest_chunk <= GST_SECOND) {
       
   296         /* add progressive download profile */
       
   297         result = g_list_append (result, GUINT_TO_POINTER (FOURCC_3gr6));
       
   298       }
       
   299       break;
       
   300     }
       
   301     case GST_QT_MUX_FORMAT_MJ2:
       
   302       major = FOURCC_mjp2;
       
   303       comp = mjp2_brands;
       
   304       version = 0;
       
   305       prefix = gst_buffer_new_and_alloc (sizeof (mjp2_prefix));
       
   306       memcpy (GST_BUFFER_DATA (prefix), mjp2_prefix, GST_BUFFER_SIZE (prefix));
       
   307       break;
       
   308     default:
       
   309       g_assert_not_reached ();
       
   310       break;
       
   311   }
       
   312 
       
   313   /* convert list to list, hm */
       
   314   while (comp && *comp != 0) {
       
   315     /* order matters over efficiency */
       
   316     result = g_list_append (result, GUINT_TO_POINTER (*comp));
       
   317     comp++;
       
   318   }
       
   319 
       
   320   *_major = major;
       
   321   *_version = version;
       
   322   *_prefix = prefix;
       
   323   *_compatible = result;
       
   324 
       
   325   /* TODO 3GPP may include mp42 as compatible if applicable */
       
   326   /* TODO 3GPP major brand 3gp7 if at most 1 video and audio track */
       
   327 }