locked
Why Mosaic Effect happens when playing MPEG-1 file with Windows Media Player RRS feed

  • Question

  • Hi, I am writing a program to convert video files into MPEG-1 format. You see, there are a set of parameters to define the converting process, like frame rate, bit rate, etc. For MPEG-1 format, only 23.976, 24, 25, 29.97, 30, 59.94, 60 fps(frame per second) are available.
    To test the converted MPEG-1 file, I first use Windows Media Player (9.0)  to play the converted file. I found that the MPEG-1 files with frame rate other than 60fps are played well. But when playing the MPEG-1 files with frame rate of 60fps, mosaic effect appears apparently. Then I played these converted files by other decoders which are
    Moonlight-Elecard MPEG2 Video Decoder, Nero Video Decoder, Libavcodec, and Libmpeg2. With these decoders, the MPEG-1 files with frame rate of 60fps play well with no mosaic effect at all.

    I have also tried other encoder software (Panasonic MPEG-1 Encoder) to generate MPEG-1 files. Results are the same: by
    Windows Media Player, mosaic effect happens only if playing 60 fps MPEG-1 files; other frame rates are OK. And by other video decoders listed above, all frame rates (include 60fps) are OK with no mosaic effect at all.

    I use DirectShow to find the decoder used by Windows Media Player, that is Microsoft MPEG1 Video Decoder 2.0. And I found that decoder depends on quartz.dll.

    In addition, I convert the file format into MPEG-1 by ffmpeg, the source code is listed below.

    int PPMtoMPEG1(const char *input_file, 
                    const char *output_file,
                    unsigned int width /* = 0 */, 
                    unsigned int height /* = 0 */, 
                    unsigned int bit_rate /* = 12000 */,
                    int overwrite /* = 1 */,
                    void *para /* = NULL */)
    {
        const int max_int_oct_bits = 20;

        int argc = 14;

        if (width > 0 && height > 0) {        // '-s size' option is needed
            argc += 2;
        }

        if (overwrite) {                    // '-y' option is needed
            ++ argc;
        }

        // We need an additional argument, see below.
        char **argv = new char *[argc + 1];

        // see whether output file exists.
        FILE *fp = fopen(output_file, "rb");
        if (NULL != fp) {
            if (!overwrite) {        // file exists but we are not allowed to overwrite it
                sprintf(error_message, "Output file '%s' already exists\n", output_file);
                return 1;
            }
            fclose(fp);
        }

        int opt_index = 0;

        // dumb argument
        argv[opt_index ++] = "ffmpeg";

        // '-r fps'            set frame rate (default = 25)
        argv[opt_index ++] = "-r";

        char opt_fps[11];
        sprintf(opt_fps, "%d/%d", frame_rate_tab[frame_rate_index], MPEG1_FRAME_RATE_BASE);
        argv[opt_index ++] = opt_fps;

        // '-i filename'    input file name
        argv[opt_index ++] = "-i";

        char *input = new char[strlen(input_file) + 1];
        strcpy(input, input_file);
        argv[opt_index ++] = input;

        // '-s size'         set frame size (WxH)
        if (width > 0 && height > 0) {
            argv[opt_index ++] = "-s";

            char opt_size[max_int_oct_bits * 2 + 1];
            sprintf(opt_size, "%dx%d", width, height);
            argv[opt_index ++] = opt_size;
        }

        // '-b bitrate'     set video bitrate (in kbit/s)
        argv[opt_index ++] = "-b";

        char opt_bitrate[max_int_oct_bits + 1];
        sprintf(opt_bitrate, "%d", bit_rate);
        argv[opt_index ++] = opt_bitrate;

        // '-y'             overwrite output file
        if (overwrite) {
            argv[opt_index ++] = "-y";
        }

        // '-qscale q'         use fixed video quantiser scale (VBR), always 1 to indicate the excellent quality
        argv[opt_index ++] = "-qscale";
        argv[opt_index ++] = "1";

        // '-vcodec codec'     force video codec to mpeg1video.
        argv[opt_index ++] = "-vcodec";
        argv[opt_index ++] = "mpeg1video";

        // '-r fps'            set frame rate (default = 25)
        argv[opt_index ++] = "-r";
        argv[opt_index ++] = opt_fps;

        // output file name
        char *output = new char[strlen(output_file) + 1];
        strcpy(output, output_file);
        argv[opt_index ++] = output;

        // the standard requires that argv[argc] be a null pointer    - from K&R. Section.5.10.
        argv[opt_index] = NULL;

        FFMPEG_PROGRESS_CALLBACK cb = NULL;
        if (progress_callback) {
            cb = ToMPEG1CallBack;
        }

        int ret = ffmpegmain(argc, argv, error_message, cb, para);

        delete []output;
        delete []input;
        delete []argv;

        return ret;
    }

    Because the users of my program will play the converted MPEG-1 files by
    Windows Media Player, I have to make sure why mosaic effect happens: is it because Windows Media Player could not play 60fps MPEG-1 files? Or is it because of codes errors? Could you help me? Thanks a lot.

    Tuesday, December 4, 2007 8:54 AM

Answers