serdec.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * SER demuxer
  3. * Copyright (c) 2018 Paul B Mahol
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "libavutil/imgutils.h"
  22. #include "libavutil/parseutils.h"
  23. #include "libavutil/pixdesc.h"
  24. #include "libavutil/opt.h"
  25. #include "internal.h"
  26. #include "avformat.h"
  27. #define SER_MAGIC "LUCAM-RECORDER"
  28. typedef struct SERDemuxerContext {
  29. const AVClass *class;
  30. int width, height;
  31. AVRational framerate;
  32. int64_t end;
  33. } SERDemuxerContext;
  34. static int ser_probe(const AVProbeData *pd)
  35. {
  36. if (memcmp(pd->buf, SER_MAGIC, 14) == 0)
  37. return AVPROBE_SCORE_MAX;
  38. else
  39. return 0;
  40. }
  41. static int ser_read_header(AVFormatContext *s)
  42. {
  43. SERDemuxerContext *ser = s->priv_data;
  44. enum AVPixelFormat pix_fmt;
  45. int depth, color_id, endian;
  46. int packet_size;
  47. AVStream *st;
  48. st = avformat_new_stream(s, NULL);
  49. if (!st)
  50. return AVERROR(ENOMEM);
  51. avio_skip(s->pb, 14);
  52. avio_skip(s->pb, 4);
  53. color_id = avio_rl32(s->pb);
  54. endian = avio_rl32(s->pb);
  55. ser->width = avio_rl32(s->pb);
  56. ser->height = avio_rl32(s->pb);
  57. depth = avio_rl32(s->pb);
  58. st->nb_frames = st->duration = avio_rl32(s->pb);
  59. avio_skip(s->pb, 120);
  60. avio_skip(s->pb, 8);
  61. avio_skip(s->pb, 8);
  62. switch (color_id) {
  63. case 0: pix_fmt = depth <= 8 ? AV_PIX_FMT_GRAY8 : endian ? AV_PIX_FMT_GRAY16BE : AV_PIX_FMT_GRAY16LE; break;
  64. case 8: pix_fmt = depth <= 8 ? AV_PIX_FMT_BAYER_RGGB8 : endian ? AV_PIX_FMT_BAYER_RGGB16BE : AV_PIX_FMT_BAYER_RGGB16LE; break;
  65. case 9: pix_fmt = depth <= 8 ? AV_PIX_FMT_BAYER_GRBG8 : endian ? AV_PIX_FMT_BAYER_GRBG16BE : AV_PIX_FMT_BAYER_GRBG16LE; break;
  66. case 10: pix_fmt = depth <= 8 ? AV_PIX_FMT_BAYER_GBRG8 : endian ? AV_PIX_FMT_BAYER_GBRG16BE : AV_PIX_FMT_BAYER_GBRG16LE; break;
  67. case 11: pix_fmt = depth <= 8 ? AV_PIX_FMT_BAYER_BGGR8 : endian ? AV_PIX_FMT_BAYER_BGGR16BE : AV_PIX_FMT_BAYER_BGGR16LE; break;
  68. case 100: pix_fmt = depth <= 8 ? AV_PIX_FMT_RGB24 : endian ? AV_PIX_FMT_RGB48BE : AV_PIX_FMT_RGB48LE; break;
  69. case 101: pix_fmt = depth <= 8 ? AV_PIX_FMT_BGR24 : endian ? AV_PIX_FMT_BGR48BE : AV_PIX_FMT_BGR48LE; break;
  70. default:
  71. return AVERROR_PATCHWELCOME;
  72. }
  73. st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  74. st->codecpar->codec_id = s->iformat->raw_codec_id;
  75. avpriv_set_pts_info(st, 64, ser->framerate.den, ser->framerate.num);
  76. st->codecpar->width = ser->width;
  77. st->codecpar->height = ser->height;
  78. st->codecpar->format = pix_fmt;
  79. packet_size = av_image_get_buffer_size(st->codecpar->format, ser->width, ser->height, 1);
  80. if (packet_size < 0)
  81. return packet_size;
  82. ser->end = 178 + st->nb_frames * packet_size;
  83. s->packet_size = packet_size;
  84. st->codecpar->bit_rate = av_rescale_q(s->packet_size,
  85. (AVRational){8,1}, st->time_base);
  86. return 0;
  87. }
  88. static int ser_read_packet(AVFormatContext *s, AVPacket *pkt)
  89. {
  90. SERDemuxerContext *ser = s->priv_data;
  91. int64_t pos;
  92. int ret;
  93. pos = avio_tell(s->pb);
  94. if (pos >= ser->end)
  95. return AVERROR_EOF;
  96. ret = av_get_packet(s->pb, pkt, s->packet_size);
  97. pkt->pts = pkt->dts = (pkt->pos - ffformatcontext(s)->data_offset) / s->packet_size;
  98. pkt->stream_index = 0;
  99. if (ret < 0)
  100. return ret;
  101. return 0;
  102. }
  103. #define OFFSET(x) offsetof(SERDemuxerContext, x)
  104. #define DEC AV_OPT_FLAG_DECODING_PARAM
  105. static const AVOption ser_options[] = {
  106. { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC },
  107. { NULL },
  108. };
  109. static const AVClass ser_demuxer_class = {
  110. .class_name = "ser demuxer",
  111. .item_name = av_default_item_name,
  112. .option = ser_options,
  113. .version = LIBAVUTIL_VERSION_INT,
  114. };
  115. const AVInputFormat ff_ser_demuxer = {
  116. .name = "ser",
  117. .long_name = NULL_IF_CONFIG_SMALL("SER (Simple uncompressed video format for astronomical capturing)"),
  118. .priv_data_size = sizeof(SERDemuxerContext),
  119. .read_probe = ser_probe,
  120. .read_header = ser_read_header,
  121. .read_packet = ser_read_packet,
  122. .flags = AVFMT_GENERIC_INDEX,
  123. .extensions = "ser",
  124. .raw_codec_id = AV_CODEC_ID_RAWVIDEO,
  125. .priv_class = &ser_demuxer_class,
  126. };