~ubuntu-branches/ubuntu/oneiric/mplayer2/oneiric-proposed

« back to all changes in this revision

Viewing changes to mplayer/libvo/vo_yuv4mpeg.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2011-03-20 22:48:03 UTC
  • Revision ID: james.westby@ubuntu.com-20110320224803-kc2nlrxz6pcphmf1
Tags: upstream-2.0~rc2
ImportĀ upstreamĀ versionĀ 2.0~rc2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * yuv4mpeg (mjpegtools) interface
 
3
 *
 
4
 * Thrown together by Robert Kesterson <robertk@robertk.com>
 
5
 * Based on the pgm output plugin, the rgb2rgb postproc filter, divxdec,
 
6
 * and probably others.
 
7
 *
 
8
 * This is undoubtedly incomplete, inaccurate, or just plain wrong. :-)
 
9
 *
 
10
 * 2002/06/19 Klaus Stengel <Klaus.Stengel@asamnet.de>
 
11
 *            - added support for interlaced output
 
12
 *              Activate by using '-vo yuv4mpeg:interlaced'
 
13
 *              or '-vo yuv4mpeg:interlaced_bf' if your source has
 
14
 *              bottom fields first
 
15
 *            - added some additional checks to catch problems
 
16
 *
 
17
 * 2002/04/17 Juergen Hammelmann <juergen.hammelmann@gmx.de>
 
18
 *            - added support for output of subtitles
 
19
 *              best, if you give option '-osdlevel 0' to mplayer for
 
20
 *              no watching the seek+timer
 
21
 *
 
22
 * This file is part of MPlayer.
 
23
 *
 
24
 * MPlayer is free software; you can redistribute it and/or modify
 
25
 * it under the terms of the GNU General Public License as published by
 
26
 * the Free Software Foundation; either version 2 of the License, or
 
27
 * (at your option) any later version.
 
28
 *
 
29
 * MPlayer is distributed in the hope that it will be useful,
 
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
32
 * GNU General Public License for more details.
 
33
 *
 
34
 * You should have received a copy of the GNU General Public License along
 
35
 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
 
36
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
37
 */
 
38
 
 
39
#include <stdio.h>
 
40
#include <stdlib.h>
 
41
#include <string.h>
 
42
#include <unistd.h>
 
43
#include <errno.h>
 
44
#include <fcntl.h>
 
45
#include <limits.h>
 
46
 
 
47
#include "config.h"
 
48
#include "subopt-helper.h"
 
49
#include "video_out.h"
 
50
#include "video_out_internal.h"
 
51
 
 
52
#include "mp_msg.h"
 
53
 
 
54
#include "sub/sub.h"
 
55
 
 
56
#include "fastmemcpy.h"
 
57
#include "libavutil/rational.h"
 
58
 
 
59
static const vo_info_t info =
 
60
{
 
61
        "yuv4mpeg output for mjpegtools",
 
62
        "yuv4mpeg",
 
63
        "Robert Kesterson <robertk@robertk.com>",
 
64
        ""
 
65
};
 
66
 
 
67
const LIBVO_EXTERN (yuv4mpeg)
 
68
 
 
69
static int image_width = 0;
 
70
static int image_height = 0;
 
71
static float image_fps = 0;
 
72
 
 
73
static uint8_t *image = NULL;
 
74
static uint8_t *image_y = NULL;
 
75
static uint8_t *image_u = NULL;
 
76
static uint8_t *image_v = NULL;
 
77
 
 
78
static char *yuv_filename = NULL;
 
79
 
 
80
static int using_format = 0;
 
81
static FILE *yuv_out;
 
82
static int write_bytes;
 
83
 
 
84
#define Y4M_ILACE_NONE         'p'  /* non-interlaced, progressive frame */
 
85
#define Y4M_ILACE_TOP_FIRST    't'  /* interlaced, top-field first       */
 
86
#define Y4M_ILACE_BOTTOM_FIRST 'b'  /* interlaced, bottom-field first    */
 
87
 
 
88
/* Set progressive mode as default */
 
89
static int config_interlace = Y4M_ILACE_NONE;
 
90
#define Y4M_IS_INTERLACED (config_interlace != Y4M_ILACE_NONE)
 
91
 
 
92
static int config(uint32_t width, uint32_t height, uint32_t d_width,
 
93
       uint32_t d_height, uint32_t flags, char *title,
 
94
       uint32_t format)
 
95
{
 
96
        AVRational pixelaspect = av_div_q((AVRational){d_width, d_height},
 
97
                                          (AVRational){width, height});
 
98
        AVRational fps_frac = av_d2q(vo_fps, vo_fps * 1001 + 2);
 
99
        if (image_width == width && image_height == height &&
 
100
             image_fps == vo_fps && vo_config_count)
 
101
          return 0;
 
102
        if (vo_config_count) {
 
103
          mp_msg(MSGT_VO, MSGL_WARN,
 
104
            "Video formats differ (w:%i=>%i, h:%i=>%i, fps:%f=>%f), "
 
105
            "restarting output.\n",
 
106
            image_width, width, image_height, height, image_fps, vo_fps);
 
107
          uninit();
 
108
        }
 
109
        image_height = height;
 
110
        image_width = width;
 
111
        image_fps = vo_fps;
 
112
        using_format = format;
 
113
 
 
114
        if (Y4M_IS_INTERLACED)
 
115
        {
 
116
                if (height % 4)
 
117
                {
 
118
                        mp_tmsg(MSGT_VO,MSGL_FATAL,
 
119
                                "Interlaced mode requires image height to be divisible by 4.");
 
120
                        return -1;
 
121
                }
 
122
        }
 
123
 
 
124
        if (width % 2)
 
125
        {
 
126
                mp_tmsg(MSGT_VO,MSGL_FATAL,
 
127
                        "Image width must be divisible by 2.");
 
128
                return -1;
 
129
        }
 
130
 
 
131
        write_bytes = image_width * image_height * 3 / 2;
 
132
        image = malloc(write_bytes);
 
133
 
 
134
        yuv_out = fopen(yuv_filename, "wb");
 
135
        if (!yuv_out || image == 0)
 
136
        {
 
137
                mp_tmsg(MSGT_VO,MSGL_FATAL,
 
138
                        "Can't get memory or file handle to write \"%s\"!",
 
139
                        yuv_filename);
 
140
                return -1;
 
141
        }
 
142
        image_y = image;
 
143
        image_u = image_y + image_width * image_height;
 
144
        image_v = image_u + image_width * image_height / 4;
 
145
 
 
146
        fprintf(yuv_out, "YUV4MPEG2 W%d H%d F%d:%d I%c A%d:%d\n",
 
147
                        image_width, image_height, fps_frac.num, fps_frac.den,
 
148
                        config_interlace,
 
149
                        pixelaspect.num, pixelaspect.den);
 
150
 
 
151
        fflush(yuv_out);
 
152
        return 0;
 
153
}
 
154
 
 
155
static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
 
156
                       unsigned char *srca, int stride) {
 
157
                vo_draw_alpha_yv12(w, h, src, srca, stride,
 
158
                                       image + y0 * image_width + x0, image_width);
 
159
}
 
160
 
 
161
static void draw_osd(void)
 
162
{
 
163
    vo_draw_text(image_width, image_height, draw_alpha);
 
164
}
 
165
 
 
166
static void vo_y4m_write(const void *ptr, const size_t num_bytes)
 
167
{
 
168
        if (fwrite(ptr, 1, num_bytes, yuv_out) != num_bytes)
 
169
                mp_tmsg(MSGT_VO,MSGL_ERR,
 
170
                        "Error writing image to output!");
 
171
}
 
172
 
 
173
static int write_last_frame(void)
 
174
{
 
175
    fprintf(yuv_out, "FRAME\n");
 
176
 
 
177
    vo_y4m_write(image, write_bytes);
 
178
    return VO_TRUE;
 
179
}
 
180
 
 
181
static void flip_page (void)
 
182
{
 
183
        fprintf(yuv_out, "FRAME\n");
 
184
 
 
185
        vo_y4m_write(image, write_bytes);
 
186
}
 
187
 
 
188
static int draw_slice(uint8_t *srcimg[], int stride[], int w,int h,int x,int y)
 
189
{
 
190
        int i;
 
191
        uint8_t *dst, *src = srcimg[0];
 
192
 
 
193
                // copy Y:
 
194
                dst = image_y + image_width * y + x;
 
195
                for (i = 0; i < h; i++)
 
196
                {
 
197
                        fast_memcpy(dst, src, w);
 
198
                        src += stride[0];
 
199
                        dst += image_width;
 
200
                }
 
201
                {
 
202
                        // copy U + V:
 
203
                        int imgstride = image_width >> 1;
 
204
                        uint8_t *src1 = srcimg[1];
 
205
                        uint8_t *src2 = srcimg[2];
 
206
                        uint8_t *dstu = image_u + imgstride * (y >> 1) + (x >> 1);
 
207
                        uint8_t *dstv = image_v + imgstride * (y >> 1) + (x >> 1);
 
208
                        for (i = 0; i < h / 2; i++)
 
209
                        {
 
210
                                fast_memcpy(dstu, src1 , w >> 1);
 
211
                                fast_memcpy(dstv, src2, w >> 1);
 
212
                                src1 += stride[1];
 
213
                                src2 += stride[2];
 
214
                                dstu += imgstride;
 
215
                                dstv += imgstride;
 
216
                        }
 
217
                }
 
218
        return 0;
 
219
}
 
220
 
 
221
static int draw_frame(uint8_t * src[])
 
222
{
 
223
                        // gets done in draw_slice
 
224
    return 0;
 
225
}
 
226
 
 
227
static int query_format(uint32_t format)
 
228
{
 
229
        if (format == IMGFMT_YV12)
 
230
                return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW|VFCAP_OSD|VFCAP_ACCEPT_STRIDE;
 
231
        return 0;
 
232
}
 
233
 
 
234
// WARNING: config(...) also uses this
 
235
static void uninit(void)
 
236
{
 
237
        free(image);
 
238
        image = NULL;
 
239
 
 
240
        if(yuv_out)
 
241
                fclose(yuv_out);
 
242
        yuv_out = NULL;
 
243
 
 
244
        free(yuv_filename);
 
245
        yuv_filename = NULL;
 
246
        image_width = 0;
 
247
        image_height = 0;
 
248
        image_fps = 0;
 
249
}
 
250
 
 
251
 
 
252
static void check_events(void)
 
253
{
 
254
}
 
255
 
 
256
static int preinit(const char *arg)
 
257
{
 
258
  int il, il_bf;
 
259
  const opt_t subopts[] = {
 
260
    {"interlaced",    OPT_ARG_BOOL, &il,    NULL},
 
261
    {"interlaced_bf", OPT_ARG_BOOL, &il_bf, NULL},
 
262
    {"file",          OPT_ARG_MSTRZ,  &yuv_filename,  NULL},
 
263
    {NULL}
 
264
  };
 
265
 
 
266
  il = 0;
 
267
  il_bf = 0;
 
268
  yuv_filename = strdup("stream.yuv");
 
269
  if (subopt_parse(arg, subopts) != 0) {
 
270
    mp_tmsg(MSGT_VO, MSGL_FATAL, "Unknown subdevice: %s", arg);
 
271
    return -1;
 
272
  }
 
273
 
 
274
  config_interlace = Y4M_ILACE_NONE;
 
275
  if (il)
 
276
    config_interlace = Y4M_ILACE_TOP_FIRST;
 
277
  if (il_bf)
 
278
    config_interlace = Y4M_ILACE_BOTTOM_FIRST;
 
279
 
 
280
    /* Inform user which output mode is used */
 
281
    switch (config_interlace)
 
282
    {
 
283
        case Y4M_ILACE_TOP_FIRST:
 
284
            mp_tmsg(MSGT_VO,MSGL_STATUS,
 
285
                    "Using interlaced output mode, top-field first.");
 
286
            break;
 
287
        case Y4M_ILACE_BOTTOM_FIRST:
 
288
            mp_tmsg(MSGT_VO,MSGL_STATUS,
 
289
                    "Using interlaced output mode, bottom-field first.");
 
290
            break;
 
291
        default:
 
292
            mp_tmsg(MSGT_VO,MSGL_STATUS,
 
293
                    "Using (default) progressive frame mode.");
 
294
            break;
 
295
    }
 
296
    return 0;
 
297
}
 
298
 
 
299
static int control(uint32_t request, void *data)
 
300
{
 
301
  switch (request) {
 
302
  case VOCTRL_QUERY_FORMAT:
 
303
    return query_format(*((uint32_t*)data));
 
304
  case VOCTRL_DUPLICATE_FRAME:
 
305
    return write_last_frame();
 
306
  }
 
307
  return VO_NOTIMPL;
 
308
}