I'm gonna stop writing about actions in PDFs to begin with the filters that can be applied to the stream objects. An stream object is composed by a dictionary followed by the real content between the words stream and endstream. Within this dictionary are defined the stream properties like size, filters to apply in order to decode/decompress it or the file name in the case of the stream is located in an external file.
As you suppose, a way to hide information in a PDF file is applying to it one or more filters in order to avoid identifying it easily and putting it hard to extract the real content. In fact this is an usual technique in most of the malicious files that try to exploit some of the latest vulnerabilities.
There are two types of filters: the ASCII filters that decode ASCII text and obtain binary data, and decompression filters, which decode data compressed with some algorithm. The more usual filter is FlateDecode that uses the zlib/deflate method to obtain the compressed data. Normally we find this filter alone, I mean without another chained filter to encode its input/output. If we have a filter of this type first we must isolate the encoded data: we have to extract the characters between the words stream and endstream without taking the newline and carriage return characters next to these tags. After this we only need the zlib library and your chosen programming language to make a simple script to decompress the stream and obtain the content. In Python we can make it with a few lines:
Normally filters aren't used to hide information but they are used in normal PDF files to decrement their size or avoid binary characters, for example. There are more filters that you can find explained in the section 3.3 of the PDF specification, for instance the 1.7.
If you are boring and you want to practise it you can download this file and check it out! ;)