github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/jpeg/start_of_frame1.go (about)

     1  package jpeg
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  // StartOfFrame1 is a SOF1 marker.
     8  type StartOfFrame1 struct {
     9  	Type                   uint8
    10  	Width                  int
    11  	Height                 int
    12  	QuantizationTableCount uint8 // write only
    13  }
    14  
    15  // Unmarshal decodes the marker.
    16  func (m *StartOfFrame1) Unmarshal(buf []byte) error {
    17  	if len(buf) != 15 {
    18  		return fmt.Errorf("unsupported SOF size of %d", len(buf))
    19  	}
    20  
    21  	precision := buf[0]
    22  	if precision != 8 {
    23  		return fmt.Errorf("precision %d is not supported", precision)
    24  	}
    25  
    26  	m.Height = int(buf[1])<<8 | int(buf[2])
    27  	m.Width = int(buf[3])<<8 | int(buf[4])
    28  
    29  	components := buf[5]
    30  	if components != 3 {
    31  		return fmt.Errorf("number of components = %d is not supported", components)
    32  	}
    33  
    34  	samp0 := buf[7]
    35  	switch samp0 {
    36  	case 0x21:
    37  		m.Type = 0
    38  
    39  	case 0x22:
    40  		m.Type = 1
    41  
    42  	default:
    43  		return fmt.Errorf("samp0 %x is not supported", samp0)
    44  	}
    45  
    46  	samp1 := buf[10]
    47  	if samp1 != 0x11 {
    48  		return fmt.Errorf("samp1 %x is not supported", samp1)
    49  	}
    50  
    51  	samp2 := buf[13]
    52  	if samp2 != 0x11 {
    53  		return fmt.Errorf("samp2 %x is not supported", samp2)
    54  	}
    55  
    56  	return nil
    57  }
    58  
    59  // Marshal encodes the marker.
    60  func (m StartOfFrame1) Marshal(buf []byte) []byte {
    61  	buf = append(buf, []byte{0xFF, MarkerStartOfFrame1}...)
    62  	buf = append(buf, []byte{0, 17}...)                               // length
    63  	buf = append(buf, []byte{8}...)                                   // precision
    64  	buf = append(buf, []byte{byte(m.Height >> 8), byte(m.Height)}...) // height
    65  	buf = append(buf, []byte{byte(m.Width >> 8), byte(m.Width)}...)   // width
    66  	buf = append(buf, []byte{3}...)                                   // components
    67  	if (m.Type & 0x3f) == 0 {                                         // component 0
    68  		buf = append(buf, []byte{0x00, 0x21, 0}...)
    69  	} else {
    70  		buf = append(buf, []byte{0x00, 0x22, 0}...)
    71  	}
    72  
    73  	var secondQuantizationTable byte
    74  	if m.QuantizationTableCount == 2 {
    75  		secondQuantizationTable = 1
    76  	} else {
    77  		secondQuantizationTable = 0
    78  	}
    79  
    80  	buf = append(buf, []byte{1, 0x11, secondQuantizationTable}...) // component 1
    81  	buf = append(buf, []byte{2, 0x11, secondQuantizationTable}...) // component 2
    82  	return buf
    83  }