I have a webcam that outputs raw MJPEG over HTTP, in fact not fully raw but as
a mime attachment like:
--Ba4oTvQMY8ew04N8dcnM
Content-Type: image/jpeg
<0xFFD8 JPEG frame>
--Ba4oTvQMY8ew04N8dcnM
Content-Type: image/jpeg
<0xFFD8 JPEG frame>
....
in order not to have to specify -f mjpeg, I added a probe function for it that detects either the JPEG header or the
mime type info as above
this also lets libav probe ordinary JPEG files for which is so far has relied on the file extension only. Similar probe
functions could be added for all the supported formats in imgdec2 too.
diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c
index 5e95d10..f085b45 100644
--- a/libavformat/rawdec.c
+++ b/libavformat/rawdec.c
@@ -27,11 +27,13 @@
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "libavutil/pixdesc.h"
+#include "libavutil/avstring.h"
#define RAW_PACKET_SIZE 1024
int ff_raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt)
{
+ FFRawVideoDemuxerContext *s1 = s->priv_data;
int ret, size;
size = RAW_PACKET_SIZE;
@@ -41,6 +43,9 @@ int ff_raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt)
pkt->pos= avio_tell(s->pb);
pkt->stream_index = 0;
+ if( s1->gen_ts )
+ pkt->pts = (av_gettime() - s1->starttime) / 1000;
+av_log(NULL, AV_LOG_ERROR, "pts %lld\n", pkt->pts);
ret = ffio_read_partial(s->pb, pkt->data, size);
if (ret < 0) {
av_free_packet(pkt);
@@ -92,6 +97,11 @@ int ff_raw_video_read_header(AVFormatContext *s)
goto fail;
}
+ if( s1->gen_ts ) {
+ framerate.den = 1;
+ framerate.num = 1000;
+ s1->starttime = av_gettime();
+ }
#if FF_API_R_FRAME_RATE
st->r_frame_rate =
#endif
@@ -108,6 +118,7 @@ fail:
#define DEC AV_OPT_FLAG_DECODING_PARAM
const AVOption ff_rawvideo_options[] = {
{ "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "25"}, 0, 0, DEC},
+ { "generate_timestamps", "", OFFSET(gen_ts), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
{ NULL },
};
@@ -124,7 +135,43 @@ AVInputFormat ff_latm_demuxer = {
#endif
#if CONFIG_MJPEG_DEMUXER
-FF_DEF_RAWVIDEO_DEMUXER(mjpeg, "raw MJPEG video", NULL, "mjpg,mjpeg", AV_CODEC_ID_MJPEG)
+
+static int mjpeg_probe(AVProbeData *p)
+{
+ int ofs = 0;
+ // possible attachment with mime type
+ if(!memcmp(p->buf , "--", 2) || !memcmp(p->buf , "\r\n--", 4)) {
+ if(av_strnstr(p->buf, "image/jpeg", p->buf_size )) {
+av_log(NULL, AV_LOG_ERROR, "mjpeg_probe MIME\n");
+ return AVPROBE_SCORE_MAX;
+ }
+ }
+ if( p->buf[ofs] == 0xFF && p->buf[ofs + 1] == 0xD8) {
+av_log(NULL, AV_LOG_ERROR, "mjpeg_probe FFD8\n");
+ return AVPROBE_SCORE_MAX;
+ }
+ return 0;
+}
+
+static const AVClass mjpeg_demuxer_class = {
+ .class_name = "mjpeg demuxer",
+ .item_name = av_default_item_name,
+ .option = ff_rawvideo_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_mjpeg_demuxer = {
+ .name = "mjpeg",
+ .long_name = NULL_IF_CONFIG_SMALL("raw MJPEG video"),
+ .read_header = ff_raw_video_read_header,
+ .read_packet = ff_raw_read_partial_packet,
+ .read_probe = mjpeg_probe,
+ .flags = AVFMT_GENERIC_INDEX,
+ .extensions = "mjpg,mjpeg",
+ .raw_codec_id = AV_CODEC_ID_MJPEG,
+ .priv_data_size = sizeof(FFRawVideoDemuxerContext),
+ .priv_class = &mjpeg_demuxer_class,
+};
#endif
#if CONFIG_MLP_DEMUXER
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel