Пример #1
0
    def image_sequence_encode(self, codec_name):

        try:
            codec = Codec(codec_name, 'w')
        except UnknownCodecError:
            raise SkipTest()

        container = av.open(fate_suite('h264/interlaced_crop.mp4'))
        video_stream = container.streams.video[0]

        width = 640
        height = 480

        ctx = codec.create()

        pix_fmt = ctx.codec.video_formats[0].name

        ctx.width = width
        ctx.height = height
        ctx.time_base = video_stream.codec_context.time_base
        ctx.pix_fmt = pix_fmt
        ctx.open()

        frame_count = 1
        path_list = []
        for frame in iter_frames(container, video_stream):

            new_frame = frame.reformat(width, height, pix_fmt)
            new_packets = ctx.encode(new_frame)

            self.assertEqual(len(new_packets), 1)
            new_packet = new_packets[0]

            path = self.sandboxed('%s/encoder.%04d.%s' % (
                codec_name,
                frame_count,
                codec_name if codec_name != 'mjpeg' else 'jpg',
            ))
            path_list.append(path)
            with open(path, 'wb') as f:
                f.write(new_packet)
            frame_count += 1
            if frame_count > 5:
                break

        ctx = av.Codec(codec_name, 'r').create()

        for path in path_list:
            with open(path, 'rb') as f:
                size = os.fstat(f.fileno()).st_size
                packet = Packet(size)
                size = f.readinto(packet)
                frame = ctx.decode(packet)[0]
                self.assertEqual(frame.width, width)
                self.assertEqual(frame.height, height)
                self.assertEqual(frame.format.name, pix_fmt)
Пример #2
0
    def image_sequence_encode(self, codec_name):

        try:
            codec = Codec(codec_name, "w")
        except UnknownCodecError:
            raise SkipTest()

        container = av.open(fate_suite("h264/interlaced_crop.mp4"))
        video_stream = container.streams.video[0]

        width = 640
        height = 480

        ctx = codec.create()

        pix_fmt = ctx.codec.video_formats[0].name

        ctx.width = width
        ctx.height = height
        ctx.time_base = video_stream.codec_context.time_base
        ctx.pix_fmt = pix_fmt
        ctx.open()

        frame_count = 1
        path_list = []
        for frame in iter_frames(container, video_stream):

            new_frame = frame.reformat(width, height, pix_fmt)
            new_packets = ctx.encode(new_frame)

            self.assertEqual(len(new_packets), 1)
            new_packet = new_packets[0]

            path = self.sandboxed("%s/encoder.%04d.%s" % (
                codec_name,
                frame_count,
                codec_name if codec_name != "mjpeg" else "jpg",
            ))
            path_list.append(path)
            with open(path, "wb") as f:
                f.write(new_packet)
            frame_count += 1
            if frame_count > 5:
                break

        ctx = av.Codec(codec_name, "r").create()

        for path in path_list:
            with open(path, "rb") as f:
                size = os.fstat(f.fileno()).st_size
                packet = Packet(size)
                size = f.readinto(packet)
                frame = ctx.decode(packet)[0]
                self.assertEqual(frame.width, width)
                self.assertEqual(frame.height, height)
                self.assertEqual(frame.format.name, pix_fmt)
Пример #3
0
    def test_codec_tag(self):
        ctx = Codec("mpeg4", "w").create()
        self.assertEqual(ctx.codec_tag, "\x00\x00\x00\x00")
        ctx.codec_tag = "xvid"
        self.assertEqual(ctx.codec_tag, "xvid")

        # wrong length
        with self.assertRaises(ValueError) as cm:
            ctx.codec_tag = "bob"
        self.assertEqual(str(cm.exception),
                         "Codec tag should be a 4 character string.")

        # wrong type
        with self.assertRaises(ValueError) as cm:
            ctx.codec_tag = 123
        self.assertEqual(str(cm.exception),
                         "Codec tag should be a 4 character string.")

        with av.open(fate_suite("h264/interlaced_crop.mp4")) as container:
            self.assertEqual(container.streams[0].codec_tag, "avc1")
Пример #4
0
    def _assert_parse(self, codec_name, path):

        fh = av.open(path)
        packets = []
        for packet in fh.demux(video=0):
            packets.append(packet)

        full_source = b"".join(bytes(p) for p in packets)

        for size in 1024, 8192, 65535:

            ctx = Codec(codec_name).create()
            packets = []

            for i in range(0, len(full_source), size):
                block = full_source[i:i + size]
                packets.extend(ctx.parse(block))
            packets.extend(ctx.parse())

            parsed_source = b"".join(bytes(p) for p in packets)
            self.assertEqual(len(parsed_source), len(full_source))
            self.assertEqual(full_source, parsed_source)
Пример #5
0
    def test_codec_opus_decoder(self):
        c = Codec("opus")

        self.assertEqual(c.name, "opus")
        self.assertEqual(c.long_name, "Opus")
        self.assertEqual(c.type, "audio")
        self.assertTrue(c.is_decoder)
        self.assertFalse(c.is_encoder)

        # audio
        self.assertIsNone(c.audio_formats)
        self.assertIsNone(c.audio_rates)

        # video
        self.assertIsNone(c.video_formats)
        self.assertIsNone(c.frame_rates)
Пример #6
0
    def test_codec_opus_encoder(self):
        c = Codec("opus", "w")
        self.assertIn(c.name, ("opus", "libopus"))
        self.assertIn(c.long_name, ("Opus", "libopus Opus"))
        self.assertEqual(c.type, "audio")
        self.assertTrue(c.is_encoder)
        self.assertFalse(c.is_decoder)

        # audio
        formats = c.audio_formats
        self.assertTrue(formats)
        self.assertIsInstance(formats[0], AudioFormat)
        self.assertTrue(any(f.name in ["flt", "fltp"] for f in formats))

        self.assertIsNotNone(c.audio_rates)
        self.assertIn(48000, c.audio_rates)

        # video
        self.assertIsNone(c.video_formats)
        self.assertIsNone(c.frame_rates)
Пример #7
0
    def test_codec_mpeg4_encoder(self):
        c = Codec("mpeg4", "w")
        self.assertEqual(c.name, "mpeg4")
        self.assertEqual(c.long_name, "MPEG-4 part 2")
        self.assertEqual(c.type, "video")
        self.assertIn(c.id, (12, 13))
        self.assertTrue(c.is_encoder)
        self.assertFalse(c.is_decoder)

        # audio
        self.assertIsNone(c.audio_formats)
        self.assertIsNone(c.audio_rates)

        # video
        formats = c.video_formats
        self.assertTrue(formats)
        self.assertIsInstance(formats[0], VideoFormat)
        self.assertTrue(any(f.name == "yuv420p" for f in formats))

        self.assertIsNone(c.frame_rates)
Пример #8
0
    def audio_encoding(self, codec_name):

        try:
            codec = Codec(codec_name, "w")
        except UnknownCodecError:
            raise SkipTest()

        ctx = codec.create()
        if ctx.codec.experimental:
            raise SkipTest()

        sample_fmt = ctx.codec.audio_formats[-1].name
        sample_rate = 48000
        channel_layout = "stereo"
        channels = 2

        ctx.time_base = Fraction(1) / sample_rate
        ctx.sample_rate = sample_rate
        ctx.format = sample_fmt
        ctx.layout = channel_layout
        ctx.channels = channels

        ctx.open()

        resampler = AudioResampler(sample_fmt, channel_layout, sample_rate)

        container = av.open(
            fate_suite("audio-reference/chorusnoise_2ch_44kHz_s16.wav"))
        audio_stream = container.streams.audio[0]

        path = self.sandboxed("encoder.%s" % codec_name)

        samples = 0
        packet_sizes = []

        with open(path, "wb") as f:
            for frame in iter_frames(container, audio_stream):

                resampled_frames = resampler.resample(frame)
                for resampled_frame in resampled_frames:
                    samples += resampled_frame.samples

                    for packet in ctx.encode(resampled_frame):
                        packet_sizes.append(packet.size)
                        f.write(packet)

            for packet in ctx.encode(None):
                packet_sizes.append(packet.size)
                f.write(packet)

        ctx = Codec(codec_name, "r").create()
        ctx.sample_rate = sample_rate
        ctx.format = sample_fmt
        ctx.layout = channel_layout
        ctx.channels = channels
        ctx.open()

        result_samples = 0

        # should have more asserts but not sure what to check
        # libav and ffmpeg give different results
        # so can really use checksums
        for frame in iter_raw_frames(path, packet_sizes, ctx):
            result_samples += frame.samples
            self.assertEqual(frame.rate, sample_rate)
            self.assertEqual(len(frame.layout.channels), channels)
Пример #9
0
    def video_encoding(self, codec_name, options={}, codec_tag=None):

        try:
            codec = Codec(codec_name, "w")
        except UnknownCodecError:
            raise SkipTest()

        container = av.open(fate_suite("h264/interlaced_crop.mp4"))
        video_stream = container.streams.video[0]

        pix_fmt = options.pop("pix_fmt", "yuv420p")
        width = options.pop("width", 640)
        height = options.pop("height", 480)
        max_frames = options.pop("max_frames", 50)
        time_base = options.pop("time_base",
                                video_stream.codec_context.time_base)

        ctx = codec.create()
        ctx.width = width
        ctx.height = height
        ctx.time_base = time_base
        ctx.framerate = 1 / ctx.time_base
        ctx.pix_fmt = pix_fmt
        ctx.options = options  # TODO
        if codec_tag:
            ctx.codec_tag = codec_tag
        ctx.open()

        path = self.sandboxed("encoder.%s" % codec_name)
        packet_sizes = []
        frame_count = 0

        with open(path, "wb") as f:

            for frame in iter_frames(container, video_stream):

                new_frame = frame.reformat(width, height, pix_fmt)

                # reset the picture type
                new_frame.pict_type = PictureType.NONE

                for packet in ctx.encode(new_frame):
                    packet_sizes.append(packet.size)
                    f.write(packet)

                frame_count += 1
                if frame_count >= max_frames:
                    break

            for packet in ctx.encode(None):
                packet_sizes.append(packet.size)
                f.write(packet)

        dec_codec_name = codec_name
        if codec_name == "libx264":
            dec_codec_name = "h264"

        ctx = av.Codec(dec_codec_name, "r").create()
        ctx.open()

        decoded_frame_count = 0
        for frame in iter_raw_frames(path, packet_sizes, ctx):
            decoded_frame_count += 1
            self.assertEqual(frame.width, width)
            self.assertEqual(frame.height, height)
            self.assertEqual(frame.format.name, pix_fmt)

        self.assertEqual(frame_count, decoded_frame_count)
Пример #10
0
 def test_skip_frame_default(self):
     ctx = Codec('png', 'w').create()
     self.assertEqual(ctx.skip_frame.name, 'DEFAULT')
Пример #11
0
    def audio_encoding(self, codec_name):

        try:
            codec = Codec(codec_name, 'w')
        except UnknownCodecError:
            raise SkipTest()

        ctx = codec.create()
        if ctx.codec.experimental:
            raise SkipTest()

        sample_fmt = ctx.codec.audio_formats[-1].name
        sample_rate = 48000
        channel_layout = "stereo"
        channels = 2

        ctx.time_base = Fraction(1) / sample_rate
        ctx.sample_rate = sample_rate
        ctx.format = sample_fmt
        ctx.layout = channel_layout
        ctx.channels = channels

        ctx.open()

        resampler = AudioResampler(sample_fmt, channel_layout, sample_rate)

        container = av.open(
            fate_suite('audio-reference/chorusnoise_2ch_44kHz_s16.wav'))
        audio_stream = container.streams.audio[0]

        path = self.sandboxed('encoder.%s' % codec_name)

        samples = 0
        packet_sizes = []

        with open(path, 'wb') as f:
            for frame in iter_frames(container, audio_stream):

                # We need to let the encoder retime.
                frame.pts = None
                """
                bad_resampler = AudioResampler(sample_fmt, "mono", sample_rate)
                bad_frame = bad_resampler.resample(frame)
                with self.assertRaises(ValueError):
                    next(encoder.encode(bad_frame))

                bad_resampler = AudioResampler(sample_fmt, channel_layout, 3000)
                bad_frame = bad_resampler.resample(frame)

                with self.assertRaises(ValueError):
                    next(encoder.encode(bad_frame))

                bad_resampler = AudioResampler('u8', channel_layout, 3000)
                bad_frame = bad_resampler.resample(frame)

                with self.assertRaises(ValueError):
                    next(encoder.encode(bad_frame))
                """

                resampled_frame = resampler.resample(frame)
                samples += resampled_frame.samples

                for packet in ctx.encode(resampled_frame):
                    # bytearray because python can
                    # freaks out if the first byte is NULL
                    f.write(bytearray(packet))
                    packet_sizes.append(packet.size)

            for packet in ctx.encode(None):
                packet_sizes.append(packet.size)
                f.write(bytearray(packet))

        ctx = Codec(codec_name, 'r').create()
        ctx.time_base = Fraction(1) / sample_rate
        ctx.sample_rate = sample_rate
        ctx.format = sample_fmt
        ctx.layout = channel_layout
        ctx.channels = channels
        ctx.open()

        result_samples = 0

        # should have more asserts but not sure what to check
        # libav and ffmpeg give different results
        # so can really use checksums
        for frame in iter_raw_frames(path, packet_sizes, ctx):
            result_samples += frame.samples
            self.assertEqual(frame.rate, sample_rate)
            self.assertEqual(len(frame.layout.channels), channels)
Пример #12
0
    def audio_encoding(self, codec_name):

        try:
            codec = Codec(codec_name, 'w')
        except UnknownCodecError:
            raise SkipTest()

        ctx = codec.create()
        if ctx.codec.experimental:
            raise SkipTest()

        sample_fmt = ctx.codec.audio_formats[-1].name
        sample_rate = 48000
        channel_layout = "stereo"
        channels = 2

        ctx.time_base = Fraction(1) / sample_rate
        ctx.sample_rate = sample_rate
        ctx.format = sample_fmt
        ctx.layout = channel_layout
        ctx.channels = channels

        ctx.open()

        resampler = AudioResampler(sample_fmt, channel_layout, sample_rate)

        container = av.open(fate_suite('audio-reference/chorusnoise_2ch_44kHz_s16.wav'))
        audio_stream = container.streams.audio[0]

        path = self.sandboxed('encoder.%s' % codec_name)

        samples = 0
        packet_sizes = []

        with open(path, 'wb') as f:
            for frame in iter_frames(container, audio_stream):

                # We need to let the encoder retime.
                frame.pts = None

                """
                bad_resampler = AudioResampler(sample_fmt, "mono", sample_rate)
                bad_frame = bad_resampler.resample(frame)
                with self.assertRaises(ValueError):
                    next(encoder.encode(bad_frame))

                bad_resampler = AudioResampler(sample_fmt, channel_layout, 3000)
                bad_frame = bad_resampler.resample(frame)

                with self.assertRaises(ValueError):
                    next(encoder.encode(bad_frame))

                bad_resampler = AudioResampler('u8', channel_layout, 3000)
                bad_frame = bad_resampler.resample(frame)

                with self.assertRaises(ValueError):
                    next(encoder.encode(bad_frame))
                """

                resampled_frame = resampler.resample(frame)
                samples += resampled_frame.samples

                for packet in ctx.encode(resampled_frame):
                    # bytearray because python can
                    # freaks out if the first byte is NULL
                    f.write(bytearray(packet))
                    packet_sizes.append(packet.size)

            for packet in ctx.encode(None):
                packet_sizes.append(packet.size)
                f.write(bytearray(packet))

        ctx = Codec(codec_name, 'r').create()
        ctx.time_base = Fraction(1) / sample_rate
        ctx.sample_rate = sample_rate
        ctx.format = sample_fmt
        ctx.layout = channel_layout
        ctx.channels = channels
        ctx.open()

        result_samples = 0

        # should have more asserts but not sure what to check
        # libav and ffmpeg give different results
        # so can really use checksums
        for frame in iter_raw_frames(path, packet_sizes, ctx):
            result_samples += frame.samples
            self.assertEqual(frame.rate, sample_rate)
            self.assertEqual(len(frame.layout.channels), channels)
Пример #13
0
 def test_codec_bogus(self):
     with self.assertRaises(UnknownCodecError):
         Codec("bogus123")
     with self.assertRaises(UnknownCodecError):
         Codec("bogus123", "w")
Пример #14
0
import unittest

from av import AudioFormat, Codec, VideoFormat, codecs_available
from av.codec.codec import UnknownCodecError

from .common import TestCase


# some older ffmpeg versions have no native opus encoder
try:
    opus_c = Codec("opus", "w")
    opus_encoder_missing = False
except UnknownCodecError:
    opus_encoder_missing = True


class TestCodecs(TestCase):
    def test_codec_bogus(self):
        with self.assertRaises(UnknownCodecError):
            Codec("bogus123")
        with self.assertRaises(UnknownCodecError):
            Codec("bogus123", "w")

    def test_codec_mpeg4_decoder(self):
        c = Codec("mpeg4")

        self.assertEqual(c.name, "mpeg4")
        self.assertEqual(c.long_name, "MPEG-4 part 2")
        self.assertEqual(c.type, "video")
        self.assertIn(c.id, (12, 13))
        self.assertTrue(c.is_decoder)
Пример #15
0
 def test_skip_frame_default(self):
     ctx = Codec("png", "w").create()
     self.assertEqual(ctx.skip_frame.name, "DEFAULT")
Пример #16
0
    def video_encoding(self, codec_name, options={}):

        try:
            codec = Codec(codec_name, 'w')
        except UnknownCodecError:
            raise SkipTest()

        container = av.open(fate_suite('h264/interlaced_crop.mp4'))
        video_stream = container.streams.video[0]

        pix_fmt = options.pop('pix_fmt', 'yuv420p')
        width = options.pop('width', 640)
        height = options.pop('height', 480)
        max_frames = options.pop('max_frames', 50)
        time_base = options.pop('time_base',
                                video_stream.codec_context.time_base)

        ctx = codec.create()
        ctx.width = width
        ctx.height = height
        ctx.time_base = time_base
        ctx.framerate = 1 / ctx.time_base
        ctx.pix_fmt = pix_fmt
        ctx.options = options  # TODO
        ctx.open()

        path = self.sandboxed('encoder.%s' % codec_name)
        packet_sizes = []
        frame_count = 0

        with open(path, 'wb') as f:

            for frame in iter_frames(container, video_stream):
                """
                bad_frame = frame.reformat(width, 100, pix_fmt)
                with self.assertRaises(ValueError):
                    ctx.encode(bad_frame)

                bad_frame = frame.reformat(100, height, pix_fmt)
                with self.assertRaises(ValueError):
                    ctx.encode(bad_frame)

                bad_frame = frame.reformat(width, height, "rgb24")
                with self.assertRaises(ValueError):
                    ctx.encode(bad_frame)
                """

                if frame:
                    frame_count += 1

                new_frame = frame.reformat(width, height,
                                           pix_fmt) if frame else None
                for packet in ctx.encode(new_frame):
                    packet_sizes.append(packet.size)
                    f.write(packet)

                if frame_count >= max_frames:
                    break

            for packet in ctx.encode(None):
                packet_sizes.append(packet.size)
                f.write(packet)

        dec_codec_name = codec_name
        if codec_name == 'libx264':
            dec_codec_name = 'h264'

        ctx = av.Codec(dec_codec_name, 'r').create()
        ctx.open()

        decoded_frame_count = 0
        for frame in iter_raw_frames(path, packet_sizes, ctx):
            decoded_frame_count += 1
            self.assertEqual(frame.width, width)
            self.assertEqual(frame.height, height)
            self.assertEqual(frame.format.name, pix_fmt)

        self.assertEqual(frame_count, decoded_frame_count)
Пример #17
0
    def video_encoding(self, codec_name, options={}):

        try:
            codec = Codec(codec_name, 'w')
        except UnknownCodecError:
            raise SkipTest()

        container = av.open(fate_suite('h264/interlaced_crop.mp4'))
        video_stream = container.streams.video[0]

        pix_fmt = options.pop('pix_fmt', 'yuv420p')
        width = options.pop('width', 640)
        height = options.pop('height', 480)
        max_frames = options.pop('max_frames', 50)
        time_base = options.pop('time_base', video_stream.codec_context.time_base)

        ctx = codec.create()
        ctx.width = width
        ctx.height = height
        ctx.time_base = time_base
        ctx.framerate = 1 / ctx.time_base
        ctx.pix_fmt = pix_fmt
        ctx.options = options  # TODO
        ctx.open()

        path = self.sandboxed('encoder.%s' % codec_name)
        packet_sizes = []
        frame_count = 0

        with open(path, 'wb') as f:

            for frame in iter_frames(container, video_stream):

                """
                bad_frame = frame.reformat(width, 100, pix_fmt)
                with self.assertRaises(ValueError):
                    ctx.encode(bad_frame)

                bad_frame = frame.reformat(100, height, pix_fmt)
                with self.assertRaises(ValueError):
                    ctx.encode(bad_frame)

                bad_frame = frame.reformat(width, height, "rgb24")
                with self.assertRaises(ValueError):
                    ctx.encode(bad_frame)
                """

                if frame:
                    frame_count += 1

                new_frame = frame.reformat(width, height, pix_fmt) if frame else None
                for packet in ctx.encode(new_frame):
                    packet_sizes.append(packet.size)
                    f.write(packet)

                if frame_count >= max_frames:
                    break

            for packet in ctx.encode(None):
                packet_sizes.append(packet.size)
                f.write(packet)

        dec_codec_name = codec_name
        if codec_name == 'libx264':
            dec_codec_name = 'h264'

        ctx = av.Codec(dec_codec_name, 'r').create()
        ctx.open()

        decoded_frame_count = 0
        for frame in iter_raw_frames(path, packet_sizes, ctx):
            decoded_frame_count += 1
            self.assertEqual(frame.width, width)
            self.assertEqual(frame.height, height)
            self.assertEqual(frame.format.name, pix_fmt)

        self.assertEqual(frame_count, decoded_frame_count)