Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding raw H264 frame from subprocess stdout #578

Closed
fabriciopk opened this issue Dec 9, 2019 · 1 comment
Closed

Decoding raw H264 frame from subprocess stdout #578

fabriciopk opened this issue Dec 9, 2019 · 1 comment

Comments

@fabriciopk
Copy link

fabriciopk commented Dec 9, 2019

Overview

I have been working to get PyAV to decode raw h264 output from adb(android debug bridge) + screenrecord open as a python subprocess. This code is meant to be used to stream android screen and it's is based on the fallowing ffmpeg command:

adb exec-out screenrecord --output-format h264 --size 640x310 - | ffmpeg -i - -f sdl -

The fallowing python code was used. The main idea is to read Popen stdout and provide to pyAV decode the h264 frame.

import av
import subprocess as sp
import logging


adbCmd = ['adb', 'exec-out', 'screenrecord', '--output-format=h264', '-']
stream = sp.Popen(adbCmd, stdout = sp.PIPE, universal_newlines = True, errors='replace')

class H264Decoder:
    def __init__(self):
        self.codec = av.CodecContext.create("h264", "r")

    def decode(self, encoded_frame):
        try:
            packet = av.Packet(encoded_frame)
            # packet.pts = encoded_frame.timestamp
            packet.time_base = VIDEO_TIME_BASE
            frames = self.codec.decode(packet)
        except av.AVError as e:
            logger.warning("failed to decode, skipping package: " + str(e))
            return []

        return frames


while True:
  line = stream.stdout.readline(4096)
  decoder = H264Decoder()
  decoder.decode(u' '.join(line).encode('utf-8').strip())
  if not line:
    break

Actual behavior

Traceback:

No start code is found.
Error splitting the input into NAL units.
failed to decode, skipping package: [Errno 1094995529] Invalid data found when processing input (16: h264)
line

Investigation

I got this code working using c++ and libavcodec, where the main idea is to decode raw h264 output from adb subprocess and save each frame as ppg image.
gist.github.com/fabriciopk/6f583f079bd929ccc708aa3d3cb37b59

@fabriciopk fabriciopk changed the title How do I FOO? Decoding raw H264 frame from subprocess stdout Dec 9, 2019
@jlaine
Copy link
Member

jlaine commented Apr 29, 2020

This works fine for me:

adb exec-out screenrecord --output-format=h264 - | python test.py

With test.py:

import subprocess
import sys

import av


class Wrapper:
    """
    Wrapper which only exposes the `read` method to avoid PyAV
    trying to use `seek`.
    """

    name = "<wrapped>"

    def __init__(self, fh):
        self._fh = fh

    def read(self, buf_size):
        return self._fh.read(buf_size)


wrapper = Wrapper(sys.stdin.buffer)
with av.open(wrapper, "r") as container:
    for frame in container.decode():
        print(frame)

@jlaine jlaine closed this as completed Apr 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants