mp4: change codec identifier mpeg1audio to mpeg4aac-lc
[platform/upstream/lightmediascanner.git] / src / plugins / mp4 / mp4.c
index d287fe5..311b792 100644 (file)
@@ -52,7 +52,8 @@ struct plugin {
 #define DECL_STR(cname, str)                                            \
     static const struct lms_string_size cname = LMS_STATIC_STRING_SIZE(str)
 
-DECL_STR(_container, "mp4");
+DECL_STR(_container_mp4, "mp4");
+DECL_STR(_container_3gp, "3gp");
 
 DECL_STR(_codec_audio_mpeg4aac_main, "mpeg4aac-main");
 DECL_STR(_codec_audio_mpeg4aac_lc, "mpeg4aac-lc");
@@ -93,7 +94,7 @@ DECL_STR(_codec_audio_mpeg2aac_main, "mpeg2aac-main");
 DECL_STR(_codec_audio_mpeg2aac_lc, "mpeg2aac-lc");
 DECL_STR(_codec_audio_mpeg2aac_ssr, "mpeg2aac-ssr");
 DECL_STR(_codec_audio_mpeg2audio, "mpeg2audio");
-DECL_STR(_codec_audio_mpeg1audio, "mpeg1audio");
+DECL_STR(_codec_audio_mpeg1audio, "mpeg4aac-lc");
 DECL_STR(_codec_audio_pcm16le, "pcm16le");
 DECL_STR(_codec_audio_vorbis, "vorbis");
 DECL_STR(_codec_audio_alaw, "alaw");
@@ -174,7 +175,6 @@ DECL_STR(_codec_video_h261, "h261");
 
 DECL_STR(_codec_audio_amr, "amr");
 DECL_STR(_codec_audio_amr_wb, "amr-wb");
-#undef DECL_STR
 
 struct type_str {
     uint8_t type;
@@ -334,6 +334,7 @@ static const char *_authors[] = {
     "Andre Moreira Magalhaes",
     "Lucas De Marchi",
     "Gustavo Sverzut Barbieri",
+    "Leandro Dorileo",
     NULL
 };
 
@@ -455,7 +456,51 @@ _get_video_codec(MP4FileHandle mp4_fh, MP4TrackId id)
             snprintf(str_level, sizeof(str_level), "%u.%u", level / 10,
                      level % 10);
 
-        ret.len = snprintf(buf, sizeof(buf), "h264-%s-%s",
+        /* fix constrained and 1b case for baseline and main */
+        if (profile == 66 || profile == 77) {
+            uint8_t *sps;
+            uint32_t spslen;
+            bool constrained = false;
+            bool level1b = false;
+
+            if (MP4HaveAtom(mp4_fh,
+                            "moov.trak.mdia.minf.stbl.stsd.avc1.avcC") &&
+                MP4GetBytesProperty(mp4_fh, "moov.trak.mdia.minf.stbl.stsd."
+                                    "avc1.avcC.sequenceEntries."
+                                    "sequenceParameterSetNALUnit",
+                                    &sps, &spslen)) {
+                /* SPS (Sequence Parameter Set) is:
+                 *  8 bits (1 byte) for profile_idc
+                 *  1 bit for constraint_set0_flag
+                 *  1 bit for constraint_set1_flag <- we use this for constr.
+                 *  1 bit for constraint_set2_flag
+                 *  1 bit for constraint_set3_flag <- we use this for 1b
+                 * based on ffmpeg's (libavcodec/h264_ps.c) and
+                 * x264 (encoder/set.c)
+                 */
+                if (spslen > 1) {
+                    if ((sps[1] >> 1) & 0x1)
+                        constrained = true;
+                    if (((sps[1] >> 3) & 0x1) && level / 10 == 1)
+                        level1b = true;
+                }
+                free(sps);
+
+                if (constrained) {
+                    if (profile == 66)
+                        memcpy(str_profile, "constrained-baseline",
+                               sizeof("constrained-baseline"));
+                    else
+                        memcpy(str_profile, "constrained-main",
+                               sizeof("constrained-main"));
+                }
+
+                if (level1b)
+                    memcpy(str_level, "1b", sizeof("1b"));
+            }
+        }
+
+        ret.len = snprintf(buf, sizeof(buf), "h264-p%s-l%s",
                            str_profile, str_level);
         ret.str = buf;
         goto found;
@@ -498,6 +543,30 @@ _get_lang(MP4FileHandle mp4_fh, MP4TrackId id)
     return ret;
 }
 
+static struct lms_string_size
+_get_container(MP4FileHandle mp4_fh)
+{
+    const char *brand;
+
+    if (!MP4GetStringProperty(mp4_fh, "ftyp.majorBrand", &brand))
+        return _container_mp4;
+
+    if (strncasecmp(brand, "3gp", 3) == 0)
+        return _container_3gp;
+
+    /* NOTE: this should be an array, but the C wrapper of mp4v2
+     * doesn't expose a way to give the index number and
+     * ftyp.compatibleBrands is not in counted format (name[idx])
+     */
+    if (!MP4GetStringProperty(mp4_fh, "ftyp.compatibleBrands", &brand))
+        return _container_mp4;
+
+    if (strncasecmp(brand, "3gp", 3) == 0)
+        return _container_3gp;
+
+    return _container_mp4;
+}
+
 static int
 _parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match)
 {
@@ -588,7 +657,6 @@ _parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_in
         }
         video_info.length = info.length;
     }
-#undef STR_FIELD_FROM_TAG
 
     lms_string_size_strip_and_free(&info.title);
     lms_string_size_strip_and_free(&info.artist);
@@ -614,14 +682,16 @@ _parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_in
         audio_info.artist = info.artist;
         audio_info.album = info.album;
         audio_info.genre = info.genre;
-        audio_info.container = _container;
+        audio_info.container = _get_container(mp4_fh);
         audio_info.trackno = info.trackno;
+
         r = lms_db_audio_add(plugin->audio_db, &audio_info);
     } else {
         video_info.id = finfo->id;
         video_info.title = info.title;
         video_info.artist = info.artist;
-        video_info.container = _container;
+        video_info.container = _get_container(mp4_fh);
+
         r = lms_db_video_add(plugin->video_db, &video_info);
     }
 
@@ -702,6 +772,7 @@ lms_plugin_open(void)
     plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup;
     plugin->plugin.start = (lms_plugin_start_fn_t)_start;
     plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish;
+    plugin->plugin.order = 0;
 
     return (struct lms_plugin *)plugin;
 }
@@ -715,7 +786,7 @@ lms_plugin_info(void)
         "MP4 files (MP4, M4A, MOV, QT, 3GP)",
         PV,
         _authors,
-        "http://lms.garage.maemo.org"
+        "http://github.com/profusion/lightmediascanner"
     };
 
     return &info;