#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");
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");
DECL_STR(_codec_audio_amr, "amr");
DECL_STR(_codec_audio_amr_wb, "amr-wb");
-#undef DECL_STR
struct type_str {
uint8_t type;
"Andre Moreira Magalhaes",
"Lucas De Marchi",
"Gustavo Sverzut Barbieri",
+ "Leandro Dorileo",
NULL
};
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;
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)
{
}
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);
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);
}
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;
}
"MP4 files (MP4, M4A, MOV, QT, 3GP)",
PV,
_authors,
- "http://lms.garage.maemo.org"
+ "http://github.com/profusion/lightmediascanner"
};
return &info;