Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * YUV4MPEG muxer
  3.  * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
  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.  
  22. #include "libavutil/pixdesc.h"
  23. #include "avformat.h"
  24. #include "internal.h"
  25. #include "yuv4mpeg.h"
  26.  
  27. #define Y4M_LINE_MAX 256
  28.  
  29. static int yuv4_generate_header(AVFormatContext *s, char* buf)
  30. {
  31.     AVStream *st;
  32.     int width, height;
  33.     int raten, rated, aspectn, aspectd, n;
  34.     char inter;
  35.     const char *colorspace = "";
  36.  
  37.     st     = s->streams[0];
  38.     width  = st->codec->width;
  39.     height = st->codec->height;
  40.  
  41.     // TODO: should be avg_frame_rate
  42.     av_reduce(&raten, &rated, st->time_base.den,
  43.               st->time_base.num, (1UL << 31) - 1);
  44.  
  45.     aspectn = st->sample_aspect_ratio.num;
  46.     aspectd = st->sample_aspect_ratio.den;
  47.  
  48.     if (aspectn == 0 && aspectd == 1)
  49.         aspectd = 0;  // 0:0 means unknown
  50.  
  51.     switch (st->codec->field_order) {
  52.     case AV_FIELD_TB:
  53.     case AV_FIELD_TT: inter = 't'; break;
  54.     case AV_FIELD_BT:
  55.     case AV_FIELD_BB: inter = 'b'; break;
  56.     default:          inter = 'p'; break;
  57.     }
  58.  
  59.     switch (st->codec->pix_fmt) {
  60.     case AV_PIX_FMT_GRAY8:
  61.         colorspace = " Cmono";
  62.         break;
  63.     case AV_PIX_FMT_GRAY16:
  64.         colorspace = " Cmono16";
  65.         break;
  66.     case AV_PIX_FMT_YUV411P:
  67.         colorspace = " C411 XYSCSS=411";
  68.         break;
  69.     case AV_PIX_FMT_YUV420P:
  70.         switch (st->codec->chroma_sample_location) {
  71.         case AVCHROMA_LOC_TOPLEFT: colorspace = " C420paldv XYSCSS=420PALDV"; break;
  72.         case AVCHROMA_LOC_LEFT:    colorspace = " C420mpeg2 XYSCSS=420MPEG2"; break;
  73.         default:                   colorspace = " C420jpeg XYSCSS=420JPEG";   break;
  74.         }
  75.         break;
  76.     case AV_PIX_FMT_YUV422P:
  77.         colorspace = " C422 XYSCSS=422";
  78.         break;
  79.     case AV_PIX_FMT_YUV444P:
  80.         colorspace = " C444 XYSCSS=444";
  81.         break;
  82.     case AV_PIX_FMT_YUV420P9:
  83.         colorspace = " C420p9 XYSCSS=420P9";
  84.         break;
  85.     case AV_PIX_FMT_YUV422P9:
  86.         colorspace = " C422p9 XYSCSS=422P9";
  87.         break;
  88.     case AV_PIX_FMT_YUV444P9:
  89.         colorspace = " C444p9 XYSCSS=444P9";
  90.         break;
  91.     case AV_PIX_FMT_YUV420P10:
  92.         colorspace = " C420p10 XYSCSS=420P10";
  93.         break;
  94.     case AV_PIX_FMT_YUV422P10:
  95.         colorspace = " C422p10 XYSCSS=422P10";
  96.         break;
  97.     case AV_PIX_FMT_YUV444P10:
  98.         colorspace = " C444p10 XYSCSS=444P10";
  99.         break;
  100.     case AV_PIX_FMT_YUV420P12:
  101.         colorspace = " C420p12 XYSCSS=420P12";
  102.         break;
  103.     case AV_PIX_FMT_YUV422P12:
  104.         colorspace = " C422p12 XYSCSS=422P12";
  105.         break;
  106.     case AV_PIX_FMT_YUV444P12:
  107.         colorspace = " C444p12 XYSCSS=444P12";
  108.         break;
  109.     case AV_PIX_FMT_YUV420P14:
  110.         colorspace = " C420p14 XYSCSS=420P14";
  111.         break;
  112.     case AV_PIX_FMT_YUV422P14:
  113.         colorspace = " C422p14 XYSCSS=422P14";
  114.         break;
  115.     case AV_PIX_FMT_YUV444P14:
  116.         colorspace = " C444p14 XYSCSS=444P14";
  117.         break;
  118.     case AV_PIX_FMT_YUV420P16:
  119.         colorspace = " C420p16 XYSCSS=420P16";
  120.         break;
  121.     case AV_PIX_FMT_YUV422P16:
  122.         colorspace = " C422p16 XYSCSS=422P16";
  123.         break;
  124.     case AV_PIX_FMT_YUV444P16:
  125.         colorspace = " C444p16 XYSCSS=444P16";
  126.         break;
  127.     }
  128.  
  129.     /* construct stream header, if this is the first frame */
  130.     n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n",
  131.                  Y4M_MAGIC, width, height, raten, rated, inter,
  132.                  aspectn, aspectd, colorspace);
  133.  
  134.     return n;
  135. }
  136.  
  137. static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
  138. {
  139.     AVStream *st = s->streams[pkt->stream_index];
  140.     AVIOContext *pb = s->pb;
  141.     AVPicture *picture, picture_tmp;
  142.     int* first_pkt = s->priv_data;
  143.     int width, height, h_chroma_shift, v_chroma_shift;
  144.     int i;
  145.     char buf2[Y4M_LINE_MAX + 1];
  146.     uint8_t *ptr, *ptr1, *ptr2;
  147.  
  148.     memcpy(&picture_tmp, pkt->data, sizeof(AVPicture));
  149.     picture = &picture_tmp;
  150.  
  151.     /* for the first packet we have to output the header as well */
  152.     if (*first_pkt) {
  153.         *first_pkt = 0;
  154.         if (yuv4_generate_header(s, buf2) < 0) {
  155.             av_log(s, AV_LOG_ERROR,
  156.                    "Error. YUV4MPEG stream header write failed.\n");
  157.             return AVERROR(EIO);
  158.         } else {
  159.             avio_write(pb, buf2, strlen(buf2));
  160.         }
  161.     }
  162.  
  163.     /* construct frame header */
  164.  
  165.     avio_printf(s->pb, "%s\n", Y4M_FRAME_MAGIC);
  166.  
  167.     width  = st->codec->width;
  168.     height = st->codec->height;
  169.  
  170.     ptr = picture->data[0];
  171.  
  172.     switch (st->codec->pix_fmt) {
  173.     case AV_PIX_FMT_GRAY8:
  174.     case AV_PIX_FMT_YUV411P:
  175.     case AV_PIX_FMT_YUV420P:
  176.     case AV_PIX_FMT_YUV422P:
  177.     case AV_PIX_FMT_YUV444P:
  178.         break;
  179.     case AV_PIX_FMT_GRAY16:
  180.     case AV_PIX_FMT_YUV420P9:
  181.     case AV_PIX_FMT_YUV422P9:
  182.     case AV_PIX_FMT_YUV444P9:
  183.     case AV_PIX_FMT_YUV420P10:
  184.     case AV_PIX_FMT_YUV422P10:
  185.     case AV_PIX_FMT_YUV444P10:
  186.     case AV_PIX_FMT_YUV420P12:
  187.     case AV_PIX_FMT_YUV422P12:
  188.     case AV_PIX_FMT_YUV444P12:
  189.     case AV_PIX_FMT_YUV420P14:
  190.     case AV_PIX_FMT_YUV422P14:
  191.     case AV_PIX_FMT_YUV444P14:
  192.     case AV_PIX_FMT_YUV420P16:
  193.     case AV_PIX_FMT_YUV422P16:
  194.     case AV_PIX_FMT_YUV444P16:
  195.         width *= 2;
  196.         break;
  197.     default:
  198.         av_log(s, AV_LOG_ERROR, "The pixel format '%s' is not supported.\n",
  199.                av_get_pix_fmt_name(st->codec->pix_fmt));
  200.         return AVERROR(EINVAL);
  201.     }
  202.  
  203.     for (i = 0; i < height; i++) {
  204.         avio_write(pb, ptr, width);
  205.         ptr += picture->linesize[0];
  206.     }
  207.  
  208.     if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8 &&
  209.         st->codec->pix_fmt != AV_PIX_FMT_GRAY16) {
  210.         // Adjust for smaller Cb and Cr planes
  211.         av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift,
  212.                                          &v_chroma_shift);
  213.         width  = FF_CEIL_RSHIFT(width,  h_chroma_shift);
  214.         height = FF_CEIL_RSHIFT(height, v_chroma_shift);
  215.  
  216.         ptr1 = picture->data[1];
  217.         ptr2 = picture->data[2];
  218.         for (i = 0; i < height; i++) {     /* Cb */
  219.             avio_write(pb, ptr1, width);
  220.             ptr1 += picture->linesize[1];
  221.         }
  222.         for (i = 0; i < height; i++) {     /* Cr */
  223.             avio_write(pb, ptr2, width);
  224.             ptr2 += picture->linesize[2];
  225.         }
  226.     }
  227.  
  228.     return 0;
  229. }
  230.  
  231. static int yuv4_write_header(AVFormatContext *s)
  232. {
  233.     int *first_pkt = s->priv_data;
  234.  
  235.     if (s->nb_streams != 1)
  236.         return AVERROR(EIO);
  237.  
  238.     if (s->streams[0]->codec->codec_id != AV_CODEC_ID_RAWVIDEO) {
  239.         av_log(s, AV_LOG_ERROR, "ERROR: Only rawvideo supported.\n");
  240.         return AVERROR_INVALIDDATA;
  241.     }
  242.  
  243.     switch (s->streams[0]->codec->pix_fmt) {
  244.     case AV_PIX_FMT_YUV411P:
  245.         av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "
  246.                "stream, some mjpegtools might not work.\n");
  247.         break;
  248.     case AV_PIX_FMT_GRAY8:
  249.     case AV_PIX_FMT_GRAY16:
  250.     case AV_PIX_FMT_YUV420P:
  251.     case AV_PIX_FMT_YUV422P:
  252.     case AV_PIX_FMT_YUV444P:
  253.         break;
  254.     case AV_PIX_FMT_YUV420P9:
  255.     case AV_PIX_FMT_YUV422P9:
  256.     case AV_PIX_FMT_YUV444P9:
  257.     case AV_PIX_FMT_YUV420P10:
  258.     case AV_PIX_FMT_YUV422P10:
  259.     case AV_PIX_FMT_YUV444P10:
  260.     case AV_PIX_FMT_YUV420P12:
  261.     case AV_PIX_FMT_YUV422P12:
  262.     case AV_PIX_FMT_YUV444P12:
  263.     case AV_PIX_FMT_YUV420P14:
  264.     case AV_PIX_FMT_YUV422P14:
  265.     case AV_PIX_FMT_YUV444P14:
  266.     case AV_PIX_FMT_YUV420P16:
  267.     case AV_PIX_FMT_YUV422P16:
  268.     case AV_PIX_FMT_YUV444P16:
  269.         if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
  270.             av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. "
  271.                    "Use '-strict -1' to encode to this pixel format.\n",
  272.                    av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt));
  273.             return AVERROR(EINVAL);
  274.         }
  275.         av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. "
  276.                "Mjpegtools will not work.\n");
  277.         break;
  278.     default:
  279.         av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle "
  280.                "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. "
  281.                "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, "
  282.                "yuv444p10, yuv422p10, yuv420p10, "
  283.                "yuv444p12, yuv422p12, yuv420p12, "
  284.                "yuv444p14, yuv422p14, yuv420p14, "
  285.                "yuv444p16, yuv422p16, yuv420p16 "
  286.                "and gray16 pixel formats. "
  287.                "Use -pix_fmt to select one.\n");
  288.         return AVERROR(EIO);
  289.     }
  290.  
  291.     *first_pkt = 1;
  292.     return 0;
  293. }
  294.  
  295. AVOutputFormat ff_yuv4mpegpipe_muxer = {
  296.     .name              = "yuv4mpegpipe",
  297.     .long_name         = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
  298.     .extensions        = "y4m",
  299.     .priv_data_size    = sizeof(int),
  300.     .audio_codec       = AV_CODEC_ID_NONE,
  301.     .video_codec       = AV_CODEC_ID_RAWVIDEO,
  302.     .write_header      = yuv4_write_header,
  303.     .write_packet      = yuv4_write_packet,
  304.     .flags             = AVFMT_RAWPICTURE,
  305. };
  306.